-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgoogle-nftables.mjs
More file actions
76 lines (61 loc) · 2.7 KB
/
google-nftables.mjs
File metadata and controls
76 lines (61 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
!/usr/bin/node
import {writeFileSync, readFileSync, existsSync} from 'fs';
import {execSync} from 'child_process';
const {excludeCidr} = await import(execSync("npm root -g").toString().trim() + '/cidr-tools/dist/index.js');
//const excludeCidr = (await import(execSync("npm root -g").toString().trim() + '/fast-cidr-tools/dist/index.cjs')).exclude;
const GOOGLE_IPRANGES_URL = 'https://www.gstatic.com/ipranges/goog.json';
const GCLOUD_IPRANGES_URL = 'https://www.gstatic.com/ipranges/cloud.json';
const IPV4 = false;
const IPV6 = true;
const RULES_FILE = '/etc/nftables.d/99google.nft';
const IPV4_CHAIN = 'inet filter input';
const IPV6_CHAIN = IPV4_CHAIN;
const PORT = 9999;
const POST_COMMAND = 'rc-service nftables reload && lbu commit';
async function getIpRangesFromServer(url) {
const response = await fetch(url);
const json = await response.json();
const ranges = {syncToken: json.syncToken, ipv4: [], ipv6: []};
json.prefixes.forEach(function(prefix) {
if (IPV4 && ('ipv4Prefix' in prefix)) ranges.ipv4.push(prefix.ipv4Prefix);
if (IPV6 && ('ipv6Prefix' in prefix)) ranges.ipv6.push(prefix.ipv6Prefix);
});
return ranges;
}
function writeRule(nft, chain, saddr) {
nft.push('add rule ' + chain + ' tcp dport ' + PORT + ' ' + saddr + ' accept comment "Google servers allowed"');
}
function writeIPv4Rule(nft, range) {
writeRule(nft, IPV4_CHAIN, 'ip saddr ' + range);
}
function writeIPv6Rule(nft, range) {
writeRule(nft, IPV6_CHAIN, 'ip6 saddr ' + range);
}
async function main() {
if (!(IPV4 || IPV6)) return;
const google_ipranges = await getIpRangesFromServer(GOOGLE_IPRANGES_URL);
const gcloud_ipranges = await getIpRangesFromServer(GCLOUD_IPRANGES_URL);
const syncHeader = '# syncToken: ' + google_ipranges.syncToken + '-' + gcloud_ipranges.syncToken;
if (existsSync(RULES_FILE)) {
if (readFileSync(RULES_FILE).includes(syncHeader)) return;
}
const nft = [];
nft.push('#!/usr/sbin/nft -f');
nft.push(syncHeader);
nft.push('');
if (IPV4) {
const ipranges_ipv4 = excludeCidr(google_ipranges.ipv4, gcloud_ipranges.ipv4);
ipranges_ipv4.forEach(function(range) {
writeIPv4Rule(nft, range);
});
}
if (IPV6) {
const ipranges_ipv6 = excludeCidr(google_ipranges.ipv6, gcloud_ipranges.ipv6);
ipranges_ipv6.forEach(function(range) {
writeIPv6Rule(nft, range);
});
}
writeFileSync(RULES_FILE, nft.join('\n'));
execSync(POST_COMMAND);
}
await main();