@cyanheads/whois-mcp-server 0.1.1
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/AGENTS.md +349 -0
- package/CLAUDE.md +349 -0
- package/Dockerfile +99 -0
- package/LICENSE +201 -0
- package/README.md +316 -0
- package/changelog/0.1.x/0.1.1.md +32 -0
- package/changelog/template.md +127 -0
- package/dist/config/server-config.d.ts +16 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +30 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/_fqdn.d.ts +7 -0
- package/dist/mcp-server/tools/definitions/_fqdn.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/_fqdn.js +18 -0
- package/dist/mcp-server/tools/definitions/_fqdn.js.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.d.ts +26 -0
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.js +102 -0
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.d.ts +49 -0
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.js +97 -0
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.d.ts +41 -0
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.js +332 -0
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.d.ts +30 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.js +83 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.d.ts +40 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.js +124 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.d.ts +39 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.js +111 -0
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.js.map +1 -0
- package/dist/services/doh/doh-service.d.ts +30 -0
- package/dist/services/doh/doh-service.d.ts.map +1 -0
- package/dist/services/doh/doh-service.js +114 -0
- package/dist/services/doh/doh-service.js.map +1 -0
- package/dist/services/doh/types.d.ts +45 -0
- package/dist/services/doh/types.d.ts.map +1 -0
- package/dist/services/doh/types.js +17 -0
- package/dist/services/doh/types.js.map +1 -0
- package/dist/services/rdap/rdap-service.d.ts +54 -0
- package/dist/services/rdap/rdap-service.d.ts.map +1 -0
- package/dist/services/rdap/rdap-service.js +609 -0
- package/dist/services/rdap/rdap-service.js.map +1 -0
- package/dist/services/rdap/types.d.ts +140 -0
- package/dist/services/rdap/types.d.ts.map +1 -0
- package/dist/services/rdap/types.js +6 -0
- package/dist/services/rdap/types.js.map +1 -0
- package/package.json +103 -0
- package/server.json +161 -0
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview RDAP service — IANA bootstrap-driven domain, IP, and ASN lookups.
|
|
3
|
+
* Caches the IANA bootstrap JSON for 24 hours to avoid a bootstrap hop on every query.
|
|
4
|
+
* @module services/rdap/rdap-service
|
|
5
|
+
*/
|
|
6
|
+
import { notFound, serviceUnavailable, validationError } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
import { fetchWithTimeout, withRetry } from '@cyanheads/mcp-ts-core/utils';
|
|
8
|
+
import { getServerConfig } from '../../config/server-config.js';
|
|
9
|
+
// IANA bootstrap endpoints
|
|
10
|
+
const IANA_DNS_BOOTSTRAP = 'https://data.iana.org/rdap/dns.json';
|
|
11
|
+
const IANA_IPV4_BOOTSTRAP = 'https://data.iana.org/rdap/ipv4.json';
|
|
12
|
+
const IANA_IPV6_BOOTSTRAP = 'https://data.iana.org/rdap/ipv6.json';
|
|
13
|
+
const IANA_ASN_BOOTSTRAP = 'https://data.iana.org/rdap/asn.json';
|
|
14
|
+
const BOOTSTRAP_TTL_MS = 24 * 60 * 60 * 1000; // 24h
|
|
15
|
+
// Private/reserved IPv4 ranges
|
|
16
|
+
const PRIVATE_IPV4_RANGES = [
|
|
17
|
+
/^10\./,
|
|
18
|
+
/^172\.(1[6-9]|2\d|3[01])\./,
|
|
19
|
+
/^192\.168\./,
|
|
20
|
+
/^127\./,
|
|
21
|
+
/^169\.254\./,
|
|
22
|
+
/^100\.(6[4-9]|[7-9]\d|1([01]\d|2[0-7]))\./, // CGNAT 100.64-100.127
|
|
23
|
+
/^0\./,
|
|
24
|
+
/^255\./,
|
|
25
|
+
];
|
|
26
|
+
// Private/reserved IPv6 ranges (string prefix checks)
|
|
27
|
+
const PRIVATE_IPV6_PREFIXES = [
|
|
28
|
+
'::1', // loopback
|
|
29
|
+
'fc', // ULA fc00::/7
|
|
30
|
+
'fd', // ULA fd00::/7
|
|
31
|
+
'fe80', // link-local fe80::/10
|
|
32
|
+
];
|
|
33
|
+
function isPrivateIpv4(ip) {
|
|
34
|
+
return PRIVATE_IPV4_RANGES.some((r) => r.test(ip));
|
|
35
|
+
}
|
|
36
|
+
function isPrivateIpv6(ip) {
|
|
37
|
+
const lower = ip.toLowerCase();
|
|
38
|
+
return PRIVATE_IPV6_PREFIXES.some((p) => lower.startsWith(p));
|
|
39
|
+
}
|
|
40
|
+
/** Check if an IP or CIDR base is private/reserved. */
|
|
41
|
+
function isPrivateIp(ip) {
|
|
42
|
+
const base = ip.split('/')[0] ?? '';
|
|
43
|
+
if (base.includes(':'))
|
|
44
|
+
return isPrivateIpv6(base);
|
|
45
|
+
return isPrivateIpv4(base);
|
|
46
|
+
}
|
|
47
|
+
/** Simple IPv4 validation */
|
|
48
|
+
function isValidIpv4(ip) {
|
|
49
|
+
const parts = ip.split('.');
|
|
50
|
+
if (parts.length !== 4)
|
|
51
|
+
return false;
|
|
52
|
+
return parts.every((p) => {
|
|
53
|
+
const n = parseInt(p, 10);
|
|
54
|
+
return !Number.isNaN(n) && n >= 0 && n <= 255 && String(n) === p;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** Simple IPv6 validation — accepts compressed forms */
|
|
58
|
+
function isValidIpv6(ip) {
|
|
59
|
+
if (!ip.includes(':'))
|
|
60
|
+
return false;
|
|
61
|
+
if (ip.split(':').length > 8)
|
|
62
|
+
return false;
|
|
63
|
+
return /^[0-9a-fA-F:]+$/.test(ip);
|
|
64
|
+
}
|
|
65
|
+
/** Validate an IP address or CIDR notation */
|
|
66
|
+
export function validateIp(ip) {
|
|
67
|
+
const parts = ip.split('/');
|
|
68
|
+
const base = parts[0] ?? '';
|
|
69
|
+
const hasCidr = parts.length === 2;
|
|
70
|
+
if (hasCidr) {
|
|
71
|
+
const prefix = parseInt(parts[1] ?? '', 10);
|
|
72
|
+
if (Number.isNaN(prefix) || prefix < 0)
|
|
73
|
+
return { valid: false, isIpv6: false, hasCidr: true };
|
|
74
|
+
}
|
|
75
|
+
const isIpv6 = base.includes(':');
|
|
76
|
+
if (isIpv6) {
|
|
77
|
+
if (hasCidr && parseInt(parts[1] ?? '129', 10) > 128)
|
|
78
|
+
return { valid: false, isIpv6: true, hasCidr: true };
|
|
79
|
+
return { valid: isValidIpv6(base), isIpv6: true, hasCidr };
|
|
80
|
+
}
|
|
81
|
+
if (hasCidr && parseInt(parts[1] ?? '33', 10) > 32)
|
|
82
|
+
return { valid: false, isIpv6: false, hasCidr: true };
|
|
83
|
+
return { valid: isValidIpv4(base), isIpv6: false, hasCidr };
|
|
84
|
+
}
|
|
85
|
+
/** Build reverse PTR query name from an IPv4 address */
|
|
86
|
+
export function ipv4ToPtr(ip) {
|
|
87
|
+
return `${ip.split('.').reverse().join('.')}.in-addr.arpa`;
|
|
88
|
+
}
|
|
89
|
+
/** Expand a compressed IPv6 address to a full 128-bit BigInt */
|
|
90
|
+
function ipv6ToBigInt(ip) {
|
|
91
|
+
let groups;
|
|
92
|
+
if (ip.includes('::')) {
|
|
93
|
+
const parts = ip.split('::');
|
|
94
|
+
const left = parts[0] ? parts[0].split(':') : [];
|
|
95
|
+
const right = parts[1] ? parts[1].split(':') : [];
|
|
96
|
+
const missing = 8 - left.length - right.length;
|
|
97
|
+
groups = [...left, ...Array(missing).fill('0'), ...right];
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
groups = ip.split(':');
|
|
101
|
+
}
|
|
102
|
+
return groups.reduce((acc, g) => (acc << 16n) | BigInt(parseInt(g || '0', 16)), 0n);
|
|
103
|
+
}
|
|
104
|
+
/** Build reverse PTR query name from an IPv6 address */
|
|
105
|
+
export function ipv6ToPtr(ip) {
|
|
106
|
+
let hex;
|
|
107
|
+
// Handle :: compression
|
|
108
|
+
if (ip.includes('::')) {
|
|
109
|
+
const parts = ip.split('::');
|
|
110
|
+
const left = parts[0] ? parts[0].split(':') : [];
|
|
111
|
+
const right = parts[1] ? parts[1].split(':') : [];
|
|
112
|
+
const missing = 8 - left.length - right.length;
|
|
113
|
+
const full = [...left, ...Array(missing).fill('0'), ...right];
|
|
114
|
+
hex = full.map((g) => g.padStart(4, '0')).join('');
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
hex = ip
|
|
118
|
+
.split(':')
|
|
119
|
+
.map((g) => g.padStart(4, '0'))
|
|
120
|
+
.join('');
|
|
121
|
+
}
|
|
122
|
+
return `${hex.split('').reverse().join('.')}.ip6.arpa`;
|
|
123
|
+
}
|
|
124
|
+
/** Extract top-level TLD (last label) */
|
|
125
|
+
function extractToplevelTld(domain) {
|
|
126
|
+
const labels = domain.toLowerCase().split('.');
|
|
127
|
+
return labels[labels.length - 1] ?? '';
|
|
128
|
+
}
|
|
129
|
+
/** Normalize a domain to its two-label suffix for bootstrap lookup */
|
|
130
|
+
function extractTwoLabelSuffix(domain) {
|
|
131
|
+
const labels = domain.toLowerCase().split('.');
|
|
132
|
+
if (labels.length < 2)
|
|
133
|
+
return '';
|
|
134
|
+
return labels.slice(-2).join('.');
|
|
135
|
+
}
|
|
136
|
+
/** Identify RIR from an RDAP self-link URL */
|
|
137
|
+
function ririFromSelfLink(selfLink) {
|
|
138
|
+
if (selfLink.includes('arin.net'))
|
|
139
|
+
return 'ARIN';
|
|
140
|
+
if (selfLink.includes('ripe.net'))
|
|
141
|
+
return 'RIPE';
|
|
142
|
+
if (selfLink.includes('apnic.net'))
|
|
143
|
+
return 'APNIC';
|
|
144
|
+
if (selfLink.includes('lacnic.net'))
|
|
145
|
+
return 'LACNIC';
|
|
146
|
+
if (selfLink.includes('afrinic.net'))
|
|
147
|
+
return 'AFRINIC';
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
/** Extract vCard field value by field name */
|
|
151
|
+
function vcardField(vcard, fieldName) {
|
|
152
|
+
for (const entry of vcard) {
|
|
153
|
+
if (Array.isArray(entry) && entry[0] === fieldName) {
|
|
154
|
+
const val = entry[3];
|
|
155
|
+
if (typeof val === 'string')
|
|
156
|
+
return val;
|
|
157
|
+
if (Array.isArray(val) && typeof val[0] === 'string')
|
|
158
|
+
return val[0];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
/** Extract fn (full name / org name) from an entity's vcard */
|
|
164
|
+
function entityName(entity) {
|
|
165
|
+
if (!entity.vcardArray)
|
|
166
|
+
return;
|
|
167
|
+
const vcard = entity.vcardArray[1];
|
|
168
|
+
return vcardField(vcard, 'fn');
|
|
169
|
+
}
|
|
170
|
+
/** Extract email from an entity's vcard */
|
|
171
|
+
function entityEmail(entity) {
|
|
172
|
+
if (!entity.vcardArray)
|
|
173
|
+
return;
|
|
174
|
+
const vcard = entity.vcardArray[1];
|
|
175
|
+
return vcardField(vcard, 'email');
|
|
176
|
+
}
|
|
177
|
+
/** Find nested entity by role, searching recursively */
|
|
178
|
+
function findEntityByRole(entities, role) {
|
|
179
|
+
for (const e of entities) {
|
|
180
|
+
if (e.roles?.includes(role))
|
|
181
|
+
return e;
|
|
182
|
+
if (e.entities) {
|
|
183
|
+
const found = findEntityByRole(e.entities, role);
|
|
184
|
+
if (found)
|
|
185
|
+
return found;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
/** Extract registrar IANA ID from publicIds */
|
|
191
|
+
function registrarIanaId(entity) {
|
|
192
|
+
return entity.publicIds?.find((p) => p.type === 'IANA Registrar ID')?.identifier;
|
|
193
|
+
}
|
|
194
|
+
/** Normalize RDAP domain response to our output shape */
|
|
195
|
+
function normalizeDomain(raw) {
|
|
196
|
+
const events = raw.events ?? [];
|
|
197
|
+
const getDate = (action) => events.find((e) => e.eventAction === action)?.eventDate;
|
|
198
|
+
const nameservers = (raw.nameservers ?? [])
|
|
199
|
+
.map((ns) => (ns.ldhName ?? ns.unicodeName ?? '').toLowerCase())
|
|
200
|
+
.filter(Boolean);
|
|
201
|
+
const entities = raw.entities ?? [];
|
|
202
|
+
const registrarEntity = findEntityByRole(entities, 'registrar');
|
|
203
|
+
const registrar = registrarEntity ? entityName(registrarEntity) : undefined;
|
|
204
|
+
const registrarIanaIdVal = registrarEntity ? registrarIanaId(registrarEntity) : undefined;
|
|
205
|
+
const registrantEntity = findEntityByRole(entities, 'registrant');
|
|
206
|
+
const registrantOrg = registrantEntity ? entityName(registrantEntity) : undefined;
|
|
207
|
+
const registrantRedacted = !registrantOrg;
|
|
208
|
+
const rdapLastUpdated = getDate('last update of RDAP database');
|
|
209
|
+
const createdDate = getDate('registration');
|
|
210
|
+
const updatedDate = getDate('last changed');
|
|
211
|
+
const expiryDate = getDate('expiration');
|
|
212
|
+
const domainName = (raw.ldhName ?? raw.unicodeName ?? '').toLowerCase();
|
|
213
|
+
// Build with exactOptionalPropertyTypes compliance using type assertion on optional fields
|
|
214
|
+
const result = {
|
|
215
|
+
domain: domainName,
|
|
216
|
+
rdap_coverage: true,
|
|
217
|
+
status: raw.status ?? [],
|
|
218
|
+
nameservers,
|
|
219
|
+
dnssec_signed: raw.secureDNS?.delegationSigned ?? false,
|
|
220
|
+
registrant_redacted: registrantRedacted,
|
|
221
|
+
};
|
|
222
|
+
if (raw.handle !== undefined)
|
|
223
|
+
result.handle = raw.handle;
|
|
224
|
+
if (registrar !== undefined)
|
|
225
|
+
result.registrar = registrar;
|
|
226
|
+
if (registrarIanaIdVal !== undefined)
|
|
227
|
+
result.registrar_iana_id = registrarIanaIdVal;
|
|
228
|
+
if (createdDate !== undefined)
|
|
229
|
+
result.created_date = createdDate;
|
|
230
|
+
if (updatedDate !== undefined)
|
|
231
|
+
result.updated_date = updatedDate;
|
|
232
|
+
if (expiryDate !== undefined)
|
|
233
|
+
result.expiry_date = expiryDate;
|
|
234
|
+
if (rdapLastUpdated !== undefined)
|
|
235
|
+
result.rdap_last_updated = rdapLastUpdated;
|
|
236
|
+
if (registrantOrg !== undefined)
|
|
237
|
+
result.registrant_org = registrantOrg;
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
/** Normalize RDAP IP network response */
|
|
241
|
+
function normalizeIpNetwork(raw, ip) {
|
|
242
|
+
const entities = raw.entities ?? [];
|
|
243
|
+
const registrant = findEntityByRole(entities, 'registrant');
|
|
244
|
+
const abuse = findEntityByRole(entities, 'abuse');
|
|
245
|
+
const orgName = registrant ? entityName(registrant) : undefined;
|
|
246
|
+
const abuseEmail = abuse ? entityEmail(abuse) : undefined;
|
|
247
|
+
let cidr;
|
|
248
|
+
if (raw.cidr0_cidrs && raw.cidr0_cidrs.length > 0) {
|
|
249
|
+
const c = raw.cidr0_cidrs[0];
|
|
250
|
+
if (c) {
|
|
251
|
+
if (c.v4prefix !== undefined && c.length !== undefined)
|
|
252
|
+
cidr = `${c.v4prefix}/${c.length}`;
|
|
253
|
+
else if (c.v6prefix !== undefined && c.length !== undefined)
|
|
254
|
+
cidr = `${c.v6prefix}/${c.length}`;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const selfLink = raw.links?.find((l) => l.rel === 'self')?.href ?? '';
|
|
258
|
+
const rdapSource = ririFromSelfLink(selfLink);
|
|
259
|
+
const result = { ip, ptr: null };
|
|
260
|
+
if (raw.handle !== undefined)
|
|
261
|
+
result.handle = raw.handle;
|
|
262
|
+
if (raw.startAddress !== undefined)
|
|
263
|
+
result.start_address = raw.startAddress;
|
|
264
|
+
if (raw.endAddress !== undefined)
|
|
265
|
+
result.end_address = raw.endAddress;
|
|
266
|
+
if (cidr !== undefined)
|
|
267
|
+
result.cidr = cidr;
|
|
268
|
+
if (raw.ipVersion !== undefined)
|
|
269
|
+
result.ip_version = raw.ipVersion;
|
|
270
|
+
if (raw.name !== undefined)
|
|
271
|
+
result.name = raw.name;
|
|
272
|
+
if (raw.type !== undefined)
|
|
273
|
+
result.type = raw.type;
|
|
274
|
+
if (raw.country !== undefined && raw.country !== null)
|
|
275
|
+
result.country = raw.country;
|
|
276
|
+
if (orgName !== undefined)
|
|
277
|
+
result.org_name = orgName;
|
|
278
|
+
if (abuseEmail !== undefined)
|
|
279
|
+
result.abuse_email = abuseEmail;
|
|
280
|
+
if (rdapSource !== undefined)
|
|
281
|
+
result.rdap_source = rdapSource;
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
/** Normalize RDAP autnum (ASN) response */
|
|
285
|
+
function normalizeAutnum(raw, asn) {
|
|
286
|
+
const entities = raw.entities ?? [];
|
|
287
|
+
const registrant = findEntityByRole(entities, 'registrant');
|
|
288
|
+
const orgName = registrant ? entityName(registrant) : undefined;
|
|
289
|
+
const selfLink = raw.links?.find((l) => l.rel === 'self')?.href ?? '';
|
|
290
|
+
const rir = ririFromSelfLink(selfLink);
|
|
291
|
+
const result = { asn };
|
|
292
|
+
if (raw.handle !== undefined)
|
|
293
|
+
result.handle = raw.handle;
|
|
294
|
+
if (raw.startAutnum !== undefined)
|
|
295
|
+
result.start_autnum = raw.startAutnum;
|
|
296
|
+
if (raw.endAutnum !== undefined)
|
|
297
|
+
result.end_autnum = raw.endAutnum;
|
|
298
|
+
if (raw.name !== undefined)
|
|
299
|
+
result.name = raw.name;
|
|
300
|
+
if (raw.type !== undefined)
|
|
301
|
+
result.type = raw.type;
|
|
302
|
+
if (raw.country !== undefined && raw.country !== null)
|
|
303
|
+
result.country = raw.country;
|
|
304
|
+
if (orgName !== undefined)
|
|
305
|
+
result.org_name = orgName;
|
|
306
|
+
if (rir !== undefined)
|
|
307
|
+
result.rir = rir;
|
|
308
|
+
return result;
|
|
309
|
+
}
|
|
310
|
+
// ─── Service class ────────────────────────────────────────────────────────────
|
|
311
|
+
export class RdapService {
|
|
312
|
+
bootstrapCache = new Map();
|
|
313
|
+
reqCtx(ctx) {
|
|
314
|
+
return { requestId: ctx.requestId, tenantId: ctx.tenantId, timestamp: ctx.timestamp };
|
|
315
|
+
}
|
|
316
|
+
/** Fetch and cache a bootstrap JSON from IANA */
|
|
317
|
+
async fetchBootstrap(url, ctx) {
|
|
318
|
+
const cached = this.bootstrapCache.get(url);
|
|
319
|
+
if (cached && Date.now() - cached.fetchedAt < BOOTSTRAP_TTL_MS) {
|
|
320
|
+
return cached.data;
|
|
321
|
+
}
|
|
322
|
+
const config = getServerConfig();
|
|
323
|
+
const reqCtx = this.reqCtx(ctx);
|
|
324
|
+
const response = await fetchWithTimeout(url, config.rdapTimeoutMs, reqCtx, {
|
|
325
|
+
headers: { Accept: 'application/json' },
|
|
326
|
+
signal: ctx.signal,
|
|
327
|
+
});
|
|
328
|
+
const data = (await response.json());
|
|
329
|
+
this.bootstrapCache.set(url, { data, fetchedAt: Date.now() });
|
|
330
|
+
return data;
|
|
331
|
+
}
|
|
332
|
+
/** Find the RDAP server URL for a domain's TLD via IANA bootstrap */
|
|
333
|
+
async findDomainRdapServer(domain, ctx) {
|
|
334
|
+
const bootstrap = await this.fetchBootstrap(IANA_DNS_BOOTSTRAP, ctx);
|
|
335
|
+
const twoLabel = extractTwoLabelSuffix(domain);
|
|
336
|
+
const singleLabel = extractToplevelTld(domain);
|
|
337
|
+
for (const candidate of [twoLabel, singleLabel]) {
|
|
338
|
+
if (!candidate)
|
|
339
|
+
continue;
|
|
340
|
+
for (const [tlds, servers] of bootstrap.services) {
|
|
341
|
+
if (tlds.includes(candidate) && servers.length > 0) {
|
|
342
|
+
return servers[0]?.replace(/\/$/, '') ?? null;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
/** Find the RDAP server URL for an IP address via IANA bootstrap */
|
|
349
|
+
async findIpRdapServer(ip, isIpv6, ctx) {
|
|
350
|
+
const bootstrapUrl = isIpv6 ? IANA_IPV6_BOOTSTRAP : IANA_IPV4_BOOTSTRAP;
|
|
351
|
+
const bootstrap = await this.fetchBootstrap(bootstrapUrl, ctx);
|
|
352
|
+
if (isIpv6) {
|
|
353
|
+
// IPv6: match against CIDR prefixes in the bootstrap using bigint arithmetic
|
|
354
|
+
const base = ip.split('/')[0] ?? '';
|
|
355
|
+
const ipBig = ipv6ToBigInt(base);
|
|
356
|
+
for (const [cidrs, servers] of bootstrap.services) {
|
|
357
|
+
for (const cidr of cidrs) {
|
|
358
|
+
const slash = cidr.indexOf('/');
|
|
359
|
+
if (slash === -1)
|
|
360
|
+
continue;
|
|
361
|
+
const net = cidr.slice(0, slash);
|
|
362
|
+
const prefixLen = parseInt(cidr.slice(slash + 1), 10);
|
|
363
|
+
if (Number.isNaN(prefixLen) || prefixLen < 0 || prefixLen > 128)
|
|
364
|
+
continue;
|
|
365
|
+
const netBig = ipv6ToBigInt(net);
|
|
366
|
+
const mask = prefixLen === 0 ? 0n : ~((1n << BigInt(128 - prefixLen)) - 1n);
|
|
367
|
+
if ((netBig & mask) === (ipBig & mask) && servers.length > 0) {
|
|
368
|
+
return servers[0]?.replace(/\/$/, '') ?? null;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
// IPv4: match against CIDR prefixes in the bootstrap
|
|
375
|
+
const base = ip.split('/')[0] ?? '';
|
|
376
|
+
const parts = base.split('.').map(Number);
|
|
377
|
+
for (const [cidrs, servers] of bootstrap.services) {
|
|
378
|
+
for (const cidr of cidrs) {
|
|
379
|
+
const cidrParts = cidr.split('/');
|
|
380
|
+
const net = cidrParts[0] ?? '';
|
|
381
|
+
const bits = cidrParts[1] ?? '0';
|
|
382
|
+
const prefixLen = parseInt(bits, 10);
|
|
383
|
+
const netParts = net.split('.').map(Number);
|
|
384
|
+
if (netParts.length !== 4 || parts.length !== 4)
|
|
385
|
+
continue;
|
|
386
|
+
const mask = ~((1 << (32 - prefixLen)) - 1);
|
|
387
|
+
const [n0, n1, n2, n3] = netParts;
|
|
388
|
+
const [p0, p1, p2, p3] = parts;
|
|
389
|
+
const netNum = (n0 << 24) | (n1 << 16) | (n2 << 8) | n3;
|
|
390
|
+
const ipNum = (p0 << 24) | (p1 << 16) | (p2 << 8) | p3;
|
|
391
|
+
if ((netNum & mask) === (ipNum & mask) && servers.length > 0) {
|
|
392
|
+
return servers[0]?.replace(/\/$/, '') ?? null;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
/** Find the RDAP server URL for an ASN via IANA bootstrap */
|
|
399
|
+
async findAsnRdapServer(asnNum, ctx) {
|
|
400
|
+
const bootstrap = await this.fetchBootstrap(IANA_ASN_BOOTSTRAP, ctx);
|
|
401
|
+
for (const [ranges, servers] of bootstrap.services) {
|
|
402
|
+
for (const range of ranges) {
|
|
403
|
+
const rangeParts = range.split('-').map(Number);
|
|
404
|
+
const start = rangeParts[0];
|
|
405
|
+
const rangeEnd = rangeParts.length > 1 ? rangeParts[1] : start;
|
|
406
|
+
if (start === undefined || rangeEnd === undefined)
|
|
407
|
+
continue;
|
|
408
|
+
if (asnNum >= start && asnNum <= rangeEnd && servers.length > 0) {
|
|
409
|
+
return servers[0]?.replace(/\/$/, '') ?? null;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
/** Look up a domain registration record via RDAP */
|
|
416
|
+
async lookupDomain(domain, ctx) {
|
|
417
|
+
const rdapServer = await this.findDomainRdapServer(domain, ctx);
|
|
418
|
+
if (!rdapServer) {
|
|
419
|
+
return {
|
|
420
|
+
domain: domain.toLowerCase(),
|
|
421
|
+
rdap_coverage: false,
|
|
422
|
+
status: [],
|
|
423
|
+
nameservers: [],
|
|
424
|
+
dnssec_signed: false,
|
|
425
|
+
registrant_redacted: false,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
const config = getServerConfig();
|
|
429
|
+
const url = `${rdapServer}/domain/${encodeURIComponent(domain.toLowerCase())}`;
|
|
430
|
+
const reqCtx = this.reqCtx(ctx);
|
|
431
|
+
try {
|
|
432
|
+
const raw = await withRetry(async () => {
|
|
433
|
+
const response = await fetchWithTimeout(url, config.rdapTimeoutMs, reqCtx, {
|
|
434
|
+
headers: { Accept: 'application/rdap+json, application/json' },
|
|
435
|
+
signal: ctx.signal,
|
|
436
|
+
});
|
|
437
|
+
return response.json();
|
|
438
|
+
}, {
|
|
439
|
+
operation: 'rdap.lookupDomain',
|
|
440
|
+
context: reqCtx,
|
|
441
|
+
maxRetries: config.rdapMaxRetries,
|
|
442
|
+
baseDelayMs: 1000,
|
|
443
|
+
signal: ctx.signal,
|
|
444
|
+
isTransient: (err) => {
|
|
445
|
+
// 404 is NOT transient — domain is not registered; don't retry
|
|
446
|
+
if (err instanceof Error) {
|
|
447
|
+
const msg = err.message;
|
|
448
|
+
if (msg.includes('404') || msg.includes('Not Found') || msg.includes('NotFound')) {
|
|
449
|
+
return false;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return true;
|
|
453
|
+
},
|
|
454
|
+
});
|
|
455
|
+
return normalizeDomain(raw);
|
|
456
|
+
}
|
|
457
|
+
catch (err) {
|
|
458
|
+
// RDAP 404 on a domain lookup means the domain is not registered
|
|
459
|
+
if (err instanceof Error &&
|
|
460
|
+
(err.message.includes('404') ||
|
|
461
|
+
err.message.includes('Not Found') ||
|
|
462
|
+
err.message.includes('NotFound'))) {
|
|
463
|
+
throw notFound(`Domain "${domain}" is not registered (RDAP 404).`, {
|
|
464
|
+
reason: 'domain_not_found',
|
|
465
|
+
domain: domain.toLowerCase(),
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
throw err;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Check domain availability via RDAP.
|
|
473
|
+
* Returns `{ available: true }` on 404, normalized record on 200,
|
|
474
|
+
* or `{ available: null }` when TLD has no RDAP coverage.
|
|
475
|
+
*/
|
|
476
|
+
async checkAvailability(domain, ctx) {
|
|
477
|
+
const rdapServer = await this.findDomainRdapServer(domain, ctx);
|
|
478
|
+
if (!rdapServer) {
|
|
479
|
+
return { available: null, rdap_coverage: false };
|
|
480
|
+
}
|
|
481
|
+
const config = getServerConfig();
|
|
482
|
+
const url = `${rdapServer}/domain/${encodeURIComponent(domain.toLowerCase())}`;
|
|
483
|
+
const reqCtx = this.reqCtx(ctx);
|
|
484
|
+
try {
|
|
485
|
+
const raw = await withRetry(async () => {
|
|
486
|
+
const response = await fetchWithTimeout(url, config.rdapTimeoutMs, reqCtx, {
|
|
487
|
+
headers: { Accept: 'application/rdap+json, application/json' },
|
|
488
|
+
signal: ctx.signal,
|
|
489
|
+
});
|
|
490
|
+
return response.json();
|
|
491
|
+
}, {
|
|
492
|
+
operation: 'rdap.checkAvailability',
|
|
493
|
+
context: reqCtx,
|
|
494
|
+
maxRetries: config.rdapMaxRetries,
|
|
495
|
+
baseDelayMs: 1000,
|
|
496
|
+
signal: ctx.signal,
|
|
497
|
+
isTransient: (err) => {
|
|
498
|
+
if (err instanceof Error) {
|
|
499
|
+
const msg = err.message;
|
|
500
|
+
// 404 is NOT transient — it's the availability signal
|
|
501
|
+
if (msg.includes('404') || msg.includes('Not Found') || msg.includes('NotFound')) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return true;
|
|
506
|
+
},
|
|
507
|
+
});
|
|
508
|
+
const record = normalizeDomain(raw);
|
|
509
|
+
return { available: false, record };
|
|
510
|
+
}
|
|
511
|
+
catch (err) {
|
|
512
|
+
// A 404 from the RDAP server means the domain is available (not registered)
|
|
513
|
+
if (err instanceof Error &&
|
|
514
|
+
(err.message.includes('404') ||
|
|
515
|
+
err.message.includes('Not Found') ||
|
|
516
|
+
err.message.includes('NotFound'))) {
|
|
517
|
+
return { available: true };
|
|
518
|
+
}
|
|
519
|
+
throw err;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/** Look up an IP address or CIDR via RIR RDAP */
|
|
523
|
+
async lookupIp(ip, ctx) {
|
|
524
|
+
const { valid, isIpv6 } = validateIp(ip);
|
|
525
|
+
if (!valid) {
|
|
526
|
+
throw validationError(`"${ip}" is not a valid IPv4, IPv6, or CIDR address.`, {
|
|
527
|
+
reason: 'invalid_ip',
|
|
528
|
+
...ctx.recoveryFor('invalid_ip'),
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
const base = ip.split('/')[0] ?? '';
|
|
532
|
+
if (isPrivateIp(base)) {
|
|
533
|
+
throw validationError(`"${base}" is a private or reserved IP address — no RIR RDAP record exists for it.`, {
|
|
534
|
+
reason: 'private_range',
|
|
535
|
+
...ctx.recoveryFor('private_range'),
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
const rdapServer = await this.findIpRdapServer(ip, isIpv6, ctx);
|
|
539
|
+
if (!rdapServer) {
|
|
540
|
+
throw serviceUnavailable('No RIR RDAP server found for this IP address range.', { ip });
|
|
541
|
+
}
|
|
542
|
+
const config = getServerConfig();
|
|
543
|
+
// IPv6 addresses contain colons which must NOT be percent-encoded in the RDAP path.
|
|
544
|
+
// encodeURIComponent would produce 2001%3A4860%3A... which RDAP servers reject.
|
|
545
|
+
const url = `${rdapServer}/ip/${base}`;
|
|
546
|
+
const reqCtx = this.reqCtx(ctx);
|
|
547
|
+
const raw = await withRetry(async () => {
|
|
548
|
+
const response = await fetchWithTimeout(url, config.rdapTimeoutMs, reqCtx, {
|
|
549
|
+
headers: { Accept: 'application/rdap+json, application/json' },
|
|
550
|
+
signal: ctx.signal,
|
|
551
|
+
});
|
|
552
|
+
return response.json();
|
|
553
|
+
}, {
|
|
554
|
+
operation: 'rdap.lookupIp',
|
|
555
|
+
context: reqCtx,
|
|
556
|
+
maxRetries: config.rdapMaxRetries,
|
|
557
|
+
baseDelayMs: 1000,
|
|
558
|
+
signal: ctx.signal,
|
|
559
|
+
});
|
|
560
|
+
return normalizeIpNetwork(raw, ip);
|
|
561
|
+
}
|
|
562
|
+
/** Look up an ASN via RIR RDAP */
|
|
563
|
+
async lookupAsn(asn, ctx) {
|
|
564
|
+
const asnClean = asn.toUpperCase().replace(/^AS/, '');
|
|
565
|
+
const asnNum = parseInt(asnClean, 10);
|
|
566
|
+
if (Number.isNaN(asnNum) || asnNum <= 0) {
|
|
567
|
+
throw validationError(`"${asn}" is not a valid ASN. Expected AS<number> or bare integer (e.g., AS15169 or 15169).`, {
|
|
568
|
+
reason: 'invalid_asn',
|
|
569
|
+
...ctx.recoveryFor('invalid_asn'),
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
const rdapServer = await this.findAsnRdapServer(asnNum, ctx);
|
|
573
|
+
if (!rdapServer) {
|
|
574
|
+
throw notFound(`ASN ${asnNum} not found in any RIR RDAP server.`, {
|
|
575
|
+
reason: 'asn_not_found',
|
|
576
|
+
...ctx.recoveryFor('asn_not_found'),
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
const config = getServerConfig();
|
|
580
|
+
const url = `${rdapServer}/autnum/${asnNum}`;
|
|
581
|
+
const reqCtx = this.reqCtx(ctx);
|
|
582
|
+
const raw = await withRetry(async () => {
|
|
583
|
+
const response = await fetchWithTimeout(url, config.rdapTimeoutMs, reqCtx, {
|
|
584
|
+
headers: { Accept: 'application/rdap+json, application/json' },
|
|
585
|
+
signal: ctx.signal,
|
|
586
|
+
});
|
|
587
|
+
return response.json();
|
|
588
|
+
}, {
|
|
589
|
+
operation: 'rdap.lookupAsn',
|
|
590
|
+
context: reqCtx,
|
|
591
|
+
maxRetries: config.rdapMaxRetries,
|
|
592
|
+
baseDelayMs: 1000,
|
|
593
|
+
signal: ctx.signal,
|
|
594
|
+
});
|
|
595
|
+
return normalizeAutnum(raw, `AS${asnNum}`);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
// ─── Init/accessor pattern ────────────────────────────────────────────────────
|
|
599
|
+
let _service;
|
|
600
|
+
export function initRdapService(_config, _storage) {
|
|
601
|
+
_service = new RdapService();
|
|
602
|
+
}
|
|
603
|
+
export function getRdapService() {
|
|
604
|
+
if (!_service) {
|
|
605
|
+
throw new Error('RdapService not initialized — call initRdapService() in setup()');
|
|
606
|
+
}
|
|
607
|
+
return _service;
|
|
608
|
+
}
|
|
609
|
+
//# sourceMappingURL=rdap-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rdap-service.js","sourceRoot":"","sources":["../../../src/services/rdap/rdap-service.ts"],"names":[],"mappings":"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"}
|