@push.rocks/smartnetwork 4.8.0 → 4.10.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_rust/rustnetwork_linux_amd64 +0 -0
- package/dist_rust/rustnetwork_linux_arm64 +0 -0
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/helpers/ip.d.ts +21 -0
- package/dist_ts/helpers/ip.js +80 -1
- package/dist_ts/index.d.ts +1 -1
- package/dist_ts/index.js +2 -2
- package/dist_ts/smartnetwork.classes.domainintelligence.d.ts +13 -58
- package/dist_ts/smartnetwork.classes.domainintelligence.js +45 -319
- package/dist_ts/smartnetwork.classes.ipintelligence.d.ts +3 -34
- package/dist_ts/smartnetwork.classes.ipintelligence.js +18 -281
- package/dist_ts/smartnetwork.plugins.d.ts +2 -1
- package/dist_ts/smartnetwork.plugins.js +3 -2
- package/package.json +5 -4
- package/readme.md +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/helpers/ip.ts +79 -0
- package/ts/index.ts +1 -1
- package/ts/smartnetwork.classes.domainintelligence.ts +48 -341
- package/ts/smartnetwork.classes.ipintelligence.ts +19 -310
- package/ts/smartnetwork.plugins.ts +2 -1
|
@@ -3,13 +3,11 @@ import { getLogger } from './logging.js';
|
|
|
3
3
|
// CDN URLs for GeoLite2 MMDB files (served via jsDelivr from npm packages)
|
|
4
4
|
const CITY_MMDB_URL = 'https://cdn.jsdelivr.net/npm/@ip-location-db/geolite2-city-mmdb/geolite2-city-ipv4.mmdb';
|
|
5
5
|
const ASN_MMDB_URL = 'https://cdn.jsdelivr.net/npm/@ip-location-db/geolite2-asn-mmdb/geolite2-asn-ipv4.mmdb';
|
|
6
|
-
// IANA bootstrap for RDAP
|
|
7
|
-
const IANA_BOOTSTRAP_IPV4_URL = 'https://data.iana.org/rdap/ipv4.json';
|
|
8
6
|
const DEFAULT_DB_MAX_AGE = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
9
7
|
const DEFAULT_TIMEOUT = 5000;
|
|
10
8
|
/**
|
|
11
9
|
* IpIntelligence provides IP address intelligence by combining three data sources:
|
|
12
|
-
* - RDAP (direct to RIRs) for registration/org data
|
|
10
|
+
* - RDAP (direct to RIRs, via @push.rocks/smartwhois) for registration/org data
|
|
13
11
|
* - Team Cymru DNS for ASN
|
|
14
12
|
* - MaxMind GeoLite2 (in-memory MMDB) for geolocation
|
|
15
13
|
*/
|
|
@@ -21,12 +19,14 @@ export class IpIntelligence {
|
|
|
21
19
|
this.asnReader = null;
|
|
22
20
|
this.lastFetchTime = 0;
|
|
23
21
|
this.refreshPromise = null;
|
|
24
|
-
// RDAP bootstrap cache
|
|
25
|
-
this.bootstrapEntries = null;
|
|
26
|
-
this.bootstrapPromise = null;
|
|
27
22
|
this.dbMaxAge = options?.dbMaxAge ?? DEFAULT_DB_MAX_AGE;
|
|
28
23
|
this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;
|
|
29
24
|
this.sharedDnsClient = options?.dnsClient ?? null;
|
|
25
|
+
this.rdapClient = new plugins.smartwhois.RdapClient({
|
|
26
|
+
requestTimeoutMs: this.timeout,
|
|
27
|
+
totalTimeoutMs: this.timeout,
|
|
28
|
+
userAgent: '@push.rocks/smartnetwork',
|
|
29
|
+
});
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Get comprehensive IP intelligence for the given IP address.
|
|
@@ -91,228 +91,27 @@ export class IpIntelligence {
|
|
|
91
91
|
// the asnOrg remains null (we don't do an additional lookup)
|
|
92
92
|
return result;
|
|
93
93
|
}
|
|
94
|
-
// ─── RDAP Subsystem
|
|
94
|
+
// ─── RDAP Subsystem (delegated to @push.rocks/smartwhois) ───────────
|
|
95
95
|
/**
|
|
96
|
-
*
|
|
97
|
-
*/
|
|
98
|
-
async ensureBootstrap() {
|
|
99
|
-
if (this.bootstrapEntries)
|
|
100
|
-
return;
|
|
101
|
-
if (this.bootstrapPromise) {
|
|
102
|
-
await this.bootstrapPromise;
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
this.bootstrapPromise = (async () => {
|
|
106
|
-
try {
|
|
107
|
-
const controller = new AbortController();
|
|
108
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
109
|
-
try {
|
|
110
|
-
const response = await fetch(IANA_BOOTSTRAP_IPV4_URL, {
|
|
111
|
-
signal: controller.signal,
|
|
112
|
-
headers: { 'User-Agent': '@push.rocks/smartnetwork' },
|
|
113
|
-
});
|
|
114
|
-
if (!response.ok)
|
|
115
|
-
throw new Error(`HTTP ${response.status}`);
|
|
116
|
-
const data = await response.json();
|
|
117
|
-
const entries = [];
|
|
118
|
-
for (const [prefixes, urls] of data.services) {
|
|
119
|
-
const baseUrl = urls[0]; // first URL is preferred
|
|
120
|
-
for (const prefix of prefixes) {
|
|
121
|
-
const [network, bits] = prefix.split('/');
|
|
122
|
-
entries.push({
|
|
123
|
-
prefix,
|
|
124
|
-
prefixNum: this.ipToNumber(network),
|
|
125
|
-
maskBits: parseInt(bits, 10),
|
|
126
|
-
baseUrl: baseUrl.replace(/\/$/, ''), // strip trailing slash
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
// Sort by mask bits descending for longest-prefix match
|
|
131
|
-
entries.sort((a, b) => b.maskBits - a.maskBits);
|
|
132
|
-
this.bootstrapEntries = entries;
|
|
133
|
-
}
|
|
134
|
-
finally {
|
|
135
|
-
clearTimeout(timeoutId);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
catch (err) {
|
|
139
|
-
this.logger.debug?.(`Failed to load RDAP bootstrap: ${err.message}`);
|
|
140
|
-
this.bootstrapEntries = []; // empty = all RDAP lookups will skip
|
|
141
|
-
}
|
|
142
|
-
})();
|
|
143
|
-
await this.bootstrapPromise;
|
|
144
|
-
this.bootstrapPromise = null;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Find the RDAP base URL for a given IP via longest-prefix match
|
|
148
|
-
*/
|
|
149
|
-
matchRir(ip) {
|
|
150
|
-
if (!this.bootstrapEntries || this.bootstrapEntries.length === 0)
|
|
151
|
-
return null;
|
|
152
|
-
const ipNum = this.ipToNumber(ip);
|
|
153
|
-
for (const entry of this.bootstrapEntries) {
|
|
154
|
-
const mask = (0xFFFFFFFF << (32 - entry.maskBits)) >>> 0;
|
|
155
|
-
if ((ipNum & mask) === (entry.prefixNum & mask)) {
|
|
156
|
-
return entry.baseUrl;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Query RDAP for registration data
|
|
96
|
+
* Query RDAP for registration data via the smartwhois RdapClient (IPv4 and IPv6).
|
|
163
97
|
*/
|
|
164
98
|
async queryRdap(ip) {
|
|
165
|
-
await this.ensureBootstrap();
|
|
166
|
-
const baseUrl = this.matchRir(ip);
|
|
167
|
-
if (!baseUrl)
|
|
168
|
-
return null;
|
|
169
|
-
const controller = new AbortController();
|
|
170
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
171
99
|
try {
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
headers: {
|
|
175
|
-
'Accept': 'application/rdap+json',
|
|
176
|
-
'User-Agent': '@push.rocks/smartnetwork',
|
|
177
|
-
},
|
|
178
|
-
});
|
|
179
|
-
if (!response.ok)
|
|
100
|
+
const rdapRecord = await this.rdapClient.lookupIp(ip);
|
|
101
|
+
if (!rdapRecord)
|
|
180
102
|
return null;
|
|
181
|
-
const data = await response.json();
|
|
182
|
-
let registrantOrg = null;
|
|
183
|
-
let registrantCountry = data.country || null;
|
|
184
|
-
let abuseContact = null;
|
|
185
|
-
const { networkRange, networkCidrs } = this.parseRdapNetworkInfo(data);
|
|
186
|
-
// Parse entities
|
|
187
|
-
if (data.entities && Array.isArray(data.entities)) {
|
|
188
|
-
for (const entity of data.entities) {
|
|
189
|
-
const roles = entity.roles || [];
|
|
190
|
-
if (roles.includes('registrant') || roles.includes('administrative')) {
|
|
191
|
-
const orgName = this.extractVcardFn(entity);
|
|
192
|
-
if (orgName)
|
|
193
|
-
registrantOrg = orgName;
|
|
194
|
-
// Try to get country from registrant address if not at top level
|
|
195
|
-
if (!registrantCountry) {
|
|
196
|
-
registrantCountry = this.extractVcardCountry(entity);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (roles.includes('abuse')) {
|
|
200
|
-
abuseContact = this.extractVcardEmail(entity);
|
|
201
|
-
// Check nested entities for abuse contact
|
|
202
|
-
if (!abuseContact && entity.entities) {
|
|
203
|
-
for (const subEntity of entity.entities) {
|
|
204
|
-
const subRoles = subEntity.roles || [];
|
|
205
|
-
if (subRoles.includes('abuse')) {
|
|
206
|
-
abuseContact = this.extractVcardEmail(subEntity);
|
|
207
|
-
if (abuseContact)
|
|
208
|
-
break;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
return { registrantOrg, registrantCountry, networkRange, networkCidrs, abuseContact };
|
|
216
|
-
}
|
|
217
|
-
catch (err) {
|
|
218
|
-
this.logger.debug?.(`RDAP query failed for ${ip}: ${err.message}`);
|
|
219
|
-
return null;
|
|
220
|
-
}
|
|
221
|
-
finally {
|
|
222
|
-
clearTimeout(timeoutId);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
parseRdapNetworkInfo(data) {
|
|
226
|
-
const cidrs = this.extractRdapCidrs(data);
|
|
227
|
-
if (cidrs.length > 0) {
|
|
228
|
-
return {
|
|
229
|
-
networkRange: cidrs[0],
|
|
230
|
-
networkCidrs: cidrs,
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
if (typeof data.startAddress === 'string' && typeof data.endAddress === 'string') {
|
|
234
|
-
const rangeCidrs = this.ipv4RangeToCidrs(data.startAddress, data.endAddress);
|
|
235
103
|
return {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
networkCidrs:
|
|
104
|
+
registrantOrg: rdapRecord.registrantOrg ?? null,
|
|
105
|
+
registrantCountry: rdapRecord.registrantCountry ?? null,
|
|
106
|
+
networkRange: rdapRecord.networkRange ?? null,
|
|
107
|
+
networkCidrs: rdapRecord.networkCidrs ?? null,
|
|
108
|
+
abuseContact: rdapRecord.abuseEmail ?? null,
|
|
240
109
|
};
|
|
241
110
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
extractRdapCidrs(data) {
|
|
245
|
-
if (!Array.isArray(data.cidr0_cidrs))
|
|
246
|
-
return [];
|
|
247
|
-
return data.cidr0_cidrs
|
|
248
|
-
.map((cidr) => {
|
|
249
|
-
const prefix = cidr?.v4prefix || cidr?.v6prefix;
|
|
250
|
-
const length = Number(cidr?.length);
|
|
251
|
-
if (typeof prefix !== 'string' || !Number.isInteger(length))
|
|
252
|
-
return null;
|
|
253
|
-
return `${prefix}/${length}`;
|
|
254
|
-
})
|
|
255
|
-
.filter(Boolean);
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Extract the 'fn' (formatted name) from an entity's vcardArray
|
|
259
|
-
*/
|
|
260
|
-
extractVcardFn(entity) {
|
|
261
|
-
if (!entity.vcardArray || !Array.isArray(entity.vcardArray))
|
|
262
|
-
return null;
|
|
263
|
-
const properties = entity.vcardArray[1];
|
|
264
|
-
if (!Array.isArray(properties))
|
|
265
|
-
return null;
|
|
266
|
-
for (const prop of properties) {
|
|
267
|
-
if (Array.isArray(prop) && prop[0] === 'fn') {
|
|
268
|
-
return prop[3] || null;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
return null;
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Extract email from an entity's vcardArray
|
|
275
|
-
*/
|
|
276
|
-
extractVcardEmail(entity) {
|
|
277
|
-
if (!entity.vcardArray || !Array.isArray(entity.vcardArray))
|
|
278
|
-
return null;
|
|
279
|
-
const properties = entity.vcardArray[1];
|
|
280
|
-
if (!Array.isArray(properties))
|
|
281
|
-
return null;
|
|
282
|
-
for (const prop of properties) {
|
|
283
|
-
if (Array.isArray(prop) && prop[0] === 'email') {
|
|
284
|
-
return prop[3] || null;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
return null;
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Extract country from an entity's vcardArray address field
|
|
291
|
-
*/
|
|
292
|
-
extractVcardCountry(entity) {
|
|
293
|
-
if (!entity.vcardArray || !Array.isArray(entity.vcardArray))
|
|
294
|
-
return null;
|
|
295
|
-
const properties = entity.vcardArray[1];
|
|
296
|
-
if (!Array.isArray(properties))
|
|
111
|
+
catch (err) {
|
|
112
|
+
this.logger.debug?.(`RDAP query failed for ${ip}: ${err.message}`);
|
|
297
113
|
return null;
|
|
298
|
-
for (const prop of properties) {
|
|
299
|
-
if (Array.isArray(prop) && prop[0] === 'adr') {
|
|
300
|
-
// The label parameter often contains the full address with country at the end
|
|
301
|
-
const label = prop[1]?.label;
|
|
302
|
-
if (typeof label === 'string') {
|
|
303
|
-
const lines = label.split('\n');
|
|
304
|
-
const lastLine = lines[lines.length - 1]?.trim();
|
|
305
|
-
if (lastLine && lastLine.length > 1)
|
|
306
|
-
return lastLine;
|
|
307
|
-
}
|
|
308
|
-
// Also check the structured value (7-element array, last element is country)
|
|
309
|
-
const value = prop[3];
|
|
310
|
-
if (Array.isArray(value) && value.length >= 7 && value[6]) {
|
|
311
|
-
return value[6];
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
114
|
}
|
|
315
|
-
return null;
|
|
316
115
|
}
|
|
317
116
|
// ─── Team Cymru DNS Subsystem ───────────────────────────────────────
|
|
318
117
|
/**
|
|
@@ -472,67 +271,5 @@ export class IpIntelligence {
|
|
|
472
271
|
}
|
|
473
272
|
return { country, countryCode, city, latitude, longitude, accuracyRadius, timezone, asn, asnOrg };
|
|
474
273
|
}
|
|
475
|
-
// ─── Utilities ──────────────────────────────────────────────────────
|
|
476
|
-
/**
|
|
477
|
-
* Convert an IPv4 address string to a 32-bit unsigned number
|
|
478
|
-
*/
|
|
479
|
-
ipToNumber(ip) {
|
|
480
|
-
const parts = ip.split('.');
|
|
481
|
-
return (((parseInt(parts[0], 10) << 24) |
|
|
482
|
-
(parseInt(parts[1], 10) << 16) |
|
|
483
|
-
(parseInt(parts[2], 10) << 8) |
|
|
484
|
-
parseInt(parts[3], 10)) >>> 0);
|
|
485
|
-
}
|
|
486
|
-
ipv4RangeToCidrs(startIp, endIp) {
|
|
487
|
-
const start = this.ipv4ToBigInt(startIp);
|
|
488
|
-
const end = this.ipv4ToBigInt(endIp);
|
|
489
|
-
if (start === undefined || end === undefined || start > end)
|
|
490
|
-
return [];
|
|
491
|
-
const cidrs = [];
|
|
492
|
-
let current = start;
|
|
493
|
-
while (current <= end) {
|
|
494
|
-
let maxBlockSize = current === 0n ? 1n << 32n : current & -current;
|
|
495
|
-
const remaining = end - current + 1n;
|
|
496
|
-
while (maxBlockSize > remaining) {
|
|
497
|
-
maxBlockSize = maxBlockSize / 2n;
|
|
498
|
-
}
|
|
499
|
-
const prefixLength = 32 - this.powerOfTwoExponent(maxBlockSize);
|
|
500
|
-
cidrs.push(`${this.numberToIpv4(current)}/${prefixLength}`);
|
|
501
|
-
current += maxBlockSize;
|
|
502
|
-
}
|
|
503
|
-
return cidrs;
|
|
504
|
-
}
|
|
505
|
-
ipv4ToBigInt(ip) {
|
|
506
|
-
const parts = ip.trim().split('.');
|
|
507
|
-
if (parts.length !== 4)
|
|
508
|
-
return undefined;
|
|
509
|
-
let result = 0n;
|
|
510
|
-
for (const part of parts) {
|
|
511
|
-
if (!/^\d+$/.test(part))
|
|
512
|
-
return undefined;
|
|
513
|
-
const number = Number(part);
|
|
514
|
-
if (!Number.isInteger(number) || number < 0 || number > 255)
|
|
515
|
-
return undefined;
|
|
516
|
-
result = (result * 256n) + BigInt(number);
|
|
517
|
-
}
|
|
518
|
-
return result;
|
|
519
|
-
}
|
|
520
|
-
numberToIpv4(value) {
|
|
521
|
-
return [
|
|
522
|
-
Number((value >> 24n) & 255n),
|
|
523
|
-
Number((value >> 16n) & 255n),
|
|
524
|
-
Number((value >> 8n) & 255n),
|
|
525
|
-
Number(value & 255n),
|
|
526
|
-
].join('.');
|
|
527
|
-
}
|
|
528
|
-
powerOfTwoExponent(value) {
|
|
529
|
-
let exponent = 0;
|
|
530
|
-
let remaining = value;
|
|
531
|
-
while (remaining > 1n) {
|
|
532
|
-
remaining >>= 1n;
|
|
533
|
-
exponent++;
|
|
534
|
-
}
|
|
535
|
-
return exponent;
|
|
536
|
-
}
|
|
537
274
|
}
|
|
538
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZXR3b3JrLmNsYXNzZXMuaXBpbnRlbGxpZ2VuY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydG5ldHdvcmsuY2xhc3Nlcy5pcGludGVsbGlnZW5jZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLDJCQUEyQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUE2RHpDLDJFQUEyRTtBQUMzRSxNQUFNLGFBQWEsR0FBRyx5RkFBeUYsQ0FBQztBQUNoSCxNQUFNLFlBQVksR0FBRyx1RkFBdUYsQ0FBQztBQUU3RywwQkFBMEI7QUFDMUIsTUFBTSx1QkFBdUIsR0FBRyxzQ0FBc0MsQ0FBQztBQUV2RSxNQUFNLGtCQUFrQixHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxTQUFTO0FBQzdELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQztBQWlCN0I7Ozs7O0dBS0c7QUFDSCxNQUFNLE9BQU8sY0FBYztJQWtCekIsWUFBWSxPQUFnQztRQWpCM0IsV0FBTSxHQUFHLFNBQVMsRUFBRSxDQUFDO1FBSXRDLHVDQUF1QztRQUMvQixlQUFVLEdBQXNELElBQUksQ0FBQztRQUNyRSxjQUFTLEdBQStCLElBQUksQ0FBQztRQUM3QyxrQkFBYSxHQUFHLENBQUMsQ0FBQztRQUNsQixtQkFBYyxHQUF5QixJQUFJLENBQUM7UUFFcEQsdUJBQXVCO1FBQ2YscUJBQWdCLEdBQTZCLElBQUksQ0FBQztRQUNsRCxxQkFBZ0IsR0FBeUIsSUFBSSxDQUFDO1FBTXBELElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxFQUFFLFFBQVEsSUFBSSxrQkFBa0IsQ0FBQztRQUN4RCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sRUFBRSxPQUFPLElBQUksZUFBZSxDQUFDO1FBQ25ELElBQUksQ0FBQyxlQUFlLEdBQUcsT0FB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
|
|
275
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZXR3b3JrLmNsYXNzZXMuaXBpbnRlbGxpZ2VuY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydG5ldHdvcmsuY2xhc3Nlcy5pcGludGVsbGlnZW5jZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLDJCQUEyQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUE2RHpDLDJFQUEyRTtBQUMzRSxNQUFNLGFBQWEsR0FBRyx5RkFBeUYsQ0FBQztBQUNoSCxNQUFNLFlBQVksR0FBRyx1RkFBdUYsQ0FBQztBQUU3RyxNQUFNLGtCQUFrQixHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxTQUFTO0FBQzdELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQztBQUU3Qjs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyxjQUFjO0lBaUJ6QixZQUFZLE9BQWdDO1FBaEIzQixXQUFNLEdBQUcsU0FBUyxFQUFFLENBQUM7UUFJdEMsdUNBQXVDO1FBQy9CLGVBQVUsR0FBc0QsSUFBSSxDQUFDO1FBQ3JFLGNBQVMsR0FBK0IsSUFBSSxDQUFDO1FBQzdDLGtCQUFhLEdBQUcsQ0FBQyxDQUFDO1FBQ2xCLG1CQUFjLEdBQXlCLElBQUksQ0FBQztRQVNsRCxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sRUFBRSxRQUFRLElBQUksa0JBQWtCLENBQUM7UUFDeEQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLEVBQUUsT0FBTyxJQUFJLGVBQWUsQ0FBQztRQUNuRCxJQUFJLENBQUMsZUFBZSxHQUFHLE9BQU8sRUFBRSxTQUFTLElBQUksSUFBSSxDQUFDO1FBQ2xELElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQztZQUNsRCxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsT0FB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
|
|
@@ -4,6 +4,7 @@ import * as perfHooks from 'node:perf_hooks';
|
|
|
4
4
|
export { os, https, perfHooks };
|
|
5
5
|
import * as smartdns from '@push.rocks/smartdns';
|
|
6
6
|
import * as smartrust from '@push.rocks/smartrust';
|
|
7
|
-
|
|
7
|
+
import * as smartwhois from '@push.rocks/smartwhois';
|
|
8
|
+
export { smartdns, smartrust, smartwhois };
|
|
8
9
|
import * as maxmind from 'maxmind';
|
|
9
10
|
export { maxmind };
|
|
@@ -6,8 +6,9 @@ export { os, https, perfHooks };
|
|
|
6
6
|
// @pushrocks scope
|
|
7
7
|
import * as smartdns from '@push.rocks/smartdns';
|
|
8
8
|
import * as smartrust from '@push.rocks/smartrust';
|
|
9
|
-
|
|
9
|
+
import * as smartwhois from '@push.rocks/smartwhois';
|
|
10
|
+
export { smartdns, smartrust, smartwhois };
|
|
10
11
|
// third party
|
|
11
12
|
import * as maxmind from 'maxmind';
|
|
12
13
|
export { maxmind };
|
|
13
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZXR3b3JrLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydG5ldHdvcmsucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxlQUFlO0FBQ2YsT0FBTyxLQUFLLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDOUIsT0FBTyxLQUFLLEtBQUssTUFBTSxZQUFZLENBQUM7QUFDcEMsT0FBTyxLQUFLLFNBQVMsTUFBTSxpQkFBaUIsQ0FBQztBQUU3QyxPQUFPLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsQ0FBQztBQUVoQyxtQkFBbUI7QUFDbkIsT0FBTyxLQUFLLFFBQVEsTUFBTSxzQkFBc0IsQ0FBQztBQUNqRCxPQUFPLEtBQUssU0FBUyxNQUFNLHVCQUF1QixDQUFDO0FBQ25ELE9BQU8sS0FBSyxVQUFVLE1BQU0sd0JBQXdCLENBQUM7QUFFckQsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLENBQUM7QUFFM0MsY0FBYztBQUNkLE9BQU8sS0FBSyxPQUFPLE1BQU0sU0FBUyxDQUFDO0FBRW5DLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyJ9
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartnetwork",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.10.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A toolkit for network diagnostics including speed tests, port availability checks, and more.",
|
|
6
6
|
"exports": {
|
|
@@ -11,14 +11,15 @@
|
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"devDependencies": {
|
|
13
13
|
"@git.zone/tsbuild": "^4.4.2",
|
|
14
|
-
"@git.zone/tsrun": "^2.0.
|
|
15
|
-
"@git.zone/tsrust": "^1.
|
|
14
|
+
"@git.zone/tsrun": "^2.0.5",
|
|
15
|
+
"@git.zone/tsrust": "^1.7.0",
|
|
16
16
|
"@git.zone/tstest": "^3.6.6",
|
|
17
|
-
"@types/node": "^26.
|
|
17
|
+
"@types/node": "^26.1.1"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@push.rocks/smartdns": "^7.9.2",
|
|
21
21
|
"@push.rocks/smartrust": "^1.4.0",
|
|
22
|
+
"@push.rocks/smartwhois": "^1.2.0",
|
|
22
23
|
"maxmind": "^5.0.6"
|
|
23
24
|
},
|
|
24
25
|
"files": [
|
package/readme.md
CHANGED
|
@@ -61,9 +61,9 @@ const network = new SmartNetwork({ cacheTtl: 60000 }); // 60s TTL
|
|
|
61
61
|
|
|
62
62
|
### 🕵️ IP Intelligence
|
|
63
63
|
|
|
64
|
-
Get ASN, organization, geolocation, and RDAP registration data for any IPv4 address. Combines three free public data sources in parallel:
|
|
64
|
+
Get ASN, organization, geolocation, and RDAP registration data for any IPv4 address (RDAP registration data also works for IPv6). Combines three free public data sources in parallel:
|
|
65
65
|
|
|
66
|
-
- **RDAP** — direct queries to RIRs (RIPE, ARIN, APNIC, LACNIC, AFRINIC) for authoritative registration data
|
|
66
|
+
- **RDAP** — direct queries to RIRs (RIPE, ARIN, APNIC, LACNIC, AFRINIC) for authoritative registration data, via [`@push.rocks/smartwhois`](https://code.foss.global/push.rocks/smartwhois)
|
|
67
67
|
- **Team Cymru DNS** — fast ASN resolution via DNS TXT records
|
|
68
68
|
- **MaxMind GeoLite2** — in-memory MMDB databases (auto-downloaded from CDN, periodically refreshed)
|
|
69
69
|
|
|
@@ -133,7 +133,7 @@ interface IIpIntelligenceResult {
|
|
|
133
133
|
|
|
134
134
|
Get comprehensive domain registration and DNS data. Runs an **RDAP layer** and a **DNS layer** in parallel, then merges results:
|
|
135
135
|
|
|
136
|
-
- **RDAP** — queries the correct registry RDAP server (discovered via the [IANA DNS bootstrap](https://data.iana.org/rdap/dns.json)) for registrar, registrant, events, status flags, DNSSEC, and abuse contacts
|
|
136
|
+
- **RDAP** — queries the correct registry RDAP server (discovered via the [IANA DNS bootstrap](https://data.iana.org/rdap/dns.json)) for registrar, registrant, events, status flags, DNSSEC, and abuse contacts, via [`@push.rocks/smartwhois`](https://code.foss.global/push.rocks/smartwhois)
|
|
137
137
|
- **DNS** — queries A, AAAA, NS, MX, TXT, and SOA records via `@push.rocks/smartdns` (system resolver first, DoH fallback)
|
|
138
138
|
|
|
139
139
|
For gTLDs (`.com`, `.org`, `.net`, etc.) you get the full picture from both layers. For ccTLDs without RDAP support (`.de`, `.fr`, `.nl`, etc.), the DNS layer fills in nameservers, resolved IPs, MX, TXT, and SOA — so you still get useful intelligence even when RDAP isn't available.
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/helpers/ip.ts
CHANGED
|
@@ -67,3 +67,82 @@ export function getIpVersion(ip: string): 4 | 6 | 0 {
|
|
|
67
67
|
if (isValidIpv6(ip)) return 6;
|
|
68
68
|
return 0;
|
|
69
69
|
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Expands a valid IPv6 address into its eight zero-padded 16-bit groups.
|
|
73
|
+
* Embedded IPv4 tails are converted to their two hex groups.
|
|
74
|
+
* Returns undefined for anything that is not a valid IPv6 address.
|
|
75
|
+
*/
|
|
76
|
+
export function expandIpv6(ip: string): string[] | undefined {
|
|
77
|
+
if (!isValidIpv6(ip)) return undefined;
|
|
78
|
+
|
|
79
|
+
let normalized = ip;
|
|
80
|
+
const lastColon = normalized.lastIndexOf(':');
|
|
81
|
+
const tail = normalized.slice(lastColon + 1);
|
|
82
|
+
if (tail.includes('.')) {
|
|
83
|
+
const octets = tail.split('.').map(Number);
|
|
84
|
+
const hexTail = `${((octets[0] << 8) | octets[1]).toString(16)}:${((octets[2] << 8) | octets[3]).toString(16)}`;
|
|
85
|
+
normalized = `${normalized.slice(0, lastColon + 1)}${hexTail}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const halves = normalized.split('::');
|
|
89
|
+
const parseGroups = (segment: string): string[] =>
|
|
90
|
+
segment === '' ? [] : segment.split(':');
|
|
91
|
+
const left = parseGroups(halves[0]);
|
|
92
|
+
const right = halves.length === 2 ? parseGroups(halves[1]) : [];
|
|
93
|
+
const missing = 8 - left.length - right.length;
|
|
94
|
+
if ((halves.length === 1 && missing !== 0) || missing < 0) return undefined;
|
|
95
|
+
const groups = [...left, ...Array.from({ length: missing }, () => '0'), ...right];
|
|
96
|
+
if (groups.length !== 8) return undefined;
|
|
97
|
+
return groups.map((group) => group.toLowerCase().padStart(4, '0'));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Returns the reverse-DNS (PTR) name for a valid IPv4 or IPv6 address:
|
|
102
|
+
* 'in-addr.arpa' for IPv4, 'ip6.arpa' with nibble ordering for IPv6.
|
|
103
|
+
* Returns undefined instead of throwing for invalid input, so lookup code
|
|
104
|
+
* can treat "no address" and "bad address" uniformly.
|
|
105
|
+
*/
|
|
106
|
+
export function toReverseDnsName(ip: string): string | undefined {
|
|
107
|
+
const family = getIpVersion(ip);
|
|
108
|
+
if (family === 4) {
|
|
109
|
+
return `${ip.split('.').reverse().join('.')}.in-addr.arpa`;
|
|
110
|
+
}
|
|
111
|
+
if (family === 6) {
|
|
112
|
+
const groups = expandIpv6(ip);
|
|
113
|
+
if (!groups) return undefined;
|
|
114
|
+
return `${groups.join('').split('').reverse().join('.')}.ip6.arpa`;
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Returns true when the address is publicly routable: not private (RFC 1918),
|
|
121
|
+
* loopback, link-local, carrier-grade NAT, documentation, benchmarking,
|
|
122
|
+
* multicast, or otherwise reserved space. Invalid input returns false.
|
|
123
|
+
* IPv6 is public when it falls in global unicast 2000::/3 and is not the
|
|
124
|
+
* 2001:db8::/32 documentation range.
|
|
125
|
+
*/
|
|
126
|
+
export function isPublicIpAddress(ip: string): boolean {
|
|
127
|
+
const family = getIpVersion(ip);
|
|
128
|
+
if (family === 4) {
|
|
129
|
+
const [a, b, c] = ip.split('.').map(Number);
|
|
130
|
+
return !(a === 0 || a === 10 || a === 127 || a >= 224
|
|
131
|
+
|| (a === 100 && b >= 64 && b <= 127)
|
|
132
|
+
|| (a === 169 && b === 254)
|
|
133
|
+
|| (a === 172 && b >= 16 && b <= 31)
|
|
134
|
+
|| (a === 192 && b === 0)
|
|
135
|
+
|| (a === 192 && b === 168)
|
|
136
|
+
|| (a === 198 && (b === 18 || b === 19))
|
|
137
|
+
|| (a === 198 && b === 51 && c === 100)
|
|
138
|
+
|| (a === 203 && b === 0 && c === 113));
|
|
139
|
+
}
|
|
140
|
+
if (family === 6) {
|
|
141
|
+
const groups = expandIpv6(ip);
|
|
142
|
+
if (!groups) return false;
|
|
143
|
+
const firstGroup = parseInt(groups[0], 16);
|
|
144
|
+
if (firstGroup < 0x2000 || firstGroup > 0x3fff) return false;
|
|
145
|
+
return !(groups[0] === '2001' && groups[1] === '0db8');
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
package/ts/index.ts
CHANGED
|
@@ -8,4 +8,4 @@ export { DomainIntelligence } from './smartnetwork.classes.domainintelligence.js
|
|
|
8
8
|
export type { IDomainIntelligenceResult, IDomainIntelligenceOptions } from './smartnetwork.classes.domainintelligence.js';
|
|
9
9
|
export { setLogger, getLogger } from './logging.js';
|
|
10
10
|
export { NetworkError, TimeoutError } from './errors.js';
|
|
11
|
-
export { isValidIpv4, isValidIpv6, getIpVersion } from './helpers/ip.js';
|
|
11
|
+
export { isValidIpv4, isValidIpv6, getIpVersion, expandIpv6, toReverseDnsName, isPublicIpAddress } from './helpers/ip.js';
|