fcdns 0.5.10 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cli.js +113 -0
- package/lib/cli.js.map +1 -0
- package/lib/dao/clear.js +8 -0
- package/lib/dao/clear.js.map +1 -0
- package/lib/dao/get-poison-test-result.js +18 -0
- package/lib/dao/get-poison-test-result.js.map +1 -0
- package/lib/dao/get-route-result.js +19 -0
- package/lib/dao/get-route-result.js.map +1 -0
- package/lib/dao/upsert-poison-test-result.js +14 -0
- package/lib/dao/upsert-poison-test-result.js.map +1 -0
- package/lib/dao/upsert-route-result.js +14 -0
- package/lib/dao/upsert-route-result.js.map +1 -0
- package/lib/database.js +44 -0
- package/lib/database.js.map +1 -0
- package/lib/hostnames.js +25 -0
- package/lib/hostnames.js.map +1 -0
- package/lib/ip-ranges.js +77 -0
- package/lib/ip-ranges.js.map +1 -0
- package/lib/poison-tester.js +55 -0
- package/lib/poison-tester.js.map +1 -0
- package/lib/record-types.js +77 -0
- package/lib/record-types.js.map +1 -0
- package/lib/router.js +63 -0
- package/lib/router.js.map +1 -0
- package/lib/server.js +88 -0
- package/lib/server.js.map +1 -0
- package/lib/utils/create-dns-resolver.js +7 -0
- package/lib/utils/create-dns-resolver.js.map +1 -0
- package/lib/utils/hostname-pattern.js +11 -0
- package/lib/utils/hostname-pattern.js.map +1 -0
- package/lib/utils/is-ipv4-address.js +4 -0
- package/lib/utils/is-ipv4-address.js.map +1 -0
- package/lib/utils/is-ipv6-address.js +4 -0
- package/lib/utils/is-ipv6-address.js.map +1 -0
- package/lib/utils/is-server-online.js +21 -0
- package/lib/utils/is-server-online.js.map +1 -0
- package/lib/utils/package.js +16 -0
- package/lib/utils/package.js.map +1 -0
- package/lib/utils/parse-server-info.js +8 -0
- package/lib/utils/parse-server-info.js.map +1 -0
- package/lib/utils/resolve-a.js +14 -0
- package/lib/utils/resolve-a.js.map +1 -0
- package/package.json +56 -54
- package/dist/cli.cjs +0 -48324
package/lib/cli.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import { startServer } from './server.js';
|
|
4
|
+
import { Router } from './router.js';
|
|
5
|
+
import { IPRanges } from './ip-ranges.js';
|
|
6
|
+
import { Hostnames } from './hostnames.js';
|
|
7
|
+
import { PoisonTester } from './poison-tester.js';
|
|
8
|
+
import { createDNSResolver } from "./utils/create-dns-resolver.js";
|
|
9
|
+
import { assert } from '@blackglory/prelude';
|
|
10
|
+
import { Level, Logger, TerminalTransport, stringToLevel } from 'extra-logger';
|
|
11
|
+
import { parseServerInfo } from "./utils/parse-server-info.js";
|
|
12
|
+
import { youDied } from 'you-died';
|
|
13
|
+
import * as Database from './database.js';
|
|
14
|
+
import { name, version, description } from "./utils/package.js";
|
|
15
|
+
process.title = name;
|
|
16
|
+
program
|
|
17
|
+
.name(name)
|
|
18
|
+
.version(version)
|
|
19
|
+
.description(description)
|
|
20
|
+
.requiredOption('--test-server <server>')
|
|
21
|
+
.requiredOption('--untrusted-server <server>')
|
|
22
|
+
.requiredOption('--trusted-server <server>')
|
|
23
|
+
.option('--port <port>', '', '53')
|
|
24
|
+
.option('--timeout <seconds>', '', '30')
|
|
25
|
+
.option('--ip-whitelist <filename>', '', 'ip-whitelist.txt')
|
|
26
|
+
.option('--hostname-whitelist <filename>', '', 'hostname-whitelist.txt')
|
|
27
|
+
.option('--hostname-blacklist <filename>', '', 'hostname-blacklist.txt')
|
|
28
|
+
.option('--cache <filename>', '', 'cache.db')
|
|
29
|
+
.option('--test-timeout <milliseconds>', '', '200')
|
|
30
|
+
.option('--log <level>', '', 'info')
|
|
31
|
+
.action(async () => {
|
|
32
|
+
const options = program.opts();
|
|
33
|
+
const cacheFilename = getCacheFilename(options);
|
|
34
|
+
const testServer = getTestServer(options);
|
|
35
|
+
const testTimeout = getTestTimeout(options);
|
|
36
|
+
const timeout = getTimeout(options);
|
|
37
|
+
const port = getPort(options);
|
|
38
|
+
const logLevel = getLogLevel(options);
|
|
39
|
+
const ipWhitelistFilename = getIpWhiltelistFilename(options);
|
|
40
|
+
const hostnameWhitelistFilename = getHostnameWhitelistFilename(options);
|
|
41
|
+
const hostnameBlacklistFilename = getHostnameBlacklistFilename(options);
|
|
42
|
+
const untrustedServer = getUntrustedServer(options);
|
|
43
|
+
const trustedServer = getTrustedServer(options);
|
|
44
|
+
Database.openDatabase(cacheFilename);
|
|
45
|
+
await Database.prepareDatabase();
|
|
46
|
+
youDied(() => Database.closeDatabase());
|
|
47
|
+
const poisonTester = new PoisonTester({
|
|
48
|
+
server: testServer,
|
|
49
|
+
timeout: testTimeout
|
|
50
|
+
});
|
|
51
|
+
const untrustedResolver = createDNSResolver(untrustedServer.host
|
|
52
|
+
+ (untrustedServer.port ? `:${untrustedServer.port}` : ''));
|
|
53
|
+
const ipWhitelist = await IPRanges.fromFile(ipWhitelistFilename);
|
|
54
|
+
const hostnameWhitelist = await Hostnames.fromFile(hostnameWhitelistFilename);
|
|
55
|
+
const hostnameBlacklist = await Hostnames.fromFile(hostnameBlacklistFilename);
|
|
56
|
+
const router = new Router({
|
|
57
|
+
poisonTester,
|
|
58
|
+
untrustedResolver,
|
|
59
|
+
ipWhitelist,
|
|
60
|
+
hostnameWhitelist,
|
|
61
|
+
hostnameBlacklist
|
|
62
|
+
});
|
|
63
|
+
const logger = new Logger({
|
|
64
|
+
level: logLevel,
|
|
65
|
+
transport: new TerminalTransport({})
|
|
66
|
+
});
|
|
67
|
+
startServer({
|
|
68
|
+
router,
|
|
69
|
+
logger,
|
|
70
|
+
trustedServer,
|
|
71
|
+
untrustedServer,
|
|
72
|
+
timeout,
|
|
73
|
+
port
|
|
74
|
+
});
|
|
75
|
+
})
|
|
76
|
+
.parse();
|
|
77
|
+
function getTestServer(options) {
|
|
78
|
+
return options.testServer;
|
|
79
|
+
}
|
|
80
|
+
function getUntrustedServer(options) {
|
|
81
|
+
return parseServerInfo(options.untrustedServer);
|
|
82
|
+
}
|
|
83
|
+
function getTrustedServer(options) {
|
|
84
|
+
return parseServerInfo(options.trustedServer);
|
|
85
|
+
}
|
|
86
|
+
function getPort(options) {
|
|
87
|
+
assert(/^\d+$/.test(options.port), 'The parameter port must be integer');
|
|
88
|
+
return Number.parseInt(options.port, 10);
|
|
89
|
+
}
|
|
90
|
+
function getTimeout(options) {
|
|
91
|
+
assert(/^\d+$/.test(options.timeout), 'The parameter timeout must be integer');
|
|
92
|
+
return Number.parseInt(options.port, 10) * 1000;
|
|
93
|
+
}
|
|
94
|
+
function getIpWhiltelistFilename(options) {
|
|
95
|
+
return options.ipWhitelist;
|
|
96
|
+
}
|
|
97
|
+
function getHostnameWhitelistFilename(options) {
|
|
98
|
+
return options.hostnameWhitelist;
|
|
99
|
+
}
|
|
100
|
+
function getHostnameBlacklistFilename(options) {
|
|
101
|
+
return options.hostnameBlacklist;
|
|
102
|
+
}
|
|
103
|
+
function getCacheFilename(options) {
|
|
104
|
+
return options.cache;
|
|
105
|
+
}
|
|
106
|
+
function getTestTimeout(options) {
|
|
107
|
+
assert(/^\d+$/.test(options.testTimeout), 'The parameter test timeout must be integer');
|
|
108
|
+
return Number.parseInt(options.testTimeout, 10);
|
|
109
|
+
}
|
|
110
|
+
function getLogLevel(options) {
|
|
111
|
+
return stringToLevel(options.log, Level.Info);
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=cli.js.map
|
package/lib/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/lib/dao/clear.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { getDatabase } from "../database.js";
|
|
2
|
+
import { withLazyStatic, lazyStatic } from 'extra-lazy';
|
|
3
|
+
export const clear = withLazyStatic(function () {
|
|
4
|
+
lazyStatic(() => getDatabase().prepare(`
|
|
5
|
+
DELETE FROM hostname
|
|
6
|
+
`), [getDatabase()]).run();
|
|
7
|
+
});
|
|
8
|
+
//# sourceMappingURL=clear.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clear.js","sourceRoot":"","sources":["../../src/dao/clear.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,uBAAwB;AAC9C,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvD,MAAM,CAAC,MAAM,KAAK,GAAG,cAAc,CAAC;IAClC,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC;;GAEtC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAA;AAC5B,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getDatabase } from "../database.js";
|
|
2
|
+
import { PoisonTestResult } from "../poison-tester.js";
|
|
3
|
+
import { withLazyStatic, lazyStatic } from 'extra-lazy';
|
|
4
|
+
export const getPoisonResult = withLazyStatic((hostname) => {
|
|
5
|
+
const row = lazyStatic(() => getDatabase()
|
|
6
|
+
.prepare(`
|
|
7
|
+
SELECT poison_test_result
|
|
8
|
+
FROM hostname
|
|
9
|
+
WHERE hostname = $hostname
|
|
10
|
+
`), [getDatabase()])
|
|
11
|
+
.get({ hostname });
|
|
12
|
+
switch (row === null || row === void 0 ? void 0 : row.poison_test_result) {
|
|
13
|
+
case PoisonTestResult.Poisoned: return PoisonTestResult.Poisoned;
|
|
14
|
+
case PoisonTestResult.NotPoisoned: return PoisonTestResult.NotPoisoned;
|
|
15
|
+
default: return null;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
//# sourceMappingURL=get-poison-test-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-poison-test-result.js","sourceRoot":"","sources":["../../src/dao/get-poison-test-result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,uBAAwB;AAC9C,OAAO,EAAE,gBAAgB,EAAE,4BAA6B;AACxD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvD,MAAM,CAAC,MAAM,eAAe,GAAG,cAAc,CAAC,CAAC,QAAgB,EAA2B,EAAE;IAC1F,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;SACvC,OAAO,CAAC;;;;KAIR,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;SACnB,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAsD,CAAA;IAEzE,QAAQ,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,kBAAkB,EAAE,CAAC;QAChC,KAAK,gBAAgB,CAAC,QAAQ,CAAC,CAAC,OAAO,gBAAgB,CAAC,QAAQ,CAAA;QAChE,KAAK,gBAAgB,CAAC,WAAW,CAAC,CAAC,OAAO,gBAAgB,CAAC,WAAW,CAAA;QACtE,OAAO,CAAC,CAAC,OAAO,IAAI,CAAA;IACtB,CAAC;AACH,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getDatabase } from "../database.js";
|
|
2
|
+
import { RouteResult } from "../router.js";
|
|
3
|
+
import { withLazyStatic, lazyStatic } from 'extra-lazy';
|
|
4
|
+
export const getRouteResult = withLazyStatic((hostname) => {
|
|
5
|
+
const row = lazyStatic(() => getDatabase()
|
|
6
|
+
.prepare(`
|
|
7
|
+
SELECT route_result
|
|
8
|
+
FROM hostname
|
|
9
|
+
WHERE hostname = $hostname
|
|
10
|
+
`), [getDatabase()])
|
|
11
|
+
.get({ hostname });
|
|
12
|
+
switch (row === null || row === void 0 ? void 0 : row.route_result) {
|
|
13
|
+
case RouteResult.Unresolved: return RouteResult.Unresolved;
|
|
14
|
+
case RouteResult.TrustedServer: return RouteResult.TrustedServer;
|
|
15
|
+
case RouteResult.UntrustedServer: return RouteResult.UntrustedServer;
|
|
16
|
+
default: return null;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
//# sourceMappingURL=get-route-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-route-result.js","sourceRoot":"","sources":["../../src/dao/get-route-result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,uBAAwB;AAC9C,OAAO,EAAE,WAAW,EAAE,qBAAsB;AAC5C,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvD,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,QAAgB,EAAsB,EAAE;IACpF,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;SACvC,OAAO,CAAC;;;;KAIR,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;SACnB,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAgD,CAAA;IAEnE,QAAQ,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,YAAY,EAAE,CAAC;QAC1B,KAAK,WAAW,CAAC,UAAU,CAAC,CAAC,OAAO,WAAW,CAAC,UAAU,CAAA;QAC1D,KAAK,WAAW,CAAC,aAAa,CAAC,CAAC,OAAO,WAAW,CAAC,aAAa,CAAA;QAChE,KAAK,WAAW,CAAC,eAAe,CAAC,CAAC,OAAO,WAAW,CAAC,eAAe,CAAA;QACpE,OAAO,CAAC,CAAC,OAAO,IAAI,CAAA;IACtB,CAAC;AACH,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getDatabase } from "../database.js";
|
|
2
|
+
import { withLazyStatic, lazyStatic } from 'extra-lazy';
|
|
3
|
+
export const upsertPoisonTestResult = withLazyStatic(function (hostname, result) {
|
|
4
|
+
lazyStatic(() => getDatabase().prepare(`
|
|
5
|
+
INSERT INTO hostname (
|
|
6
|
+
hostname
|
|
7
|
+
, poison_test_result
|
|
8
|
+
)
|
|
9
|
+
VALUES ($hostname, $result)
|
|
10
|
+
ON CONFLICT(hostname)
|
|
11
|
+
DO UPDATE SET poison_test_result = $result
|
|
12
|
+
`), [getDatabase()]).run({ hostname, result });
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=upsert-poison-test-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upsert-poison-test-result.js","sourceRoot":"","sources":["../../src/dao/upsert-poison-test-result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,uBAAwB;AAE9C,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvD,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC,UACnD,QAAgB,EAChB,MAAwB;IAExB,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC;;;;;;;;GAQtC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;AAChD,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getDatabase } from "../database.js";
|
|
2
|
+
import { withLazyStatic, lazyStatic } from 'extra-lazy';
|
|
3
|
+
export const upsertRouteResult = withLazyStatic(function (hostname, routeResult) {
|
|
4
|
+
lazyStatic(() => getDatabase().prepare(`
|
|
5
|
+
INSERT INTO hostname (
|
|
6
|
+
hostname
|
|
7
|
+
, route_result
|
|
8
|
+
)
|
|
9
|
+
VALUES ($hostname, $routeResult)
|
|
10
|
+
ON CONFLICT(hostname)
|
|
11
|
+
DO UPDATE SET route_result = $routeResult
|
|
12
|
+
`), [getDatabase()]).run({ hostname, routeResult });
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=upsert-route-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upsert-route-result.js","sourceRoot":"","sources":["../../src/dao/upsert-route-result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,uBAAwB;AAE9C,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,cAAc,CAAC,UAC9C,QAAgB,EAChB,WAAwB;IAExB,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC;;;;;;;;GAQtC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAA;AACrD,CAAC,CAAC,CAAA"}
|
package/lib/database.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { ensureDirSync, findUpPackageFilename } from 'extra-filesystem';
|
|
4
|
+
import { assert } from '@blackglory/errors';
|
|
5
|
+
import { findMigrationFilenames, readMigrationFile } from 'migration-files';
|
|
6
|
+
import { migrate } from '@blackglory/better-sqlite3-migrations';
|
|
7
|
+
import { isntUndefined } from '@blackglory/prelude';
|
|
8
|
+
import { map } from 'extra-promise';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
let db;
|
|
12
|
+
export function openDatabase(filename) {
|
|
13
|
+
if (isntUndefined(filename)) {
|
|
14
|
+
ensureDirSync(path.dirname(filename));
|
|
15
|
+
db = new Database(filename);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
db = new Database(':memory:');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function prepareDatabase() {
|
|
22
|
+
assert(db, 'Database is not opened');
|
|
23
|
+
await migrateDatabase(db);
|
|
24
|
+
}
|
|
25
|
+
export function getDatabase() {
|
|
26
|
+
assert(db, 'Database is not opened');
|
|
27
|
+
return db;
|
|
28
|
+
}
|
|
29
|
+
export function closeDatabase() {
|
|
30
|
+
if (db) {
|
|
31
|
+
db.exec(`
|
|
32
|
+
PRAGMA analysis_limit=400;
|
|
33
|
+
PRAGMA optimize;
|
|
34
|
+
`);
|
|
35
|
+
db.close();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function migrateDatabase(db) {
|
|
39
|
+
const pkgRoot = path.join((await findUpPackageFilename(__dirname)), '..');
|
|
40
|
+
const migrationsPath = path.join(pkgRoot, 'migrations');
|
|
41
|
+
const migrations = await map(await findMigrationFilenames(migrationsPath), readMigrationFile);
|
|
42
|
+
migrate(db, migrations);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AAErC,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,uCAAuC,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAE9D,IAAI,EAAa,CAAA;AAEjB,MAAM,UAAU,YAAY,CAAC,QAAiB;IAC5C,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;QAErC,EAAE,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC7B,CAAC;SAAM,CAAC;QACN,EAAE,GAAG,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAA;IAC/B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAA;IACpC,MAAM,eAAe,CAAC,EAAE,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAA;IACpC,OAAO,EAAE,CAAA;AACX,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,IAAI,CAAC;;;KAGP,CAAC,CAAA;QACF,EAAE,CAAC,KAAK,EAAE,CAAA;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,EAAa;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,qBAAqB,CAAC,SAAS,CAAC,CAAE,EAAE,IAAI,CAAC,CAAA;IAC1E,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;IACvD,MAAM,UAAU,GAAG,MAAM,GAAG,CAC1B,MAAM,sBAAsB,CAAC,cAAc,CAAC,EAC5C,iBAAiB,CAClB,CAAA;IACD,OAAO,CAAC,EAAE,EAAE,UAAU,CAAC,CAAA;AACzB,CAAC"}
|
package/lib/hostnames.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import { HostnamePattern } from "./utils/hostname-pattern.js";
|
|
3
|
+
import { ensureFile } from 'extra-filesystem';
|
|
4
|
+
export class Hostnames {
|
|
5
|
+
constructor(patterns) {
|
|
6
|
+
this.patterns = patterns;
|
|
7
|
+
}
|
|
8
|
+
static async fromFile(filename) {
|
|
9
|
+
await ensureFile(filename);
|
|
10
|
+
const text = await fs.readFile(filename, 'utf-8');
|
|
11
|
+
const patterns = text.split('\n')
|
|
12
|
+
.map(x => x.trim())
|
|
13
|
+
.filter(x => x !== '')
|
|
14
|
+
.filter(isHostnamePattern)
|
|
15
|
+
.map(x => new HostnamePattern(x));
|
|
16
|
+
return new Hostnames(patterns);
|
|
17
|
+
}
|
|
18
|
+
includes(hostname) {
|
|
19
|
+
return this.patterns.some(x => x.match(hostname));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function isHostnamePattern(text) {
|
|
23
|
+
return /^[\da-zA-Z\-.*]+$/.test(text);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=hostnames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostnames.js","sourceRoot":"","sources":["../src/hostnames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,oCAAkC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,MAAM,OAAO,SAAS;IACpB,YAAoB,QAA2B;QAA3B,aAAQ,GAAR,QAAQ,CAAmB;IAAG,CAAC;IAEnD,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAgB;QACpC,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAA;QAE1B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;aAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;aACrB,MAAM,CAAC,iBAAiB,CAAC;aACzB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC,CAAA;QAEnC,OAAO,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAA;IAChC,CAAC;IAED,QAAQ,CAAC,QAAgB;QACvB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;IACnD,CAAC;CACF;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACvC,CAAC"}
|
package/lib/ip-ranges.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { IPv4AddressRange, IPv6AddressRange } from 'address-range';
|
|
2
|
+
import { isIPv4Address } from "./utils/is-ipv4-address.js";
|
|
3
|
+
import { isIPv6Address } from "./utils/is-ipv6-address.js";
|
|
4
|
+
import { promises as fs } from 'fs';
|
|
5
|
+
import { groupBy } from 'iterable-operator';
|
|
6
|
+
export class IPRanges {
|
|
7
|
+
constructor(...args) {
|
|
8
|
+
if (args.length === 1) {
|
|
9
|
+
const [ranges] = args;
|
|
10
|
+
const groups = groupBy(ranges, element => {
|
|
11
|
+
if (element instanceof IPv4AddressRange) {
|
|
12
|
+
return 'ipv4';
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return 'ipv6';
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
this.ipv4 = groups.get('ipv4');
|
|
19
|
+
this.ipv6 = groups.get('ipv6');
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
const [ipv4, ipv6] = args;
|
|
23
|
+
this.ipv4 = ipv4;
|
|
24
|
+
this.ipv6 = ipv6;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
static async fromFile(filename) {
|
|
28
|
+
const ipv4 = [];
|
|
29
|
+
const ipv6 = [];
|
|
30
|
+
const text = await fs.readFile(filename, 'utf-8');
|
|
31
|
+
text.split('\n')
|
|
32
|
+
.filter(x => x.trim())
|
|
33
|
+
.filter(x => x !== '')
|
|
34
|
+
.forEach(x => {
|
|
35
|
+
if (isIPv4Address(x)) {
|
|
36
|
+
ipv4.push(IPv4AddressRange.from(x, x));
|
|
37
|
+
}
|
|
38
|
+
if (isIPv6Address(x)) {
|
|
39
|
+
ipv6.push(IPv6AddressRange.from(x, x));
|
|
40
|
+
}
|
|
41
|
+
if (isIPv4AddressRange(x)) {
|
|
42
|
+
const [startAddress, endAddress] = x.split('-');
|
|
43
|
+
ipv4.push(IPv4AddressRange.from(startAddress, endAddress));
|
|
44
|
+
}
|
|
45
|
+
if (isIPv6AddressRange(x)) {
|
|
46
|
+
const [startAddress, endAddress] = x.split('-');
|
|
47
|
+
ipv6.push(IPv6AddressRange.from(startAddress, endAddress));
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return new IPRanges(ipv4, ipv6);
|
|
51
|
+
}
|
|
52
|
+
async toFile(filename) {
|
|
53
|
+
const ipv4 = this.ipv4
|
|
54
|
+
.map(range => range.toString())
|
|
55
|
+
.join('\n');
|
|
56
|
+
const ipv6 = this.ipv6
|
|
57
|
+
.map(range => range.toString())
|
|
58
|
+
.join('\n');
|
|
59
|
+
await fs.writeFile(filename, [ipv4, ipv6].join('\n'));
|
|
60
|
+
}
|
|
61
|
+
includes(address) {
|
|
62
|
+
if (isIPv4Address(address)) {
|
|
63
|
+
return this.ipv4.some(x => x.includes(address));
|
|
64
|
+
}
|
|
65
|
+
if (isIPv6Address(address)) {
|
|
66
|
+
return this.ipv6.some(x => x.includes(address));
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function isIPv4AddressRange(text) {
|
|
72
|
+
return /^[\d\.]+-[\d\.]+$/.test(text);
|
|
73
|
+
}
|
|
74
|
+
function isIPv6AddressRange(text) {
|
|
75
|
+
return /^[\da-f:]+-[\da-f:]+$/.test(text);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=ip-ranges.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ip-ranges.js","sourceRoot":"","sources":["../src/ip-ranges.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { isServerOnline } from "./utils/is-server-online.js";
|
|
2
|
+
import { createDNSResolver } from "./utils/create-dns-resolver.js";
|
|
3
|
+
import { resolveA } from "./utils/resolve-a.js";
|
|
4
|
+
import { CustomError } from '@blackglory/errors';
|
|
5
|
+
import { isSuccessPromise } from 'return-style';
|
|
6
|
+
import { isntNull } from '@blackglory/prelude';
|
|
7
|
+
import { getPoisonResult } from "./dao/get-poison-test-result.js";
|
|
8
|
+
import { upsertPoisonTestResult } from "./dao/upsert-poison-test-result.js";
|
|
9
|
+
export var PoisonTestResult;
|
|
10
|
+
(function (PoisonTestResult) {
|
|
11
|
+
PoisonTestResult[PoisonTestResult["NotPoisoned"] = 0] = "NotPoisoned";
|
|
12
|
+
PoisonTestResult[PoisonTestResult["Poisoned"] = 1] = "Poisoned";
|
|
13
|
+
})(PoisonTestResult || (PoisonTestResult = {}));
|
|
14
|
+
export class ServerUnreachable extends CustomError {
|
|
15
|
+
constructor() {
|
|
16
|
+
super('The test server is unreachable or not sending a echo reply in time');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class PoisonTester {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.server = options.server;
|
|
22
|
+
this.timeout = options.timeout;
|
|
23
|
+
this.testResolver = createDNSResolver(this.server);
|
|
24
|
+
}
|
|
25
|
+
async isHostnamePoisoned(hostname) {
|
|
26
|
+
const result = getPoisonResult(hostname);
|
|
27
|
+
if (isntNull(result)) {
|
|
28
|
+
return poisonTestResultToIsPoisoned(result);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
const [alive, poisoned] = await Promise.all([
|
|
32
|
+
isServerOnline(this.server, this.timeout),
|
|
33
|
+
isSuccessPromise(resolveA(this.testResolver, hostname, this.timeout))
|
|
34
|
+
]);
|
|
35
|
+
if (alive) {
|
|
36
|
+
const result = poisoned
|
|
37
|
+
? PoisonTestResult.Poisoned
|
|
38
|
+
: PoisonTestResult.NotPoisoned;
|
|
39
|
+
upsertPoisonTestResult(hostname, result);
|
|
40
|
+
return poisonTestResultToIsPoisoned(result);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
throw new ServerUnreachable();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function poisonTestResultToIsPoisoned(result) {
|
|
49
|
+
switch (result) {
|
|
50
|
+
case PoisonTestResult.Poisoned: return true;
|
|
51
|
+
case PoisonTestResult.NotPoisoned: return false;
|
|
52
|
+
default: throw new Error('Unknown poision test result');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=poison-tester.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poison-tester.js","sourceRoot":"","sources":["../src/poison-tester.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,oCAAkC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,uCAAqC;AACjE,OAAO,EAAE,QAAQ,EAAE,6BAA2B;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,wCAAsC;AAChE,OAAO,EAAE,sBAAsB,EAAE,2CAAyC;AAE1E,MAAM,CAAN,IAAY,gBAGX;AAHD,WAAY,gBAAgB;IAC1B,qEAAe,CAAA;IACf,+DAAY,CAAA;AACd,CAAC,EAHW,gBAAgB,KAAhB,gBAAgB,QAG3B;AAED,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAChD;QACE,KAAK,CAAC,oEAAoE,CAAC,CAAA;IAC7E,CAAC;CACF;AAED,MAAM,OAAO,YAAY;IAKvB,YAAY,OAGX;QACC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;QAC9B,IAAI,CAAC,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACpD,CAAC;IAKD,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QACvC,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAA;QACxC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,OAAO,4BAA4B,CAAC,MAAM,CAAC,CAAA;QAC7C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAC1C,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC;gBACzC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;aACtE,CAAC,CAAA;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,MAAM,GAAG,QAAQ;oBACrB,CAAC,CAAC,gBAAgB,CAAC,QAAQ;oBAC3B,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAA;gBAChC,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;gBACxC,OAAO,4BAA4B,CAAC,MAAM,CAAC,CAAA;YAC7C,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,iBAAiB,EAAE,CAAA;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,SAAS,4BAA4B,CAAC,MAAwB;IAC5D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,gBAAgB,CAAC,QAAQ,CAAC,CAAC,OAAO,IAAI,CAAA;QAC3C,KAAK,gBAAgB,CAAC,WAAW,CAAC,CAAC,OAAO,KAAK,CAAA;QAC/C,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IACzD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export var RecordType;
|
|
2
|
+
(function (RecordType) {
|
|
3
|
+
RecordType[RecordType["A"] = 1] = "A";
|
|
4
|
+
RecordType[RecordType["NS"] = 2] = "NS";
|
|
5
|
+
RecordType[RecordType["MD"] = 3] = "MD";
|
|
6
|
+
RecordType[RecordType["MF"] = 4] = "MF";
|
|
7
|
+
RecordType[RecordType["CNAME"] = 5] = "CNAME";
|
|
8
|
+
RecordType[RecordType["SOA"] = 6] = "SOA";
|
|
9
|
+
RecordType[RecordType["MB"] = 7] = "MB";
|
|
10
|
+
RecordType[RecordType["MG"] = 8] = "MG";
|
|
11
|
+
RecordType[RecordType["MR"] = 9] = "MR";
|
|
12
|
+
RecordType[RecordType["NULL"] = 10] = "NULL";
|
|
13
|
+
RecordType[RecordType["WKS"] = 11] = "WKS";
|
|
14
|
+
RecordType[RecordType["PTR"] = 12] = "PTR";
|
|
15
|
+
RecordType[RecordType["HINFO"] = 13] = "HINFO";
|
|
16
|
+
RecordType[RecordType["MINFO"] = 14] = "MINFO";
|
|
17
|
+
RecordType[RecordType["MX"] = 15] = "MX";
|
|
18
|
+
RecordType[RecordType["TXT"] = 16] = "TXT";
|
|
19
|
+
RecordType[RecordType["RP"] = 17] = "RP";
|
|
20
|
+
RecordType[RecordType["AFSDB"] = 18] = "AFSDB";
|
|
21
|
+
RecordType[RecordType["X25"] = 19] = "X25";
|
|
22
|
+
RecordType[RecordType["ISDN"] = 20] = "ISDN";
|
|
23
|
+
RecordType[RecordType["RT"] = 21] = "RT";
|
|
24
|
+
RecordType[RecordType["NSAP"] = 22] = "NSAP";
|
|
25
|
+
RecordType[RecordType["NSAP-PTR"] = 23] = "NSAP-PTR";
|
|
26
|
+
RecordType[RecordType["SIG"] = 24] = "SIG";
|
|
27
|
+
RecordType[RecordType["KEY"] = 25] = "KEY";
|
|
28
|
+
RecordType[RecordType["PX"] = 26] = "PX";
|
|
29
|
+
RecordType[RecordType["GPOS"] = 27] = "GPOS";
|
|
30
|
+
RecordType[RecordType["AAAA"] = 28] = "AAAA";
|
|
31
|
+
RecordType[RecordType["LOC"] = 29] = "LOC";
|
|
32
|
+
RecordType[RecordType["NXT"] = 30] = "NXT";
|
|
33
|
+
RecordType[RecordType["EID"] = 31] = "EID";
|
|
34
|
+
RecordType[RecordType["NIMLOC"] = 32] = "NIMLOC";
|
|
35
|
+
RecordType[RecordType["SRV"] = 33] = "SRV";
|
|
36
|
+
RecordType[RecordType["ATMA"] = 34] = "ATMA";
|
|
37
|
+
RecordType[RecordType["NAPTR"] = 35] = "NAPTR";
|
|
38
|
+
RecordType[RecordType["KX"] = 36] = "KX";
|
|
39
|
+
RecordType[RecordType["CERT"] = 37] = "CERT";
|
|
40
|
+
RecordType[RecordType["A6"] = 38] = "A6";
|
|
41
|
+
RecordType[RecordType["DNAME"] = 39] = "DNAME";
|
|
42
|
+
RecordType[RecordType["SINK"] = 40] = "SINK";
|
|
43
|
+
RecordType[RecordType["OPT"] = 41] = "OPT";
|
|
44
|
+
RecordType[RecordType["APL"] = 42] = "APL";
|
|
45
|
+
RecordType[RecordType["DS"] = 43] = "DS";
|
|
46
|
+
RecordType[RecordType["SSHFP"] = 44] = "SSHFP";
|
|
47
|
+
RecordType[RecordType["IPSECKEY"] = 45] = "IPSECKEY";
|
|
48
|
+
RecordType[RecordType["RRSIG"] = 46] = "RRSIG";
|
|
49
|
+
RecordType[RecordType["NSEC"] = 47] = "NSEC";
|
|
50
|
+
RecordType[RecordType["DNSKEY"] = 48] = "DNSKEY";
|
|
51
|
+
RecordType[RecordType["DHCID"] = 49] = "DHCID";
|
|
52
|
+
RecordType[RecordType["NSEC3"] = 50] = "NSEC3";
|
|
53
|
+
RecordType[RecordType["NSEC3PARAM"] = 51] = "NSEC3PARAM";
|
|
54
|
+
RecordType[RecordType["TLSA"] = 52] = "TLSA";
|
|
55
|
+
RecordType[RecordType["HIP"] = 55] = "HIP";
|
|
56
|
+
RecordType[RecordType["NINFO"] = 56] = "NINFO";
|
|
57
|
+
RecordType[RecordType["RKEY"] = 57] = "RKEY";
|
|
58
|
+
RecordType[RecordType["TALINK"] = 58] = "TALINK";
|
|
59
|
+
RecordType[RecordType["CDS"] = 59] = "CDS";
|
|
60
|
+
RecordType[RecordType["SPF"] = 99] = "SPF";
|
|
61
|
+
RecordType[RecordType["UINFO"] = 100] = "UINFO";
|
|
62
|
+
RecordType[RecordType["UID"] = 101] = "UID";
|
|
63
|
+
RecordType[RecordType["GID"] = 102] = "GID";
|
|
64
|
+
RecordType[RecordType["UNSPEC"] = 103] = "UNSPEC";
|
|
65
|
+
RecordType[RecordType["TKEY"] = 249] = "TKEY";
|
|
66
|
+
RecordType[RecordType["TSIG"] = 250] = "TSIG";
|
|
67
|
+
RecordType[RecordType["IXFR"] = 251] = "IXFR";
|
|
68
|
+
RecordType[RecordType["AXFR"] = 252] = "AXFR";
|
|
69
|
+
RecordType[RecordType["MAILB"] = 253] = "MAILB";
|
|
70
|
+
RecordType[RecordType["MAILA"] = 254] = "MAILA";
|
|
71
|
+
RecordType[RecordType["ANY"] = 255] = "ANY";
|
|
72
|
+
RecordType[RecordType["URI"] = 256] = "URI";
|
|
73
|
+
RecordType[RecordType["CAA"] = 257] = "CAA";
|
|
74
|
+
RecordType[RecordType["TA"] = 32768] = "TA";
|
|
75
|
+
RecordType[RecordType["DLV"] = 32769] = "DLV";
|
|
76
|
+
})(RecordType || (RecordType = {}));
|
|
77
|
+
//# sourceMappingURL=record-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-types.js","sourceRoot":"","sources":["../src/record-types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,UA0EX;AA1ED,WAAY,UAAU;IACpB,qCAAK,CAAA;IACL,uCAAM,CAAA;IACN,uCAAM,CAAA;IACN,uCAAM,CAAA;IACN,6CAAS,CAAA;IACT,yCAAO,CAAA;IACP,uCAAM,CAAA;IACN,uCAAM,CAAA;IACN,uCAAM,CAAA;IACN,4CAAS,CAAA;IACT,0CAAQ,CAAA;IACR,0CAAQ,CAAA;IACR,8CAAU,CAAA;IACV,8CAAU,CAAA;IACV,wCAAO,CAAA;IACP,0CAAQ,CAAA;IACR,wCAAO,CAAA;IACP,8CAAU,CAAA;IACV,0CAAQ,CAAA;IACR,4CAAS,CAAA;IACT,wCAAO,CAAA;IACP,4CAAS,CAAA;IACT,oDAAe,CAAA;IACf,0CAAQ,CAAA;IACR,0CAAQ,CAAA;IACR,wCAAO,CAAA;IACP,4CAAS,CAAA;IACT,4CAAS,CAAA;IACT,0CAAQ,CAAA;IACR,0CAAQ,CAAA;IACR,0CAAQ,CAAA;IACR,gDAAW,CAAA;IACX,0CAAQ,CAAA;IACR,4CAAS,CAAA;IACT,8CAAU,CAAA;IACV,wCAAO,CAAA;IACP,4CAAS,CAAA;IACT,wCAAO,CAAA;IACP,8CAAU,CAAA;IACV,4CAAS,CAAA;IACT,0CAAQ,CAAA;IACR,0CAAQ,CAAA;IACR,wCAAO,CAAA;IACP,8CAAU,CAAA;IACV,oDAAa,CAAA;IACb,8CAAU,CAAA;IACV,4CAAS,CAAA;IACT,gDAAW,CAAA;IACX,8CAAU,CAAA;IACV,8CAAU,CAAA;IACV,wDAAe,CAAA;IACf,4CAAS,CAAA;IACT,0CAAQ,CAAA;IACR,8CAAU,CAAA;IACV,4CAAS,CAAA;IACT,gDAAW,CAAA;IACX,0CAAQ,CAAA;IACR,0CAAQ,CAAA;IACR,+CAAW,CAAA;IACX,2CAAS,CAAA;IACT,2CAAS,CAAA;IACT,iDAAY,CAAA;IACZ,6CAAU,CAAA;IACV,6CAAU,CAAA;IACV,6CAAU,CAAA;IACV,6CAAU,CAAA;IACV,+CAAW,CAAA;IACX,+CAAW,CAAA;IACX,2CAAS,CAAA;IACT,2CAAS,CAAA;IACT,2CAAS,CAAA;IACT,2CAAU,CAAA;IACV,6CAAW,CAAA;AACb,CAAC,EA1EW,UAAU,KAAV,UAAU,QA0ErB"}
|
package/lib/router.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { resolveA } from "./utils/resolve-a.js";
|
|
2
|
+
import { isntNull } from '@blackglory/prelude';
|
|
3
|
+
import { getRouteResult } from "./dao/get-route-result.js";
|
|
4
|
+
import { upsertRouteResult } from "./dao/upsert-route-result.js";
|
|
5
|
+
export var RouteResult;
|
|
6
|
+
(function (RouteResult) {
|
|
7
|
+
RouteResult[RouteResult["UntrustedServer"] = 0] = "UntrustedServer";
|
|
8
|
+
RouteResult[RouteResult["TrustedServer"] = 1] = "TrustedServer";
|
|
9
|
+
RouteResult[RouteResult["Unresolved"] = 2] = "Unresolved";
|
|
10
|
+
})(RouteResult || (RouteResult = {}));
|
|
11
|
+
export class Router {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.poisonTester = options.poisonTester;
|
|
14
|
+
this.untrustedResolver = options.untrustedResolver;
|
|
15
|
+
this.ipWhitelist = options.ipWhitelist;
|
|
16
|
+
this.hostnameWhitelist = options.hostnameWhitelist;
|
|
17
|
+
this.hostnameBlacklist = options.hostnameBlacklist;
|
|
18
|
+
}
|
|
19
|
+
async route(hostname) {
|
|
20
|
+
if (this.inHostnameWhitelist(hostname))
|
|
21
|
+
return RouteResult.UntrustedServer;
|
|
22
|
+
if (this.inHostnameBlacklist(hostname))
|
|
23
|
+
return RouteResult.TrustedServer;
|
|
24
|
+
const result = getRouteResult(hostname);
|
|
25
|
+
if (isntNull(result)) {
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
const result = await this.resolveRoute(hostname);
|
|
30
|
+
upsertRouteResult(hostname, result);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async resolveRoute(hostname) {
|
|
35
|
+
if (await this.poisonTester.isHostnamePoisoned(hostname)) {
|
|
36
|
+
return RouteResult.TrustedServer;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const addresses = await resolveA(this.untrustedResolver, hostname);
|
|
40
|
+
if (addresses.length > 0) {
|
|
41
|
+
if (this.inIPWhitelist(addresses)) {
|
|
42
|
+
return RouteResult.UntrustedServer;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return RouteResult.TrustedServer;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return RouteResult.Unresolved;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
inIPWhitelist(addresses) {
|
|
54
|
+
return addresses.some(x => this.ipWhitelist.includes(x));
|
|
55
|
+
}
|
|
56
|
+
inHostnameWhitelist(hostname) {
|
|
57
|
+
return this.hostnameWhitelist.includes(hostname);
|
|
58
|
+
}
|
|
59
|
+
inHostnameBlacklist(hostname) {
|
|
60
|
+
return this.hostnameBlacklist.includes(hostname);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,6BAA2B;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,kCAAgC;AACzD,OAAO,EAAE,iBAAiB,EAAE,qCAAmC;AAE/D,MAAM,CAAN,IAAY,WAIX;AAJD,WAAY,WAAW;IACrB,mEAAmB,CAAA;IACnB,+DAAiB,CAAA;IACjB,yDAAc,CAAA;AAChB,CAAC,EAJW,WAAW,KAAX,WAAW,QAItB;AAED,MAAM,OAAO,MAAM;IAOjB,YAAY,OAMX;QACC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAA;QACxC,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAA;QAClD,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAA;QACtC,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAA;QAClD,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAA;IACpD,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,QAAgB;QAC1B,IAAI,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC;YAAE,OAAO,WAAW,CAAC,eAAe,CAAA;QAC1E,IAAI,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC;YAAE,OAAO,WAAW,CAAC,aAAa,CAAA;QAExE,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;QACvC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,OAAO,MAAM,CAAA;QACf,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;YAChD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YACnC,OAAO,MAAM,CAAA;QACf,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,QAAgB;QACzC,IAAI,MAAM,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzD,OAAO,WAAW,CAAC,aAAa,CAAA;QAClC,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAA;YAClE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;oBAClC,OAAO,WAAW,CAAC,eAAe,CAAA;gBACpC,CAAC;qBAAM,CAAC;oBACN,OAAO,WAAW,CAAC,aAAa,CAAA;gBAClC,CAAC;YACH,CAAC;iBAAM,CAAC;gBAEN,OAAO,WAAW,CAAC,UAAU,CAAA;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,SAAmB;QACvC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1D,CAAC;IAEO,mBAAmB,CAAC,QAAgB;QAC1C,OAAO,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAClD,CAAC;IAEO,mBAAmB,CAAC,QAAgB;QAC1C,OAAO,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAClD,CAAC;CACF"}
|