Commit 4826c896 authored by 神楽坂玲奈's avatar 神楽坂玲奈

subnet

parent c2bd355e
...@@ -6,8 +6,8 @@ import YAML from 'yaml'; ...@@ -6,8 +6,8 @@ import YAML from 'yaml';
import _ from 'lodash'; import _ from 'lodash';
import child_process from 'child_process'; import child_process from 'child_process';
import assert from 'assert'; import assert from 'assert';
import ip from "ip"; import ip from 'ip';
import { promises as dns } from "dns"; import { promises as dns } from 'dns';
class InventoryBuilder { class InventoryBuilder {
hosts: { [key: string]: any }; hosts: { [key: string]: any };
...@@ -24,17 +24,17 @@ class InventoryBuilder { ...@@ -24,17 +24,17 @@ class InventoryBuilder {
if (this.resolveCache.has(domain)) { if (this.resolveCache.has(domain)) {
return this.resolveCache.get(domain); return this.resolveCache.get(domain);
} }
const rrtype = (domain.includes("-v6") || ipv6) ? "AAAA" : "A"; const rrtype = (domain.includes('-v6') || ipv6) ? 'AAAA' : 'A';
let resolvedIP: string; let resolvedIP: string;
while (true) { while (true) {
try { try {
[ resolvedIP ] = (await this.resolver.resolve(domain, rrtype)) as string[]; [resolvedIP] = (await this.resolver.resolve(domain, rrtype)) as string[];
break; break;
} catch (e) { } catch (e) {
console.log(`${domain} => FAIL: ${e.toString()}`); console.log(`${domain} => FAIL: ${e.toString()}`);
} }
} }
if (rrtype === "AAAA") { if (rrtype === 'AAAA') {
resolvedIP = `[${resolvedIP}]`; resolvedIP = `[${resolvedIP}]`;
} }
console.log(`${domain} => ${resolvedIP}`); console.log(`${domain} => ${resolvedIP}`);
...@@ -57,7 +57,7 @@ class InventoryBuilder { ...@@ -57,7 +57,7 @@ class InventoryBuilder {
async loadGateways() { async loadGateways() {
const gateways = await this.load('gateways2'); const gateways = await this.load('gateways2');
for (let gateway of gateways) { for (let gateway of gateways) {
gateway.isCN = this.hosts[gateway.router] && this.hosts[gateway.router].location.startsWith("CN"); gateway.isCN = this.hosts[gateway.router] && this.hosts[gateway.router].location.startsWith('CN');
if (gateway.mark) { if (gateway.mark) {
gateway.selectionMark = gateway.mark + 50; gateway.selectionMark = gateway.mark + 50;
} else { } else {
...@@ -74,11 +74,20 @@ class InventoryBuilder { ...@@ -74,11 +74,20 @@ class InventoryBuilder {
//console.log(this.gateways); //console.log(this.gateways);
this.connections = _.intersection(Object.keys(this.hosts), Object.keys(_.find(this.hosts))); this.connections = _.intersection(Object.keys(this.hosts), Object.keys(_.find(this.hosts)));
const subnets = await this.load('subnets');
for (const [name, router] of Object.entries(this.hosts)) {
router.lanInterfaces = subnets
.filter((subnet) => subnet.router === name)
.map((subnet) => subnet.interface)
.filter((i) => i);
router.subnets = subnets.filter((subnet) => subnet.router === name).map((subnet) => subnet.subnet);
}
for (const host of Object.values(this.hosts)) { for (const host of Object.values(this.hosts)) {
host.wgPublickey = await this.wgPublickey(host.wgPrivateKey); host.wgPublickey = await this.wgPublickey(host.wgPrivateKey);
} }
// console.log(Object.values(this.hosts)); // console.log(Object.values(this.hosts));
const rawHosts = await Promise.all(Object.values(this.hosts).map(async(h) => [h.name, await this.host_vars(h)])); const rawHosts = await Promise.all(Object.values(this.hosts).map(async (h) => [h.name, await this.host_vars(h)]));
const hosts = Object.fromEntries(rawHosts); const hosts = Object.fromEntries(rawHosts);
// console.log(hosts); // console.log(hosts);
const vars = await this.loadUtilities(); const vars = await this.loadUtilities();
...@@ -89,18 +98,21 @@ class InventoryBuilder { ...@@ -89,18 +98,21 @@ class InventoryBuilder {
return [`switch-${rh[0]}`, hostVars]; return [`switch-${rh[0]}`, hostVars];
}); });
const switchHosts = Object.fromEntries(rawHostsForSwitch); const switchHosts = Object.fromEntries(rawHostsForSwitch);
const result = YAML.stringify({ wg: { hosts, vars }, switch: { hosts: switchHosts, vars: JSON.parse(JSON.stringify(vars)) } }); const result = YAML.stringify({
wg: { hosts, vars },
switch: { hosts: switchHosts, vars: JSON.parse(JSON.stringify(vars)) }
});
return fs.promises.writeFile('result/inventory.yaml', result); return fs.promises.writeFile('result/inventory.yaml', result);
} }
async loadUtilities() { async loadUtilities() {
const raw_utility = _.keyBy(await this.load('configurations'), 'key'); const raw_utility = _.keyBy(await this.load('configurations'), 'key');
this.routeLists = YAML.parse(fs.readFileSync(path.join('lists', 'result.yaml'), "utf8")); this.routeLists = YAML.parse(fs.readFileSync(path.join('lists', 'result.yaml'), 'utf8'));
// 所有内网网段 // 所有内网网段
this.routeLists.mycard = ["10.198.0.0/16", "10.200.0.0/15", "172.16.0.0/12"]; this.routeLists.mycard = ['10.198.0.0/16', '10.200.0.0/15', '172.16.0.0/12'];
for (const h in this.hosts) { for (const h in this.hosts) {
const host = this.hosts[h] const host = this.hosts[h];
for (const c of host.subnets.split(",")) { for (const c of host.subnets) {
if (!c.length) { if (!c.length) {
continue; continue;
} }
...@@ -108,7 +120,9 @@ class InventoryBuilder { ...@@ -108,7 +120,9 @@ class InventoryBuilder {
} }
} }
// temp user before gateways // temp user before gateways
this.routeLists.ladder_needed = raw_utility.ladderNeeded.value.split(",").map((m) => { return m.trim() }); this.routeLists.ladder_needed = raw_utility.ladderNeeded.value.split(',').map((m) => {
return m.trim();
});
const vars = { const vars = {
routeLists: this.routeLists, routeLists: this.routeLists,
routeListNames: Object.keys(this.routeLists), routeListNames: Object.keys(this.routeLists),
...@@ -121,24 +135,25 @@ class InventoryBuilder { ...@@ -121,24 +135,25 @@ class InventoryBuilder {
return vars; return vars;
} }
async host_vars(host) { async host_vars(host) {
const connections = []; const connections = [];
host.dockerServices = { host.dockerServices = {
version: '2.4', version: '2.4',
services: { services: {
bird: { bird: {
restart: "always", restart: 'always',
image: "git-registry.mycard.moe/nanahira/docker-bird", image: 'git-registry.mycard.moe/nanahira/docker-bird',
network_mode: "host", network_mode: 'host',
cap_add: ["NET_ADMIN", "NET_BROADCAST", "NET_RAW"], cap_add: ['NET_ADMIN', 'NET_BROADCAST', 'NET_RAW'],
volumes: ["./bird.conf:/etc/bird/bird.conf:ro"] volumes: ['./bird.conf:/etc/bird/bird.conf:ro']
} }
} }
}; };
host.frpsNeeded = false; host.frpsNeeded = false;
const null_connection = "10000,null"; const null_connection = '10000,null';
const lanInterfaces = host.lanInterfaces.length > 0 ? host.lanInterfaces.split(",") : []; const lanInterfaces = host.lanInterfaces;
const masqInterfaces = host.masqInterfaces.length > 0 ? host.masqInterfaces.split(",") : []; const masqInterfaces = host.masqInterfaces.length > 0 ? host.masqInterfaces.split(',') : [];
const routePlans = []; const routePlans = [];
for (const h of this.connections) { for (const h of this.connections) {
if (h != host.name) { if (h != host.name) {
...@@ -159,7 +174,7 @@ class InventoryBuilder { ...@@ -159,7 +174,7 @@ class InventoryBuilder {
connections.push(await this.parse_connection(host, this.hosts[h], null_connection, false, true, false)); connections.push(await this.parse_connection(host, this.hosts[h], null_connection, false, true, false));
} }
routePlans.push({ routePlans.push({
name: h.replace(/-/g, "_"), name: h.replace(/-/g, '_'),
destMark: this.hosts[h].destMark, destMark: this.hosts[h].destMark,
address: this.hosts[h].address address: this.hosts[h].address
}); });
...@@ -170,9 +185,9 @@ class InventoryBuilder { ...@@ -170,9 +185,9 @@ class InventoryBuilder {
ansible_ssh_host: host.host, ansible_ssh_host: host.host,
ansible_ssh_user: host.user, ansible_ssh_user: host.user,
ansible_ssh_port: host.sshPort || 22, ansible_ssh_port: host.sshPort || 22,
ansible_python_interpreter: host.python || "python3", ansible_python_interpreter: host.python || 'python3',
address: host.address, address: host.address,
isCN: host.location.startsWith("CN"), isCN: host.location.startsWith('CN'),
key: host.wgPrivateKey, key: host.wgPrivateKey,
frpsNeeded: host.frpsNeeded, frpsNeeded: host.frpsNeeded,
frpsPort: host.frpsPort, frpsPort: host.frpsPort,
...@@ -193,7 +208,7 @@ class InventoryBuilder { ...@@ -193,7 +208,7 @@ class InventoryBuilder {
const primary = leftbottom ? outbound : inbound; // true 使用 peerAddress、port, false 使用peerAddress2、port2 const primary = leftbottom ? outbound : inbound; // true 使用 peerAddress、port, false 使用peerAddress2、port2
const connStrSplited = connstr.split(','); const connStrSplited = connstr.split(',');
const [_metric, protocol] = connStrSplited; const [_metric, protocol] = connStrSplited;
const paramsString = connStrSplited.slice(2).join("&"); const paramsString = connStrSplited.slice(2).join('&');
const metric = parseInt(_metric); const metric = parseInt(_metric);
const params = Object.fromEntries(new URLSearchParams(paramsString).entries()); const params = Object.fromEntries(new URLSearchParams(paramsString).entries());
const name = `mc${!outbound ? 'i' : '-'}${remote.name}`; const name = `mc${!outbound ? 'i' : '-'}${remote.name}`;
...@@ -223,32 +238,32 @@ class InventoryBuilder { ...@@ -223,32 +238,32 @@ class InventoryBuilder {
const frpType = protocol === 'wgfrp' ? (this.gatewayCompare(localGateway, remoteGateway) ? 'frps' : 'frpc') : undefined; const frpType = protocol === 'wgfrp' ? (this.gatewayCompare(localGateway, remoteGateway) ? 'frps' : 'frpc') : undefined;
if (frpType === "frps" && !local.dockerServices.services.frps) { if (frpType === 'frps' && !local.dockerServices.services.frps) {
local.frpsNeeded = true; local.frpsNeeded = true;
local.dockerServices.services.frps = { local.dockerServices.services.frps = {
restart: "always", restart: 'always',
image: "fatedier/frps:v0.34.2", image: 'fatedier/frps:v0.34.2',
network_mode: "host", network_mode: 'host',
command: "-c /frps.ini", command: '-c /frps.ini',
volumes: ["./frps.ini:/frps.ini:ro"] volumes: ['./frps.ini:/frps.ini:ro']
} };
} }
if (frpType === "frpc") { if (frpType === 'frpc') {
local.dockerServices.services[`frpc-${name}`] = { local.dockerServices.services[`frpc-${name}`] = {
restart: "always", restart: 'always',
image: "fatedier/frpc:v0.34.2", image: 'fatedier/frpc:v0.34.2',
network_mode: "host", network_mode: 'host',
command: "-c /frpc.ini", command: '-c /frpc.ini',
volumes: [`./frpc-${name}.ini:/frpc.ini:ro`] volumes: [`./frpc-${name}.ini:/frpc.ini:ro`]
} };
} }
const mtu = Math.min(localGateway ? localGateway.mtu : 1500, remoteGateway ? remoteGateway.mtu : 1500); const mtu = Math.min(localGateway ? localGateway.mtu : 1500, remoteGateway ? remoteGateway.mtu : 1500);
//console.log(local.name, name, mtu); //console.log(local.name, name, mtu);
if (outbound) { if (outbound) {
console.log(`${local.name} GW ${localGateway.isp} ${inbound ? "<" : "="}=${frpType === "frps" ? "s" : "="}=[${protocol}]=${frpType === "frpc" ? "s" : "="}=> ${remote.name} GW ${remoteGateway.isp}`); console.log(`${local.name} GW ${localGateway.isp} ${inbound ? '<' : '='}=${frpType === 'frps' ? 's' : '='}=[${protocol}]=${frpType === 'frpc' ? 's' : '='}=> ${remote.name} GW ${remoteGateway.isp}`);
} }
return { return {
...@@ -282,17 +297,17 @@ class InventoryBuilder { ...@@ -282,17 +297,17 @@ class InventoryBuilder {
const isCNScore = gateway.isCN ? 0 : 1; // 1 bit const isCNScore = gateway.isCN ? 0 : 1; // 1 bit
score |= isCNScore << 8; score |= isCNScore << 8;
const ipv4NatScore = ({ // 2 bits const ipv4NatScore = ({ // 2 bits
"ports": 0, 'ports': 0,
"dmz": 1 'dmz': 1
})[gateway.ipv4Nat] || 2; })[gateway.ipv4Nat] || 2;
score |= ipv4NatScore << 9; score |= ipv4NatScore << 9;
const ipv4Score = ({ // 2 bits const ipv4Score = ({ // 2 bits
"static": 2, 'static': 2,
"dynamic": 1 'dynamic': 1
})[gateway.ipv4] || 0; })[gateway.ipv4] || 0;
score |= ipv4Score << 11; score |= ipv4Score << 11;
const globalSSHScore = ({ // 1 bit const globalSSHScore = ({ // 1 bit
"globalssh": 1 'globalssh': 1
})[gateway.ssh] || 0; })[gateway.ssh] || 0;
score |= globalSSHScore << 12; score |= globalSSHScore << 12;
return score; return score;
......
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