Commit ad331e4e authored by nanahira's avatar nanahira

just wait for ssh

parent a05c64e5
......@@ -3214,6 +3214,11 @@
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
},
"events": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
......@@ -5608,8 +5613,7 @@
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
"dev": true
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
},
"p-limit": {
"version": "2.3.0",
......@@ -5627,6 +5631,23 @@
"p-limit": "^2.2.0"
}
},
"p-queue": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
"integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
"requires": {
"eventemitter3": "^4.0.4",
"p-timeout": "^3.2.0"
}
},
"p-timeout": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
"integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
"requires": {
"p-finally": "^1.0.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
......
......@@ -13,6 +13,7 @@ import * as IP from 'ip';
import * as _ from 'underscore';
import { AppLogger } from './logger.service';
import { User } from './entities/User';
import PQueue from 'p-queue';
const validDestinations = ['chnroute', 'all'];
......@@ -30,6 +31,7 @@ export class AppService {
routers: Router[];
gatewayGroups: GatewayGroup[];
railgunRules: RailgunRule[];
syncQueue: PQueue;
constructor(
@InjectConnection('railgun')
private db: Connection,
......@@ -41,17 +43,40 @@ export class AppService {
this.routers = this.configService.get('routers');
this.gatewayGroups = this.configService.get('gatewayGroups');
this.railgunRules = this.configService.get('railgunRules');
this.syncQueue = new PQueue({ concurrency: 1 });
this.addSyncTask();
}
private async syncRouter(router: Router, users: User[]) {
const ipsetData = this.getIpsetOfRouter(router, users);
// replace this part with real ssh things
console.log(router.name);
console.log(ipsetData);
}
private async sync() {
const users = await this.db.getRepository(User).find();
await Promise.all(
this.routers.map((router) => this.syncRouter(router, users)),
);
}
private async addSyncTask() {
return await this.syncQueue.add(async () => {
this.sync();
});
}
private subnetsContain(subnets: string[], ip) {
return subnets.some((subnet) => IP.cidrSubnet(subnet).contains(ip));
}
private isGatewayAllowed(ip: string, gateway: Gateway) {
if (!gateway.hidden) {
// 允许自己的网关的所有IP
const router = gateway.routerInfo;
if (router && this.subnetsContain(router.subnets, ip)) {
return true;
}
private isGatewayAllowed(ip: string, gateway: Gateway, localOnly?: boolean) {
if (gateway.hidden) {
return false;
}
// 允许自己的网关的所有IP
const router = gateway.routerInfo;
if (router && this.subnetsContain(router.subnets, ip)) {
return true;
}
if (localOnly) {
return false;
}
// 在 railgun enterprise 表中有的IP
return this.railgunRules.some((rule) => {
......@@ -78,7 +103,7 @@ export class AppService {
}
private getAllSuitableGateways(ip: string) {
return this.gateways.filter((gateway) =>
this.isGatewayAllowed(ip, gateway),
this.isGatewayAllowed(ip, gateway, false),
);
}
private getGatewayDisplayData(
......@@ -117,7 +142,7 @@ export class AppService {
async getClientData(rawAddress: string) {
const ip = this.sortAddress(rawAddress);
const displayGateways = this.gateways
.filter((gateway) => this.isGatewayAllowed(ip, gateway))
.filter((gateway) => this.isGatewayAllowed(ip, gateway, false))
.map((gateway) => this.getGatewayDisplayData(gateway, ip));
const displayGroups = this.gatewayGroups
.filter((group) => this.isGatewayGroupAllowed(ip, group))
......@@ -129,17 +154,91 @@ export class AppService {
};
}
private checkId(id: number, ip: string) {
private checkId(id: number, ip: string, localOnly: boolean) {
if (!id) {
return true;
}
if (id > 20000) {
if (id > 20000 && !localOnly) {
const gatewayGroup = this.gatewayGroups.find((g) => g.id === id);
return gatewayGroup && this.isGatewayGroupAllowed(ip, gatewayGroup);
} else {
const gateway = this.gateways.find((gw) => gw.id === id);
return this.isGatewayAllowed(ip, gateway);
return gateway && this.isGatewayAllowed(ip, gateway, localOnly);
}
}
private getGatewayOrGroupFromId(id: number) {
if (id > 20000) {
const gatewayGroup = this.gatewayGroups.find((g) => g.id === id);
return gatewayGroup;
} else {
const gateway = this.gateways.find((gw) => gw.id === id);
return gateway;
}
}
getIpsetNamesOfRouter(router: Router) {
const ipsets: string[] = [];
for (const destination of validDestinations) {
const selfGateways = this.gateways.filter(
(gateway) => router.name === gateway.router,
);
for (const gateway of selfGateways) {
ipsets.push(`u_${gateway.isp}_${destination}`);
}
const otherRouters = this.routers.filter((r) => r !== router);
for (const r of otherRouters) {
ipsets.push(`u_${r.name.replace(/-/g, '-')}_${destination}`);
}
for (const group of this.gatewayGroups) {
ipsets.push(`u_${group.name}_${destination}`);
}
}
return ipsets;
}
getIpsetOfRouter(router: Router, users: User[]) {
const lines: string[] = this.getIpsetNamesOfRouter(router).map(
(setname) => `flush ${setname}`,
);
for (const group of this.gatewayGroups) {
const matchUsers = users.filter(
(user) =>
user.remoteGatewayId === group.id &&
this.isGatewayGroupAllowed(user.ip, group),
);
for (const user of matchUsers) {
lines.push(`add u_${group.name.replace(/-/g, '_')}_${user.destination} ${user.ip}`);
}
}
for (const gateway of this.gateways) {
const matchUsers = users.filter(
(user) =>
user.remoteGatewayId === gateway.id &&
this.isGatewayAllowed(user.ip, gateway, false),
);
for (const user of matchUsers) {
if (gateway.routerInfo === router) {
lines.push(`add u_${gateway.isp}_${user.destination} ${user.ip}`);
} else {
lines.push(
`add u_${gateway.routerInfo.name.replace(/-/g, '_')}_${user.destination} ${user.ip}`,
);
}
}
}
const selfGateways = this.gateways.filter(
(gateway) => router.name === gateway.router,
);
for (const gateway of selfGateways) {
const setName = `u_${gateway.isp}_all`;
const matchUsers = users.filter(
(user) =>
user.localGatewayId === gateway.id &&
this.isGatewayAllowed(user.ip, gateway, true),
);
for (const user of matchUsers) {
lines.push(`add ${setName} ${user.ip}`);
}
}
return lines.join('\n');
}
async postData(
rawAddress: string,
......@@ -157,8 +256,8 @@ export class AppService {
};
}
if (
!this.checkId(remoteGatewayId, ip) ||
!this.checkId(localGatewayId, ip)
!this.checkId(remoteGatewayId, ip, false) ||
!this.checkId(localGatewayId, ip, true)
) {
return { success: false, statusCode: 404, message: 'invalid gateway' };
}
......@@ -166,6 +265,7 @@ export class AppService {
user.remoteGatewayId = remoteGatewayId || null;
user.localGatewayId = localGatewayId || null;
await this.db.getRepository(User).save(user);
this.addSyncTask();
return { success: true, statusCode: 200, message: 'success' };
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment