vpndetection 1.6.0 → 1.8.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/dist/client.d.ts +12 -1
- package/dist/client.js +55 -11
- package/dist/client.js.map +1 -1
- package/dist/generated/types.gen.d.ts +13 -4
- package/dist/middleware/condition.d.ts +59 -0
- package/dist/middleware/condition.js +112 -0
- package/dist/middleware/condition.js.map +1 -0
- package/dist/middleware/core.d.ts +128 -0
- package/dist/middleware/core.js +149 -0
- package/dist/middleware/core.js.map +1 -0
- package/dist/middleware/index.d.ts +4 -0
- package/dist/middleware/index.js +3 -0
- package/dist/middleware/index.js.map +1 -0
- package/package.json +5 -1
package/dist/client.d.ts
CHANGED
|
@@ -32,6 +32,13 @@ export interface Options {
|
|
|
32
32
|
concurrency?: number;
|
|
33
33
|
/** Retry attempts for a transient failure. Default 2. */
|
|
34
34
|
retries?: number;
|
|
35
|
+
/**
|
|
36
|
+
* How long one request may take before it is abandoned, in milliseconds.
|
|
37
|
+
* Default 30000. Applies per attempt, so a retried call may take longer in
|
|
38
|
+
* total. A dataset transfer is deliberately exempt: it is expected to run
|
|
39
|
+
* for minutes.
|
|
40
|
+
*/
|
|
41
|
+
timeoutMs?: number;
|
|
35
42
|
/** Override the HTTP implementation, mostly for tests. */
|
|
36
43
|
fetch?: typeof globalThis.fetch;
|
|
37
44
|
}
|
|
@@ -39,6 +46,8 @@ export interface Options {
|
|
|
39
46
|
export interface LookupOptions {
|
|
40
47
|
/** Retry attempts for a transient failure. */
|
|
41
48
|
retries?: number;
|
|
49
|
+
/** How long one attempt may take before it is abandoned, in milliseconds. */
|
|
50
|
+
timeoutMs?: number;
|
|
42
51
|
}
|
|
43
52
|
/** Per-call overrides for one batch. Anything omitted falls back to the client's setting. */
|
|
44
53
|
export interface BatchOptions extends LookupOptions {
|
|
@@ -56,6 +65,7 @@ export declare class VPNDetection {
|
|
|
56
65
|
private readonly cache;
|
|
57
66
|
private readonly limit;
|
|
58
67
|
private readonly retries;
|
|
68
|
+
private readonly timeoutMs;
|
|
59
69
|
/** The licensed dataset downloads, for keys that carry the `db.download` scope. */
|
|
60
70
|
readonly database: DatabaseApi;
|
|
61
71
|
constructor(options?: Options);
|
|
@@ -90,8 +100,9 @@ export declare class VPNDetection {
|
|
|
90
100
|
export declare class DatabaseApi {
|
|
91
101
|
private readonly client;
|
|
92
102
|
private readonly retries;
|
|
103
|
+
private readonly timeoutMs;
|
|
93
104
|
private readonly fetchImpl;
|
|
94
|
-
constructor(client: Client, retries: number, fetchImpl: typeof globalThis.fetch);
|
|
105
|
+
constructor(client: Client, retries: number, timeoutMs: number, fetchImpl: typeof globalThis.fetch);
|
|
95
106
|
list(): Promise<LicensedDataset[]>;
|
|
96
107
|
metadata(id: string): Promise<DatasetMetadata>;
|
|
97
108
|
/**
|
package/dist/client.js
CHANGED
|
@@ -7,6 +7,10 @@ import { bogonResult, isBogon } from './bogon.js';
|
|
|
7
7
|
import { errorFromResponse, VPNDetectionError } from './errors.js';
|
|
8
8
|
import { toResult } from './types.js';
|
|
9
9
|
export const DEFAULT_BASE_URL = 'https://api.vpndetection.io';
|
|
10
|
+
// Matches the other SDKs, whose HTTP clients default to 30s. Node's global
|
|
11
|
+
// fetch has no whole-request limit of its own, so without this a hung API holds
|
|
12
|
+
// a caller until undici's 300s headers timeout - which is why this exists.
|
|
13
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
10
14
|
/**
|
|
11
15
|
* A client for the VPNDetection API.
|
|
12
16
|
*
|
|
@@ -18,6 +22,7 @@ export class VPNDetection {
|
|
|
18
22
|
cache;
|
|
19
23
|
limit;
|
|
20
24
|
retries;
|
|
25
|
+
timeoutMs;
|
|
21
26
|
/** The licensed dataset downloads, for keys that carry the `db.download` scope. */
|
|
22
27
|
database;
|
|
23
28
|
constructor(options = {}) {
|
|
@@ -36,7 +41,8 @@ export class VPNDetection {
|
|
|
36
41
|
});
|
|
37
42
|
this.limit = pLimit(options.concurrency ?? 8);
|
|
38
43
|
this.retries = options.retries ?? 2;
|
|
39
|
-
this.
|
|
44
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
45
|
+
this.database = new DatabaseApi(this.client, this.retries, this.timeoutMs, fetchImpl);
|
|
40
46
|
}
|
|
41
47
|
/**
|
|
42
48
|
* Whether an address is private, loopback, link-local, documentation,
|
|
@@ -64,8 +70,11 @@ export class VPNDetection {
|
|
|
64
70
|
if (hit !== undefined) {
|
|
65
71
|
return hit;
|
|
66
72
|
}
|
|
73
|
+
const timeoutMs = options.timeoutMs ?? this.timeoutMs;
|
|
67
74
|
const result = await withRetry(options.retries ?? this.retries, async () => {
|
|
68
|
-
const res = await
|
|
75
|
+
const res = await deadline(timeoutMs, (signal) => lookupIp({
|
|
76
|
+
client: this.client, path: { ip: ip }, signal: signal,
|
|
77
|
+
}));
|
|
69
78
|
const body = unwrap(res);
|
|
70
79
|
return toResult(body);
|
|
71
80
|
});
|
|
@@ -105,21 +114,27 @@ export class VPNDetection {
|
|
|
105
114
|
export class DatabaseApi {
|
|
106
115
|
client;
|
|
107
116
|
retries;
|
|
117
|
+
timeoutMs;
|
|
108
118
|
fetchImpl;
|
|
109
|
-
constructor(client, retries, fetchImpl) {
|
|
119
|
+
constructor(client, retries, timeoutMs, fetchImpl) {
|
|
110
120
|
this.client = client;
|
|
111
121
|
this.retries = retries;
|
|
122
|
+
this.timeoutMs = timeoutMs;
|
|
112
123
|
this.fetchImpl = fetchImpl;
|
|
113
124
|
}
|
|
114
125
|
async list() {
|
|
115
126
|
return withRetry(this.retries, async () => {
|
|
116
|
-
const res = await
|
|
127
|
+
const res = await deadline(this.timeoutMs, (signal) => listDatabases({
|
|
128
|
+
client: this.client, signal: signal,
|
|
129
|
+
}));
|
|
117
130
|
return unwrap(res).datasets;
|
|
118
131
|
});
|
|
119
132
|
}
|
|
120
133
|
async metadata(id) {
|
|
121
134
|
return withRetry(this.retries, async () => {
|
|
122
|
-
const res = await
|
|
135
|
+
const res = await deadline(this.timeoutMs, (signal) => databaseMetadata({
|
|
136
|
+
client: this.client, query: { id: id }, signal: signal,
|
|
137
|
+
}));
|
|
123
138
|
return unwrap(res);
|
|
124
139
|
});
|
|
125
140
|
}
|
|
@@ -132,15 +147,17 @@ export class DatabaseApi {
|
|
|
132
147
|
*/
|
|
133
148
|
async checksums(id, format) {
|
|
134
149
|
return withRetry(this.retries, async () => {
|
|
135
|
-
const res = await databaseChecksum({
|
|
136
|
-
client: this.client, query: { id: id, format: format },
|
|
137
|
-
});
|
|
150
|
+
const res = await deadline(this.timeoutMs, (signal) => databaseChecksum({
|
|
151
|
+
client: this.client, query: { id: id, format: format }, signal: signal,
|
|
152
|
+
}));
|
|
138
153
|
return unwrap(res).checksums;
|
|
139
154
|
});
|
|
140
155
|
}
|
|
141
156
|
async downloads() {
|
|
142
157
|
return withRetry(this.retries, async () => {
|
|
143
|
-
const res = await
|
|
158
|
+
const res = await deadline(this.timeoutMs, (signal) => listDownloads({
|
|
159
|
+
client: this.client, signal: signal,
|
|
160
|
+
}));
|
|
144
161
|
return unwrap(res).downloads;
|
|
145
162
|
});
|
|
146
163
|
}
|
|
@@ -154,11 +171,12 @@ export class DatabaseApi {
|
|
|
154
171
|
*/
|
|
155
172
|
async downloadUrl(id, format) {
|
|
156
173
|
return withRetry(this.retries, async () => {
|
|
157
|
-
const res = await downloadRedirect({
|
|
174
|
+
const res = await deadline(this.timeoutMs, (signal) => downloadRedirect({
|
|
158
175
|
client: this.client,
|
|
159
176
|
query: { id: id, format: format },
|
|
160
177
|
redirect: 'manual',
|
|
161
|
-
|
|
178
|
+
signal: signal,
|
|
179
|
+
}));
|
|
162
180
|
if (res.response === undefined) {
|
|
163
181
|
throw new VPNDetectionError('network', 'no response from the API');
|
|
164
182
|
}
|
|
@@ -267,6 +285,32 @@ function unwrap(res) {
|
|
|
267
285
|
// server-supplied Retry-After, which p-retry has no way to know about. A 429
|
|
268
286
|
// carrying that header is the only 429 worth retrying, which is why the wait
|
|
269
287
|
// and the retry decision both key off the same field.
|
|
288
|
+
/**
|
|
289
|
+
* Bound one attempt, and report an expiry as our own error rather than the
|
|
290
|
+
* runtime's `TimeoutError`, whose message says nothing about which call gave up.
|
|
291
|
+
*
|
|
292
|
+
* The signal is built per call, so a retried request gets a fresh budget - the
|
|
293
|
+
* same per-attempt semantics the Go and Python clients have.
|
|
294
|
+
*/
|
|
295
|
+
async function deadline(timeoutMs, fn) {
|
|
296
|
+
const controller = new AbortController();
|
|
297
|
+
let timer;
|
|
298
|
+
// Raced, not left to the signal alone: aborting releases the socket, but only
|
|
299
|
+
// a transport that HONORS the signal then settles, and a substituted `fetch`
|
|
300
|
+
// need not. Clearing the timer stops the losing side rejecting into nothing.
|
|
301
|
+
const expiry = new Promise((_, reject) => {
|
|
302
|
+
timer = setTimeout(() => {
|
|
303
|
+
controller.abort();
|
|
304
|
+
reject(new VPNDetectionError('network', `request timed out after ${timeoutMs}ms`));
|
|
305
|
+
}, timeoutMs);
|
|
306
|
+
});
|
|
307
|
+
try {
|
|
308
|
+
return await Promise.race([fn(controller.signal), expiry]);
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
clearTimeout(timer);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
270
314
|
async function withRetry(retries, fn) {
|
|
271
315
|
try {
|
|
272
316
|
return await pRetry(fn, {
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,15 +37,15 @@ export type LookupResponse = {
|
|
|
37
37
|
*/
|
|
38
38
|
is_cdn?: boolean;
|
|
39
39
|
/**
|
|
40
|
-
* Whether the address was seen in a residential proxy pool.
|
|
40
|
+
* Whether the address was seen in a residential proxy pool. Scale and above.
|
|
41
41
|
*/
|
|
42
42
|
is_resproxy?: boolean;
|
|
43
43
|
/**
|
|
44
|
-
* Whether the address was seen in a datacenter proxy pool.
|
|
44
|
+
* Whether the address was seen in a datacenter proxy pool. Scale and above.
|
|
45
45
|
*/
|
|
46
46
|
is_dcproxy?: boolean;
|
|
47
47
|
/**
|
|
48
|
-
* Whether the address was seen in a mobile proxy pool.
|
|
48
|
+
* Whether the address was seen in a mobile proxy pool. Scale and above.
|
|
49
49
|
*/
|
|
50
50
|
is_mobproxy?: boolean;
|
|
51
51
|
/**
|
|
@@ -105,7 +105,16 @@ export type VpnDetail = {
|
|
|
105
105
|
*/
|
|
106
106
|
confidence?: string;
|
|
107
107
|
/**
|
|
108
|
-
*
|
|
108
|
+
* The class of evidence the attribution rests on, one of four values.
|
|
109
|
+
* Max only.
|
|
110
|
+
*
|
|
111
|
+
* `scan` - we spoke the VPN protocol to the address ourselves and got a
|
|
112
|
+
* valid server response. `scrape` - the operator published the address
|
|
113
|
+
* through its own API, client or configuration. `registry` - public
|
|
114
|
+
* registration or naming records attribute it to the operator.
|
|
115
|
+
* `infer` - the address was extrapolated from confirmed neighbours in
|
|
116
|
+
* the same block.
|
|
117
|
+
*
|
|
109
118
|
*/
|
|
110
119
|
method?: string;
|
|
111
120
|
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Result } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A bound on a numeric member. Every key present must hold, so
|
|
4
|
+
* `{ gte: 5, lt: 100 }` is a range.
|
|
5
|
+
*/
|
|
6
|
+
export interface NumericBound {
|
|
7
|
+
gte?: number;
|
|
8
|
+
gt?: number;
|
|
9
|
+
lte?: number;
|
|
10
|
+
lt?: number;
|
|
11
|
+
}
|
|
12
|
+
type LeafCondition<T> = T extends number ? number | number[] | NumericBound : T extends string ? string | string[] : T extends boolean ? boolean : never;
|
|
13
|
+
type ConditionOn<T> = {
|
|
14
|
+
[K in keyof T]?: NonNullable<T[K]> extends object ? ConditionOn<NonNullable<T[K]>> : LeafCondition<NonNullable<T[K]>> | false | null;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* What makes a request worth blocking, written in the shape of a `Result`.
|
|
18
|
+
*
|
|
19
|
+
* Only the members you name are considered, and they must all hold. A member
|
|
20
|
+
* set to `false` or `null` is ignored entirely - a condition states the
|
|
21
|
+
* positive signals you act on, so there is no way to write "block when this is
|
|
22
|
+
* false", which would otherwise read as blocking everybody.
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* { isVpn: true, vpn: { provider: 'nordvpn' } }
|
|
26
|
+
* { isResproxy: true, resproxy: { hits: { gte: 5 } } }
|
|
27
|
+
* { isTor: true, vpn: { confidence: ['high', 'medium'] } }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* A list means OR, so any one of its entries blocking is enough.
|
|
31
|
+
*/
|
|
32
|
+
export type BlockCondition = ConditionOn<Omit<Result, 'raw'>>;
|
|
33
|
+
/** Whether an answer satisfies the condition, and should therefore be blocked. */
|
|
34
|
+
export declare function matchesCondition(condition: BlockCondition | BlockCondition[], result: Result): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* The top-level members a condition names that this answer did not carry.
|
|
37
|
+
*
|
|
38
|
+
* A field your plan does not include is absent rather than false, so a
|
|
39
|
+
* condition naming one can never match and the block would silently never
|
|
40
|
+
* fire. Gating is per top-level member, which is why only the first segment of
|
|
41
|
+
* each path is checked: `vpn` present but empty is a real answer meaning the
|
|
42
|
+
* flag is false, not a plan gap.
|
|
43
|
+
*
|
|
44
|
+
* A locally answered bogon needs no special case: it is synthesized in the
|
|
45
|
+
* widest shape, so every member is present and nothing reads as missing. The
|
|
46
|
+
* corpus pins that, because narrowing the synthesized shape would start
|
|
47
|
+
* reporting a plan gap on every private address.
|
|
48
|
+
*/
|
|
49
|
+
export declare function missingMembers(condition: BlockCondition | BlockCondition[], result: Result): string[];
|
|
50
|
+
/**
|
|
51
|
+
* How many leaf constraints a condition actually carries.
|
|
52
|
+
*
|
|
53
|
+
* Callers use this to reject a condition that constrains nothing: with every
|
|
54
|
+
* entry ignored there is nothing left to satisfy, so it would match every
|
|
55
|
+
* answer and block all traffic. Nobody writes that on purpose, and failing at
|
|
56
|
+
* construction beats discovering it in production.
|
|
57
|
+
*/
|
|
58
|
+
export declare function constraintCount(condition: unknown): number;
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/** Whether an answer satisfies the condition, and should therefore be blocked. */
|
|
2
|
+
export function matchesCondition(condition, result) {
|
|
3
|
+
const any = Array.isArray(condition) ? condition : [condition];
|
|
4
|
+
return any.some((one) => matchesObject(one, result));
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The top-level members a condition names that this answer did not carry.
|
|
8
|
+
*
|
|
9
|
+
* A field your plan does not include is absent rather than false, so a
|
|
10
|
+
* condition naming one can never match and the block would silently never
|
|
11
|
+
* fire. Gating is per top-level member, which is why only the first segment of
|
|
12
|
+
* each path is checked: `vpn` present but empty is a real answer meaning the
|
|
13
|
+
* flag is false, not a plan gap.
|
|
14
|
+
*
|
|
15
|
+
* A locally answered bogon needs no special case: it is synthesized in the
|
|
16
|
+
* widest shape, so every member is present and nothing reads as missing. The
|
|
17
|
+
* corpus pins that, because narrowing the synthesized shape would start
|
|
18
|
+
* reporting a plan gap on every private address.
|
|
19
|
+
*/
|
|
20
|
+
export function missingMembers(condition, result) {
|
|
21
|
+
const any = Array.isArray(condition) ? condition : [condition];
|
|
22
|
+
const missing = new Set();
|
|
23
|
+
for (const one of any) {
|
|
24
|
+
for (const [member, want] of Object.entries(one)) {
|
|
25
|
+
if (constraintCount(want) > 0 && !(member in result)) {
|
|
26
|
+
missing.add(member);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return [...missing];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* How many leaf constraints a condition actually carries.
|
|
34
|
+
*
|
|
35
|
+
* Callers use this to reject a condition that constrains nothing: with every
|
|
36
|
+
* entry ignored there is nothing left to satisfy, so it would match every
|
|
37
|
+
* answer and block all traffic. Nobody writes that on purpose, and failing at
|
|
38
|
+
* construction beats discovering it in production.
|
|
39
|
+
*/
|
|
40
|
+
export function constraintCount(condition) {
|
|
41
|
+
if (condition === false || condition === null || condition === undefined) {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(condition)) {
|
|
45
|
+
return condition.reduce((n, entry) => n + constraintCount(entry), 0);
|
|
46
|
+
}
|
|
47
|
+
if (isNumericBound(condition)) {
|
|
48
|
+
return 1;
|
|
49
|
+
}
|
|
50
|
+
if (typeof condition === 'object') {
|
|
51
|
+
return Object.values(condition).reduce((n, v) => n + constraintCount(v), 0);
|
|
52
|
+
}
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
function matchesObject(condition, value) {
|
|
56
|
+
for (const [key, want] of Object.entries(condition)) {
|
|
57
|
+
if (constraintCount(want) === 0) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (!(key in value) || !matchesValue(want, value[key])) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
function matchesValue(want, got) {
|
|
67
|
+
if (Array.isArray(want)) {
|
|
68
|
+
return want.some((entry) => matchesValue(entry, got));
|
|
69
|
+
}
|
|
70
|
+
if (isNumericBound(want)) {
|
|
71
|
+
return matchesBound(want, got);
|
|
72
|
+
}
|
|
73
|
+
if (typeof want === 'object' && want !== null) {
|
|
74
|
+
return isRecord(got) && matchesObject(want, got);
|
|
75
|
+
}
|
|
76
|
+
// Providers are lowercase slugs on the wire and a caller should not have to
|
|
77
|
+
// know that, so a string compares without case.
|
|
78
|
+
if (typeof want === 'string' && typeof got === 'string') {
|
|
79
|
+
return want.toLowerCase() === got.toLowerCase();
|
|
80
|
+
}
|
|
81
|
+
return want === got;
|
|
82
|
+
}
|
|
83
|
+
function matchesBound(bound, got) {
|
|
84
|
+
if (typeof got !== 'number') {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
if (bound.gte !== undefined && got < bound.gte) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
if (bound.gt !== undefined && got <= bound.gt) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
if (bound.lte !== undefined && got > bound.lte) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
if (bound.lt !== undefined && got >= bound.lt) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
const BOUND_KEYS = ['gte', 'gt', 'lte', 'lt'];
|
|
102
|
+
function isNumericBound(value) {
|
|
103
|
+
if (!isRecord(value)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
const keys = Object.keys(value);
|
|
107
|
+
return keys.length > 0 && keys.every((k) => BOUND_KEYS.includes(k));
|
|
108
|
+
}
|
|
109
|
+
function isRecord(value) {
|
|
110
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=condition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"condition.js","sourceRoot":"","sources":["../../src/middleware/condition.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { VPNDetection, type CacheOptions } from '../client.js';
|
|
2
|
+
import { VPNDetectionError } from '../errors.js';
|
|
3
|
+
import type { Result } from '../types.js';
|
|
4
|
+
import { type BlockCondition } from './condition.js';
|
|
5
|
+
/**
|
|
6
|
+
* Enough of an incoming request for a selector to work with, whatever
|
|
7
|
+
* framework it came from. An adapter supplies one of these per request.
|
|
8
|
+
*/
|
|
9
|
+
export interface RequestView {
|
|
10
|
+
/** A request header by name, case-insensitively. */
|
|
11
|
+
header(name: string): string | undefined;
|
|
12
|
+
/** The framework's own client-address accessor, whatever that resolves to here. */
|
|
13
|
+
frameworkIp(): string | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* How the client address is decided.
|
|
17
|
+
*
|
|
18
|
+
* There is no portable answer: a framework's own accessor may return the
|
|
19
|
+
* socket peer, or may already have walked a proxy chain, depending on the
|
|
20
|
+
* framework and on how the application configured it. You know your framework
|
|
21
|
+
* and your edge, so this is yours to choose.
|
|
22
|
+
*/
|
|
23
|
+
export type IpSelector<Req> = (request: Req) => string | undefined;
|
|
24
|
+
/** What a lookup attached to the request, whether or not it succeeded. */
|
|
25
|
+
export interface Lookup {
|
|
26
|
+
/** The address that was classified, as the selector resolved it. */
|
|
27
|
+
ip?: string;
|
|
28
|
+
/** The answer. Absent when the lookup failed. */
|
|
29
|
+
result?: Result;
|
|
30
|
+
/** Why the lookup failed. Absent when it succeeded. */
|
|
31
|
+
error?: VPNDetectionError;
|
|
32
|
+
/** Whether the condition matched. Always false when no condition was configured. */
|
|
33
|
+
blocked: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** What to do when a condition names a member the plan does not serve. */
|
|
36
|
+
export type MissingFieldAction = 'warn' | 'throw' | 'ignore';
|
|
37
|
+
export interface MiddlewareOptions<Req> {
|
|
38
|
+
/**
|
|
39
|
+
* An existing client to use. Prefer this if you already hold one: two
|
|
40
|
+
* clients mean two caches, and a cache is per instance because two keys can
|
|
41
|
+
* be on different plans and entitled to different fields.
|
|
42
|
+
*/
|
|
43
|
+
client?: VPNDetection;
|
|
44
|
+
/** Your API key. Ignored when `client` is given. */
|
|
45
|
+
apiKey?: string;
|
|
46
|
+
/** Ignored when `client` is given. */
|
|
47
|
+
baseUrl?: string;
|
|
48
|
+
/** Ignored when `client` is given. Pass `false` to disable caching. */
|
|
49
|
+
cache?: CacheOptions | false;
|
|
50
|
+
/**
|
|
51
|
+
* How long a lookup may hold the request, in milliseconds. Default 2500.
|
|
52
|
+
*
|
|
53
|
+
* This sits on the request path, so it is a much tighter bound than the
|
|
54
|
+
* client's own 30s default.
|
|
55
|
+
*/
|
|
56
|
+
timeoutMs?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Retry attempts for a transient failure. Default 0, unlike the client's 2:
|
|
59
|
+
* on a request path, failing open quickly beats holding a visitor while we
|
|
60
|
+
* try again.
|
|
61
|
+
*/
|
|
62
|
+
retries?: number;
|
|
63
|
+
/** How the client address is decided. Defaults to the framework's own accessor. */
|
|
64
|
+
ipSelector?: IpSelector<Req>;
|
|
65
|
+
/**
|
|
66
|
+
* What to block on. Omit it to only enrich the request and leave the
|
|
67
|
+
* decision to your own code.
|
|
68
|
+
*/
|
|
69
|
+
blockCondition?: BlockCondition | BlockCondition[];
|
|
70
|
+
/**
|
|
71
|
+
* Block when the lookup itself fails. Default false, so our outage does not
|
|
72
|
+
* become yours.
|
|
73
|
+
*/
|
|
74
|
+
failClosed?: boolean;
|
|
75
|
+
/** What to do when the condition names a member your plan does not serve. Default `warn`. */
|
|
76
|
+
onMissingField?: MissingFieldAction;
|
|
77
|
+
/** Skip classification for this request entirely. */
|
|
78
|
+
skip?: (request: Req) => boolean;
|
|
79
|
+
/** Where warnings go. Defaults to `console.warn`. */
|
|
80
|
+
onWarn?: (message: string) => void;
|
|
81
|
+
}
|
|
82
|
+
export interface Core<Req> {
|
|
83
|
+
/** Classify one request. Answers `undefined` when `skip` claimed it. */
|
|
84
|
+
evaluate(request: Req): Promise<Lookup | undefined>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The framework-agnostic half of a middleware: resolve an address, classify it,
|
|
88
|
+
* and decide whether the condition matched.
|
|
89
|
+
*
|
|
90
|
+
* Adapters own the framework-shaped parts - reading a request, attaching the
|
|
91
|
+
* answer, and refusing a request - and share everything here.
|
|
92
|
+
*/
|
|
93
|
+
export declare function createCore<Req>(options: MiddlewareOptions<Req>, defaultIpSelector: IpSelector<Req>): Core<Req>;
|
|
94
|
+
/**
|
|
95
|
+
* Selectors bound to one framework's request type.
|
|
96
|
+
*
|
|
97
|
+
* An adapter calls this once with a function that exposes its own request, and
|
|
98
|
+
* gets the shared implementations back under its own signature - so a caller
|
|
99
|
+
* writing a custom selector still works with the request object they know.
|
|
100
|
+
*/
|
|
101
|
+
export declare function bindSelectors<Req>(view: (request: Req) => RequestView): {
|
|
102
|
+
/**
|
|
103
|
+
* The framework's own client-address accessor. What that resolves to
|
|
104
|
+
* depends on the framework and on how you configured it.
|
|
105
|
+
*/
|
|
106
|
+
defaultIpSelector: (request: Req) => string | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* An address from `X-Forwarded-For`.
|
|
109
|
+
*
|
|
110
|
+
* **The left-most entry is whatever the caller sent.** Proxies append,
|
|
111
|
+
* so a visitor who sets the header themselves appears first in the list
|
|
112
|
+
* and this returns their forgery. It is only trustworthy when an edge
|
|
113
|
+
* you control overwrites the header rather than appending to it. When
|
|
114
|
+
* you know how many proxies sit in front, count from the right with
|
|
115
|
+
* `depth` instead: `depth: 1` is the address your nearest proxy saw.
|
|
116
|
+
*/
|
|
117
|
+
xffIpSelector: (options?: {
|
|
118
|
+
depth?: number;
|
|
119
|
+
}) => (request: Req) => string | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* An address from a single-value header, by name - for an edge that
|
|
122
|
+
* writes one. `headerIpSelector('CF-Connecting-IP')` behind Cloudflare,
|
|
123
|
+
* `headerIpSelector('True-Client-IP')` behind Akamai, and so on.
|
|
124
|
+
*
|
|
125
|
+
* Falls back to the framework's accessor when the header is absent.
|
|
126
|
+
*/
|
|
127
|
+
headerIpSelector: (name: string) => (request: Req) => string | undefined;
|
|
128
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { isBogon } from '../bogon.js';
|
|
2
|
+
import { VPNDetection } from '../client.js';
|
|
3
|
+
import { VPNDetectionError } from '../errors.js';
|
|
4
|
+
import { constraintCount, matchesCondition, missingMembers } from './condition.js';
|
|
5
|
+
/**
|
|
6
|
+
* The framework-agnostic half of a middleware: resolve an address, classify it,
|
|
7
|
+
* and decide whether the condition matched.
|
|
8
|
+
*
|
|
9
|
+
* Adapters own the framework-shaped parts - reading a request, attaching the
|
|
10
|
+
* answer, and refusing a request - and share everything here.
|
|
11
|
+
*/
|
|
12
|
+
export function createCore(options, defaultIpSelector) {
|
|
13
|
+
const condition = options.blockCondition;
|
|
14
|
+
if (condition !== undefined && constraintCount(condition) === 0) {
|
|
15
|
+
throw new Error('vpndetection: blockCondition constrains nothing, which would block every request. '
|
|
16
|
+
+ 'A member set to false or null is ignored; state the positive signals you act on.');
|
|
17
|
+
}
|
|
18
|
+
const client = options.client ?? new VPNDetection({
|
|
19
|
+
apiKey: options.apiKey,
|
|
20
|
+
baseUrl: options.baseUrl,
|
|
21
|
+
cache: options.cache,
|
|
22
|
+
});
|
|
23
|
+
const selector = options.ipSelector ?? defaultIpSelector;
|
|
24
|
+
const lookupOptions = {
|
|
25
|
+
timeoutMs: options.timeoutMs ?? 2500,
|
|
26
|
+
retries: options.retries ?? 0,
|
|
27
|
+
};
|
|
28
|
+
const warn = onceEach(options.onWarn ?? ((message) => console.warn(message)));
|
|
29
|
+
return {
|
|
30
|
+
evaluate: async (request) => {
|
|
31
|
+
if (options.skip?.(request) === true) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
const ip = selector(request)?.trim();
|
|
35
|
+
if (ip === undefined || ip === '') {
|
|
36
|
+
warn('could not resolve a client address from this request; '
|
|
37
|
+
+ 'pass an ipSelector that knows where yours comes from');
|
|
38
|
+
return {
|
|
39
|
+
error: new VPNDetectionError('bad_request', 'no client address on the request'),
|
|
40
|
+
blocked: options.failClosed === true,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (isBogon(ip)) {
|
|
44
|
+
// Expected in local development. Anywhere else it means a proxy
|
|
45
|
+
// sits in front and its own address is what reached us.
|
|
46
|
+
warn(`resolved the client address as ${ip}, which is not a public address. `
|
|
47
|
+
+ 'If this application runs behind a proxy or load balancer, configure its '
|
|
48
|
+
+ 'trusted-proxy setting or pass an ipSelector that reads your edge\'s header.');
|
|
49
|
+
}
|
|
50
|
+
let result;
|
|
51
|
+
try {
|
|
52
|
+
result = await client.lookup(ip, lookupOptions);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
return {
|
|
56
|
+
ip: ip,
|
|
57
|
+
error: err instanceof VPNDetectionError
|
|
58
|
+
? err
|
|
59
|
+
: new VPNDetectionError('network', String(err)),
|
|
60
|
+
blocked: options.failClosed === true,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (condition !== undefined) {
|
|
64
|
+
reportMissing(condition, result, options.onMissingField ?? 'warn', warn);
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
ip: ip,
|
|
68
|
+
result: result,
|
|
69
|
+
blocked: condition !== undefined && matchesCondition(condition, result),
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Selectors bound to one framework's request type.
|
|
76
|
+
*
|
|
77
|
+
* An adapter calls this once with a function that exposes its own request, and
|
|
78
|
+
* gets the shared implementations back under its own signature - so a caller
|
|
79
|
+
* writing a custom selector still works with the request object they know.
|
|
80
|
+
*/
|
|
81
|
+
export function bindSelectors(view) {
|
|
82
|
+
return {
|
|
83
|
+
/**
|
|
84
|
+
* The framework's own client-address accessor. What that resolves to
|
|
85
|
+
* depends on the framework and on how you configured it.
|
|
86
|
+
*/
|
|
87
|
+
defaultIpSelector: (request) => view(request).frameworkIp(),
|
|
88
|
+
/**
|
|
89
|
+
* An address from `X-Forwarded-For`.
|
|
90
|
+
*
|
|
91
|
+
* **The left-most entry is whatever the caller sent.** Proxies append,
|
|
92
|
+
* so a visitor who sets the header themselves appears first in the list
|
|
93
|
+
* and this returns their forgery. It is only trustworthy when an edge
|
|
94
|
+
* you control overwrites the header rather than appending to it. When
|
|
95
|
+
* you know how many proxies sit in front, count from the right with
|
|
96
|
+
* `depth` instead: `depth: 1` is the address your nearest proxy saw.
|
|
97
|
+
*/
|
|
98
|
+
xffIpSelector: (options = {}) => (request) => {
|
|
99
|
+
const v = view(request);
|
|
100
|
+
const chain = (v.header('x-forwarded-for') ?? '')
|
|
101
|
+
.split(',').map((e) => e.trim()).filter((e) => e !== '');
|
|
102
|
+
if (chain.length === 0) {
|
|
103
|
+
return v.frameworkIp();
|
|
104
|
+
}
|
|
105
|
+
const depth = options.depth ?? 0;
|
|
106
|
+
return depth <= 0 ? chain[0] : chain[chain.length - depth];
|
|
107
|
+
},
|
|
108
|
+
/**
|
|
109
|
+
* An address from a single-value header, by name - for an edge that
|
|
110
|
+
* writes one. `headerIpSelector('CF-Connecting-IP')` behind Cloudflare,
|
|
111
|
+
* `headerIpSelector('True-Client-IP')` behind Akamai, and so on.
|
|
112
|
+
*
|
|
113
|
+
* Falls back to the framework's accessor when the header is absent.
|
|
114
|
+
*/
|
|
115
|
+
headerIpSelector: (name) => (request) => {
|
|
116
|
+
const v = view(request);
|
|
117
|
+
return v.header(name)?.trim() || v.frameworkIp();
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function reportMissing(condition, result, action, warn) {
|
|
122
|
+
if (action === 'ignore') {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const missing = missingMembers(condition, result);
|
|
126
|
+
if (missing.length === 0) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const message = `blockCondition names ${missing.join(', ')}, which your plan does not `
|
|
130
|
+
+ 'include, so those terms can never match. An absent member means "not in your plan", '
|
|
131
|
+
+ 'not "checked, and no".';
|
|
132
|
+
if (action === 'throw') {
|
|
133
|
+
throw new Error(`vpndetection: ${message}`);
|
|
134
|
+
}
|
|
135
|
+
warn(message);
|
|
136
|
+
}
|
|
137
|
+
// A misconfiguration is the same on every request, so saying so once is a
|
|
138
|
+
// warning and saying so a million times is an outage of its own.
|
|
139
|
+
function onceEach(sink) {
|
|
140
|
+
const seen = new Set();
|
|
141
|
+
return (message) => {
|
|
142
|
+
if (seen.has(message)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
seen.add(message);
|
|
146
|
+
sink(`[vpndetection] ${message}`);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/middleware/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { bindSelectors, createCore } from './core.js';
|
|
2
|
+
export type { Core, IpSelector, Lookup, MiddlewareOptions, MissingFieldAction, RequestView, } from './core.js';
|
|
3
|
+
export { constraintCount, matchesCondition, missingMembers } from './condition.js';
|
|
4
|
+
export type { BlockCondition, NumericBound } from './condition.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAItD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vpndetection",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Official Node.js client library for the VPNDetection API. Detect VPNs, proxies, Tor, hosting and CDN IPs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
"types": "./dist/index.d.ts",
|
|
35
35
|
"default": "./dist/index.js"
|
|
36
36
|
},
|
|
37
|
+
"./middleware": {
|
|
38
|
+
"types": "./dist/middleware/index.d.ts",
|
|
39
|
+
"default": "./dist/middleware/index.js"
|
|
40
|
+
},
|
|
37
41
|
"./package.json": "./package.json"
|
|
38
42
|
},
|
|
39
43
|
"files": [
|