@cyanheads/whois-mcp-server 0.1.5 → 0.2.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/AGENTS.md +27 -14
- package/CLAUDE.md +27 -14
- package/Dockerfile +48 -34
- package/README.md +30 -35
- package/changelog/0.1.x/0.1.6.md +41 -0
- package/changelog/0.2.x/0.2.0.md +40 -0
- package/dist/app.d.ts +67 -26
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +7 -5
- package/dist/app.js.map +1 -1
- package/dist/mcp-server/tools/definitions/_fqdn.d.ts +9 -3
- package/dist/mcp-server/tools/definitions/_fqdn.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/_fqdn.js +10 -14
- package/dist/mcp-server/tools/definitions/_fqdn.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.d.ts +11 -5
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.js +25 -40
- package/dist/mcp-server/tools/definitions/whois-check-availability.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.d.ts +23 -4
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.js +44 -28
- package/dist/mcp-server/tools/definitions/whois-get-dns.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.d.ts +0 -5
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.js +58 -53
- package/dist/mcp-server/tools/definitions/whois-get-dossier.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.js +9 -5
- package/dist/mcp-server/tools/definitions/whois-lookup-asn.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.d.ts +16 -9
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.js +60 -24
- package/dist/mcp-server/tools/definitions/whois-lookup-domain.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.d.ts +16 -2
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.js +44 -17
- package/dist/mcp-server/tools/definitions/whois-lookup-ip.tool.js.map +1 -1
- package/dist/services/doh/doh-service.d.ts +3 -3
- package/dist/services/doh/doh-service.d.ts.map +1 -1
- package/dist/services/doh/doh-service.js +71 -24
- package/dist/services/doh/doh-service.js.map +1 -1
- package/dist/services/doh/types.d.ts +16 -0
- package/dist/services/doh/types.d.ts.map +1 -1
- package/dist/services/rdap/rdap-service.d.ts +20 -8
- package/dist/services/rdap/rdap-service.d.ts.map +1 -1
- package/dist/services/rdap/rdap-service.js +200 -145
- package/dist/services/rdap/rdap-service.js.map +1 -1
- package/dist/services/rdap/types.d.ts +32 -2
- package/dist/services/rdap/types.d.ts.map +1 -1
- package/package.json +14 -12
- package/server.json +11 -25
|
@@ -5,22 +5,54 @@
|
|
|
5
5
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
6
|
import { JsonRpcErrorCode, McpError } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { getRdapService } from '../../../services/rdap/rdap-service.js';
|
|
8
|
-
import {
|
|
8
|
+
import { REGISTRATION_NAME_PATTERN } from './_fqdn.js';
|
|
9
9
|
export const whoisLookupDomain = tool('whois_lookup_domain', {
|
|
10
10
|
title: 'Domain Registration Lookup',
|
|
11
11
|
description: "Look up a domain's registration record — registrar, created/expiry dates, nameservers, EPP status codes, " +
|
|
12
|
-
'DNSSEC
|
|
12
|
+
'provider DNSSEC evidence, and public registrant organization independently of contact redaction. Uses IANA bootstrap to select ' +
|
|
13
13
|
'the correct per-TLD RDAP server, returning one normalized shape regardless of TLD. When the TLD has no RDAP ' +
|
|
14
|
-
'coverage,
|
|
15
|
-
'whois_check_availability
|
|
14
|
+
'coverage, throws rdap_no_coverage. A missing registry object throws domain_not_found; ' +
|
|
15
|
+
'whois_check_availability returns record status without an eligibility guarantee. include_registrar opts into one ' +
|
|
16
|
+
'bounded registrar referral with separate contact detail; registry fields remain authoritative.',
|
|
16
17
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
17
18
|
input: z.object({
|
|
19
|
+
include_registrar: z
|
|
20
|
+
.boolean()
|
|
21
|
+
.default(false)
|
|
22
|
+
.describe('Follow one guarded registrar RDAP referral for optional contact detail. Registry fields remain authoritative; failed detail is disclosed without discarding the registry record.'),
|
|
18
23
|
domain: z
|
|
19
24
|
.string()
|
|
25
|
+
.max(253)
|
|
26
|
+
.regex(REGISTRATION_NAME_PATTERN, 'Provide a dot-separated ASCII hostname such as example.com; labels are 1–63 characters, without underscores, whitespace or a root dot.')
|
|
20
27
|
.describe('Fully qualified domain name to look up (e.g., "example.com", "github.com"). ' +
|
|
21
28
|
'Must be a valid FQDN — labels separated by dots, each label up to 63 chars.'),
|
|
22
29
|
}),
|
|
23
30
|
output: z.object({
|
|
31
|
+
registrar_detail: z
|
|
32
|
+
.object({
|
|
33
|
+
status: z
|
|
34
|
+
.enum(['found', 'no_referral', 'failed'])
|
|
35
|
+
.describe('Optional registrar lookup outcome.'),
|
|
36
|
+
source: z
|
|
37
|
+
.string()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe('Registrar RDAP source URL, or attempted referral on failure.'),
|
|
40
|
+
registrant_org: z
|
|
41
|
+
.string()
|
|
42
|
+
.optional()
|
|
43
|
+
.describe('Public registrar-reported organization, independent of contact redaction.'),
|
|
44
|
+
registrant_redacted: z
|
|
45
|
+
.boolean()
|
|
46
|
+
.nullable()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe('Explicit registrar privacy evidence; null when absent.'),
|
|
49
|
+
source_error: z
|
|
50
|
+
.string()
|
|
51
|
+
.optional()
|
|
52
|
+
.describe('Optional detail failure; registry fields remain usable.'),
|
|
53
|
+
})
|
|
54
|
+
.optional()
|
|
55
|
+
.describe('Registrar contact detail only when include_registrar is true.'),
|
|
24
56
|
domain: z.string().describe('Normalized domain name (lowercased).'),
|
|
25
57
|
rdap_coverage: z
|
|
26
58
|
.boolean()
|
|
@@ -45,22 +77,20 @@ export const whoisLookupDomain = tool('whois_lookup_domain', {
|
|
|
45
77
|
.array(z.string())
|
|
46
78
|
.describe('EPP status codes (e.g., clientTransferProhibited, serverDeleteProhibited).'),
|
|
47
79
|
nameservers: z.array(z.string()).describe('Authoritative nameservers for this domain.'),
|
|
48
|
-
dnssec_signed: z
|
|
80
|
+
dnssec_signed: z
|
|
81
|
+
.boolean()
|
|
82
|
+
.nullable()
|
|
83
|
+
.describe('Provider delegationSigned value; null when absent.'),
|
|
49
84
|
registrant_org: z
|
|
50
85
|
.string()
|
|
51
86
|
.optional()
|
|
52
|
-
.describe('
|
|
87
|
+
.describe('Public registrant organization from jCard org. Omitted when absent or a placeholder; contact redaction is independent.'),
|
|
53
88
|
registrant_redacted: z
|
|
54
89
|
.boolean()
|
|
55
|
-
.
|
|
90
|
+
.nullable()
|
|
91
|
+
.describe('True for explicit registrant redaction evidence; null when privacy evidence is absent.'),
|
|
56
92
|
}),
|
|
57
93
|
errors: [
|
|
58
|
-
{
|
|
59
|
-
reason: 'invalid_domain',
|
|
60
|
-
code: JsonRpcErrorCode.ValidationError,
|
|
61
|
-
when: 'Input is not a valid FQDN.',
|
|
62
|
-
recovery: 'Provide a valid fully-qualified domain name like "example.com" or "sub.example.org".',
|
|
63
|
-
},
|
|
64
94
|
{
|
|
65
95
|
reason: 'rdap_no_coverage',
|
|
66
96
|
code: JsonRpcErrorCode.NotFound,
|
|
@@ -70,20 +100,15 @@ export const whoisLookupDomain = tool('whois_lookup_domain', {
|
|
|
70
100
|
{
|
|
71
101
|
reason: 'domain_not_found',
|
|
72
102
|
code: JsonRpcErrorCode.NotFound,
|
|
73
|
-
when: 'RDAP server returned 404 — domain
|
|
74
|
-
recovery: '
|
|
103
|
+
when: 'RDAP server returned 404 — no domain record found.',
|
|
104
|
+
recovery: 'Use whois_check_availability for record status; a missing record does not establish registration eligibility.',
|
|
75
105
|
},
|
|
76
106
|
],
|
|
77
107
|
async handler(input, ctx) {
|
|
78
|
-
if (!isValidFqdn(input.domain)) {
|
|
79
|
-
throw ctx.fail('invalid_domain', `"${input.domain}" is not a valid FQDN.`, {
|
|
80
|
-
...ctx.recoveryFor('invalid_domain'),
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
108
|
ctx.log.info('RDAP domain lookup', { domain: input.domain });
|
|
84
109
|
let record;
|
|
85
110
|
try {
|
|
86
|
-
record = await getRdapService().lookupDomain(input.domain, ctx);
|
|
111
|
+
record = await getRdapService().lookupDomain(input.domain, ctx, input.include_registrar);
|
|
87
112
|
}
|
|
88
113
|
catch (err) {
|
|
89
114
|
// Re-throw domain_not_found with recovery hint from the typed contract
|
|
@@ -99,7 +124,6 @@ export const whoisLookupDomain = tool('whois_lookup_domain', {
|
|
|
99
124
|
if (!record.rdap_coverage) {
|
|
100
125
|
throw ctx.fail('rdap_no_coverage', `No RDAP server found for the TLD of "${input.domain}".`, {
|
|
101
126
|
domain: input.domain,
|
|
102
|
-
...ctx.recoveryFor('rdap_no_coverage'),
|
|
103
127
|
});
|
|
104
128
|
}
|
|
105
129
|
return record;
|
|
@@ -124,14 +148,26 @@ export const whoisLookupDomain = tool('whois_lookup_domain', {
|
|
|
124
148
|
lines.push(`**RDAP DB Updated:** ${result.rdap_last_updated}`);
|
|
125
149
|
if (result.handle)
|
|
126
150
|
lines.push(`**Handle:** ${result.handle}`);
|
|
127
|
-
lines.push(`**DNSSEC:** ${result.dnssec_signed ? 'Signed' : 'Not signed'}`);
|
|
128
|
-
lines.push(`**Registrant Redacted:** ${result.registrant_redacted ? 'Yes (GDPR/privacy)' : 'No'}`);
|
|
151
|
+
lines.push(`**DNSSEC:** ${result.dnssec_signed === null ? 'Unknown' : result.dnssec_signed ? 'Signed' : 'Not signed'}`);
|
|
152
|
+
lines.push(`**Registrant Redacted:** ${result.registrant_redacted === null ? 'Unknown' : result.registrant_redacted ? 'Yes (GDPR/privacy)' : 'No'}`);
|
|
129
153
|
if (result.registrant_org)
|
|
130
154
|
lines.push(`**Registrant Org:** ${result.registrant_org}`);
|
|
131
155
|
if (result.status.length > 0)
|
|
132
156
|
lines.push(`**Status:** ${result.status.join(', ')}`);
|
|
133
157
|
if (result.nameservers.length > 0)
|
|
134
158
|
lines.push(`**Nameservers:** ${result.nameservers.join(', ')}`);
|
|
159
|
+
if (result.registrar_detail) {
|
|
160
|
+
const detail = result.registrar_detail;
|
|
161
|
+
lines.push(`**Registrar Detail:** ${detail.status}`);
|
|
162
|
+
if (detail.source)
|
|
163
|
+
lines.push(`**Registrar Source:** ${detail.source}`);
|
|
164
|
+
if (detail.registrant_org)
|
|
165
|
+
lines.push(`**Registrar Registrant Org:** ${detail.registrant_org}`);
|
|
166
|
+
if (detail.status === 'found')
|
|
167
|
+
lines.push(`**Registrar Registrant Redacted:** ${detail.registrant_redacted === null ? 'Unknown' : detail.registrant_redacted ? 'Yes' : 'No'}`);
|
|
168
|
+
if (detail.source_error)
|
|
169
|
+
lines.push(`**Registrar Detail Error:** ${detail.source_error}`);
|
|
170
|
+
}
|
|
135
171
|
return [{ type: 'text', text: lines.join('\n') }];
|
|
136
172
|
},
|
|
137
173
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whois-lookup-domain.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-domain.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"whois-lookup-domain.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-domain.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,qBAAqB,EAAE;IAC3D,KAAK,EAAE,4BAA4B;IACnC,WAAW,EACT,2GAA2G;QAC3G,iIAAiI;QACjI,8GAA8G;QAC9G,wFAAwF;QACxF,mHAAmH;QACnH,gGAAgG;IAClG,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IAE9E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,iBAAiB,EAAE,CAAC;aACjB,OAAO,EAAE;aACT,OAAO,CAAC,KAAK,CAAC;aACd,QAAQ,CACP,kLAAkL,CACnL;QACH,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,GAAG,CAAC,GAAG,CAAC;aACR,KAAK,CACJ,yBAAyB,EACzB,wIAAwI,CACzI;aACA,QAAQ,CACP,8EAA8E;YAC5E,6EAA6E,CAChF;KACJ,CAAC;IAEF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,gBAAgB,EAAE,CAAC;aAChB,MAAM,CAAC;YACN,MAAM,EAAE,CAAC;iBACN,IAAI,CAAC,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;iBACxC,QAAQ,CAAC,oCAAoC,CAAC;YACjD,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,8DAA8D,CAAC;YAC3E,cAAc,EAAE,CAAC;iBACd,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,2EAA2E,CAAC;YACxF,mBAAmB,EAAE,CAAC;iBACnB,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,EAAE;iBACV,QAAQ,CAAC,wDAAwD,CAAC;YACrE,YAAY,EAAE,CAAC;iBACZ,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,yDAAyD,CAAC;SACvE,CAAC;aACD,QAAQ,EAAE;aACV,QAAQ,CAAC,+DAA+D,CAAC;QAC5E,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;QACnE,aAAa,EAAE,CAAC;aACb,OAAO,EAAE;aACT,QAAQ,CACP,qFAAqF,CACtF;QACH,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,+DAA+D,CAAC;QAC5E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;QAC9E,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QAC9E,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QAClF,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,mDAAmD,CAAC;QAChE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QACjF,iBAAiB,EAAE,CAAC;aACjB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,MAAM,EAAE,CAAC;aACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aACjB,QAAQ,CAAC,4EAA4E,CAAC;QACzF,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACvF,aAAa,EAAE,CAAC;aACb,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,oDAAoD,CAAC;QACjE,cAAc,EAAE,CAAC;aACd,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,wHAAwH,CACzH;QACH,mBAAmB,EAAE,CAAC;aACnB,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CACP,wFAAwF,CACzF;KACJ,CAAC;IAEF,MAAM,EAAE;QACN;YACE,MAAM,EAAE,kBAAkB;YAC1B,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,uEAAuE;YAC7E,QAAQ,EACN,wGAAwG;SAC3G;QACD;YACE,MAAM,EAAE,kBAAkB;YAC1B,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,oDAAoD;YAC1D,QAAQ,EACN,+GAA+G;SAClH;KACF;IAED,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAE7D,IAAI,MAAwB,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC3F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,uEAAuE;YACvE,IACE,GAAG,YAAY,QAAQ;gBACtB,GAAG,CAAC,IAAwC,EAAE,MAAM,KAAK,kBAAkB,EAC5E,CAAC;gBACD,MAAM,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,CAAC,OAAO,EAAE;oBAC9C,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE;oBAClC,GAAG,GAAG,CAAC,WAAW,CAAC,kBAAkB,CAAC;iBACvC,CAAC,CAAC;YACL,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YAC1B,MAAM,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,wCAAwC,KAAK,CAAC,MAAM,IAAI,EAAE;gBAC3F,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAEzC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YAC9D,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACrC,IAAI,MAAM,CAAC,SAAS;YAClB,KAAK,CAAC,IAAI,CACR,kBAAkB,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,WAAW,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9G,CAAC;QACJ,IAAI,MAAM,CAAC,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QAC3E,IAAI,MAAM,CAAC,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QACzE,IAAI,MAAM,CAAC,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QAChF,IAAI,MAAM,CAAC,iBAAiB;YAAE,KAAK,CAAC,IAAI,CAAC,wBAAwB,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAC7F,IAAI,MAAM,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9D,KAAK,CAAC,IAAI,CACR,eAAe,MAAM,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,EAAE,CAC5G,CAAC;QACF,KAAK,CAAC,IAAI,CACR,4BAA4B,MAAM,CAAC,mBAAmB,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,CACzI,CAAC;QACF,IAAI,MAAM,CAAC,cAAc;YAAE,KAAK,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;QACtF,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpF,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClE,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,yBAAyB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YACrD,IAAI,MAAM,CAAC,MAAM;gBAAE,KAAK,CAAC,IAAI,CAAC,yBAAyB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YACxE,IAAI,MAAM,CAAC,cAAc;gBACvB,KAAK,CAAC,IAAI,CAAC,iCAAiC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;YACvE,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO;gBAC3B,KAAK,CAAC,IAAI,CACR,sCAAsC,MAAM,CAAC,mBAAmB,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CACpI,CAAC;YACJ,IAAI,MAAM,CAAC,YAAY;gBAAE,KAAK,CAAC,IAAI,CAAC,+BAA+B,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QAC5F,CAAC;QAED,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -12,6 +12,7 @@ export declare const whoisLookupIp: import("@cyanheads/mcp-ts-core").ToolDefinit
|
|
|
12
12
|
start_address: z.ZodOptional<z.ZodString>;
|
|
13
13
|
end_address: z.ZodOptional<z.ZodString>;
|
|
14
14
|
cidr: z.ZodOptional<z.ZodString>;
|
|
15
|
+
cidrs: z.ZodArray<z.ZodString>;
|
|
15
16
|
ip_version: z.ZodOptional<z.ZodString>;
|
|
16
17
|
name: z.ZodOptional<z.ZodString>;
|
|
17
18
|
type: z.ZodOptional<z.ZodString>;
|
|
@@ -19,8 +20,21 @@ export declare const whoisLookupIp: import("@cyanheads/mcp-ts-core").ToolDefinit
|
|
|
19
20
|
org_name: z.ZodOptional<z.ZodString>;
|
|
20
21
|
abuse_email: z.ZodOptional<z.ZodString>;
|
|
21
22
|
ptr: z.ZodNullable<z.ZodString>;
|
|
23
|
+
ptr_status: z.ZodEnum<{
|
|
24
|
+
failed: "failed";
|
|
25
|
+
found: "found";
|
|
26
|
+
not_found: "not_found";
|
|
27
|
+
}>;
|
|
28
|
+
ptr_source_error: z.ZodOptional<z.ZodString>;
|
|
22
29
|
rdap_source: z.ZodOptional<z.ZodString>;
|
|
23
30
|
}, z.core.$strip>, readonly [{
|
|
31
|
+
readonly reason: "ip_no_rdap_route";
|
|
32
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
33
|
+
readonly when: "A successfully loaded IANA bootstrap has no covering RIR route.";
|
|
34
|
+
readonly recovery: "Try another address; this range has no RDAP route in the IANA bootstrap.";
|
|
35
|
+
readonly retryable: false;
|
|
36
|
+
readonly thrownBy: "service";
|
|
37
|
+
}, {
|
|
24
38
|
readonly reason: "invalid_ip";
|
|
25
39
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
26
40
|
readonly when: "Input is not a valid IPv4, IPv6, or CIDR address.";
|
|
@@ -28,8 +42,8 @@ export declare const whoisLookupIp: import("@cyanheads/mcp-ts-core").ToolDefinit
|
|
|
28
42
|
}, {
|
|
29
43
|
readonly reason: "private_range";
|
|
30
44
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
31
|
-
readonly when: "
|
|
32
|
-
readonly recovery: "
|
|
45
|
+
readonly when: "The numeric address falls within the server’s explicit excluded ranges.";
|
|
46
|
+
readonly recovery: "Choose an address outside the excluded ranges listed in this tool’s description.";
|
|
33
47
|
readonly thrownBy: "service";
|
|
34
48
|
}, {
|
|
35
49
|
readonly reason: "ip_not_found";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whois-lookup-ip.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-ip.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"whois-lookup-ip.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-ip.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKjE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6IxB,CAAC"}
|
|
@@ -6,25 +6,37 @@ import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
|
6
6
|
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
7
|
import { getDohService } from '../../../services/doh/doh-service.js';
|
|
8
8
|
import { getRdapService, ipv4ToPtr, ipv6ToPtr, validateIp } from '../../../services/rdap/rdap-service.js';
|
|
9
|
+
import { IP_PATTERN } from './_fqdn.js';
|
|
9
10
|
export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
10
11
|
title: 'IP Address / Network Lookup',
|
|
11
12
|
description: 'Look up an IP address or CIDR block via RIR RDAP (ARIN, RIPE, APNIC, LACNIC, AFRINIC — auto-routed ' +
|
|
12
|
-
'via IANA bootstrap). Returns netblock, org, country,
|
|
13
|
-
'via DoH. PTR
|
|
14
|
-
'
|
|
13
|
+
'via IANA bootstrap). Returns netblock, org, country, all provider CIDRs, abuse contact email, and reverse DNS (PTR) ' +
|
|
14
|
+
'via DoH. PTR status distinguishes found, not_found, and failed with ptr_source_error. Alias traversal is limited ' +
|
|
15
|
+
'to five transitions under one DNS deadline. The base address is queried for CIDR input. ' +
|
|
16
|
+
'The server excludes IPv4 0/8, 10/8, 100.64/10, 127/8, 169.254/16, 172.16/12, 192.168/16, 255/8 ' +
|
|
17
|
+
'and IPv6 ::1/128, fc00::/7, fe80::/10. Other special-use addresses remain eligible for lookup.',
|
|
15
18
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
16
19
|
input: z.object({
|
|
17
20
|
ip: z
|
|
18
21
|
.string()
|
|
22
|
+
.min(1)
|
|
23
|
+
.regex(IP_PATTERN, 'Provide an IPv4/IPv6 address with at most one decimal CIDR prefix; no spaces, brackets or zone IDs.')
|
|
19
24
|
.describe('IPv4 address (e.g., "8.8.8.8"), IPv6 address (e.g., "2001:4860:4860::8888"), or CIDR notation ' +
|
|
20
|
-
'(e.g., "192.0.2.0/24").
|
|
25
|
+
'(e.g., "192.0.2.0/24"). One decimal prefix in 0–32 (IPv4) or 0–128 (IPv6); no whitespace, ' +
|
|
26
|
+
'zone IDs, or brackets. IPv4-mapped IPv6 uses its embedded IPv4 for lookup and PTR.'),
|
|
21
27
|
}),
|
|
22
28
|
output: z.object({
|
|
23
29
|
ip: z.string().describe('The IP or CIDR queried.'),
|
|
24
30
|
handle: z.string().optional().describe('RIR handle / object identifier.'),
|
|
25
31
|
start_address: z.string().optional().describe('Start address of the IP netblock.'),
|
|
26
32
|
end_address: z.string().optional().describe('End address of the IP netblock.'),
|
|
27
|
-
cidr: z
|
|
33
|
+
cidr: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe('Provider CIDR only when the allocation has exactly one component.'),
|
|
37
|
+
cidrs: z
|
|
38
|
+
.array(z.string())
|
|
39
|
+
.describe('All provider CIDR components in upstream order; empty when absent.'),
|
|
28
40
|
ip_version: z.string().optional().describe('IP version: "v4" or "v6".'),
|
|
29
41
|
name: z.string().optional().describe('Network name assigned by the RIR.'),
|
|
30
42
|
type: z.string().optional().describe('Network type (e.g., "DIRECT ALLOCATION").'),
|
|
@@ -38,12 +50,27 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
38
50
|
.string()
|
|
39
51
|
.nullable()
|
|
40
52
|
.describe('Reverse DNS hostname (PTR record). Null when PTR lookup fails, returns no answer, or domain is NXDOMAIN.'),
|
|
53
|
+
ptr_status: z
|
|
54
|
+
.enum(['found', 'not_found', 'failed'])
|
|
55
|
+
.describe('PTR outcome: matching hostname, successful absence, or failed resolver/alias traversal.'),
|
|
56
|
+
ptr_source_error: z
|
|
57
|
+
.string()
|
|
58
|
+
.optional()
|
|
59
|
+
.describe('PTR failure explanation; RDAP data remains usable.'),
|
|
41
60
|
rdap_source: z
|
|
42
61
|
.string()
|
|
43
62
|
.optional()
|
|
44
63
|
.describe('RIR that provided the RDAP data (ARIN, RIPE, APNIC, LACNIC, AFRINIC).'),
|
|
45
64
|
}),
|
|
46
65
|
errors: [
|
|
66
|
+
{
|
|
67
|
+
reason: 'ip_no_rdap_route',
|
|
68
|
+
code: JsonRpcErrorCode.NotFound,
|
|
69
|
+
when: 'A successfully loaded IANA bootstrap has no covering RIR route.',
|
|
70
|
+
recovery: 'Try another address; this range has no RDAP route in the IANA bootstrap.',
|
|
71
|
+
retryable: false,
|
|
72
|
+
thrownBy: 'service',
|
|
73
|
+
},
|
|
47
74
|
{
|
|
48
75
|
reason: 'invalid_ip',
|
|
49
76
|
code: JsonRpcErrorCode.ValidationError,
|
|
@@ -53,8 +80,8 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
53
80
|
{
|
|
54
81
|
reason: 'private_range',
|
|
55
82
|
code: JsonRpcErrorCode.ValidationError,
|
|
56
|
-
when: '
|
|
57
|
-
recovery: '
|
|
83
|
+
when: 'The numeric address falls within the server’s explicit excluded ranges.',
|
|
84
|
+
recovery: 'Choose an address outside the excluded ranges listed in this tool’s description.',
|
|
58
85
|
thrownBy: 'service',
|
|
59
86
|
},
|
|
60
87
|
{
|
|
@@ -66,21 +93,18 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
66
93
|
},
|
|
67
94
|
],
|
|
68
95
|
async handler(input, ctx) {
|
|
69
|
-
const
|
|
70
|
-
if (!valid) {
|
|
71
|
-
throw ctx.fail('invalid_ip', `"${input.ip}" is not a valid IPv4, IPv6, or CIDR address
|
|
72
|
-
...ctx.recoveryFor('invalid_ip'),
|
|
73
|
-
});
|
|
96
|
+
const parsed = validateIp(input.ip);
|
|
97
|
+
if (!parsed.valid) {
|
|
98
|
+
throw ctx.fail('invalid_ip', `"${input.ip}" is not a valid IPv4, IPv6, or CIDR address.`);
|
|
74
99
|
}
|
|
75
100
|
ctx.log.info('RDAP IP lookup', { ip: input.ip });
|
|
76
101
|
// getRdapService().lookupIp already throws invalid_ip / private_range via factories with data.reason
|
|
77
102
|
const network = await getRdapService().lookupIp(input.ip, ctx);
|
|
78
103
|
// PTR lookup — best-effort, failure = null
|
|
79
|
-
const base
|
|
80
|
-
const isIpv6 = base.includes(':');
|
|
104
|
+
const { base, isIpv6 } = parsed;
|
|
81
105
|
const ptrName = isIpv6 ? ipv6ToPtr(base) : ipv4ToPtr(base);
|
|
82
106
|
const ptr = await getDohService().ptrLookup(ptrName, ctx);
|
|
83
|
-
return { ...network, ptr };
|
|
107
|
+
return { ...network, ...ptr };
|
|
84
108
|
},
|
|
85
109
|
format: (result) => {
|
|
86
110
|
const lines = [];
|
|
@@ -89,8 +113,8 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
89
113
|
lines.push(`**RIR Source:** ${result.rdap_source}`);
|
|
90
114
|
if (result.org_name)
|
|
91
115
|
lines.push(`**Organization:** ${result.org_name}`);
|
|
92
|
-
if (result.
|
|
93
|
-
lines.push(`**
|
|
116
|
+
if (result.cidrs.length)
|
|
117
|
+
lines.push(`**CIDRs:** ${result.cidrs.join(', ')}`);
|
|
94
118
|
if (result.start_address && result.end_address) {
|
|
95
119
|
lines.push(`**Range:** ${result.start_address} — ${result.end_address}`);
|
|
96
120
|
}
|
|
@@ -107,6 +131,9 @@ export const whoisLookupIp = tool('whois_lookup_ip', {
|
|
|
107
131
|
if (result.abuse_email)
|
|
108
132
|
lines.push(`**Abuse Email:** ${result.abuse_email}`);
|
|
109
133
|
lines.push(`**Reverse DNS (PTR):** ${result.ptr ?? 'Not available'}`);
|
|
134
|
+
lines.push(`**PTR Status:** ${result.ptr_status}`);
|
|
135
|
+
if (result.ptr_source_error)
|
|
136
|
+
lines.push(`**PTR Error:** ${result.ptr_source_error}`);
|
|
110
137
|
return [{ type: 'text', text: lines.join('\n') }];
|
|
111
138
|
},
|
|
112
139
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whois-lookup-ip.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-ip.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"whois-lookup-ip.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/whois-lookup-ip.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type { Context } from '@cyanheads/mcp-ts-core';
|
|
7
7
|
import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
|
|
8
8
|
import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
|
|
9
|
-
import type { DnsLookupResult, DnsRecordType } from './types.js';
|
|
9
|
+
import type { DnsLookupResult, DnsRecordType, PtrLookupResult } from './types.js';
|
|
10
10
|
export declare class DohService {
|
|
11
11
|
/** Fetch DNS records for one type from a single DoH endpoint */
|
|
12
12
|
private fetchSingleType;
|
|
@@ -21,9 +21,9 @@ export declare class DohService {
|
|
|
21
21
|
* Perform a reverse DNS (PTR) lookup for an IP address.
|
|
22
22
|
* IPv4: reverses octets + .in-addr.arpa
|
|
23
23
|
* IPv6: reverses nibbles + .ip6.arpa
|
|
24
|
-
*
|
|
24
|
+
* Follows reachable aliases under one deadline; distinguishes absence from failure.
|
|
25
25
|
*/
|
|
26
|
-
ptrLookup(ptrName: string, ctx: Context): Promise<
|
|
26
|
+
ptrLookup(ptrName: string, ctx: Context): Promise<PtrLookupResult>;
|
|
27
27
|
}
|
|
28
28
|
export declare function initDohService(_config: AppConfig, _storage: StorageService): void;
|
|
29
29
|
export declare function getDohService(): DohService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doh-service.d.ts","sourceRoot":"","sources":["../../../src/services/doh/doh-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"doh-service.d.ts","sourceRoot":"","sources":["../../../src/services/doh/doh-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EAGb,eAAe,EAChB,MAAM,YAAY,CAAC;AAWpB,qBAAa,UAAU;IACrB,gEAAgE;IAChE,OAAO,CAAC,eAAe;IA8CvB;;;;;OAKG;IACG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CA4D3F;IAED;;;;;OAKG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CA2CvE;CACF;AAMD,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAEjF;AAED,wBAAgB,aAAa,IAAI,UAAU,CAK1C"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* CAA records always use NextDNS because Cloudflare returns raw hex wire format for them.
|
|
4
4
|
* @module services/doh/doh-service
|
|
5
5
|
*/
|
|
6
|
+
import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
6
7
|
import { fetchWithTimeout, withRetry } from '@cyanheads/mcp-ts-core/utils';
|
|
7
8
|
import { getServerConfig } from '../../config/server-config.js';
|
|
8
9
|
import { DNS_TYPE_NUMBERS } from './types.js';
|
|
@@ -15,13 +16,26 @@ export class DohService {
|
|
|
15
16
|
fetchSingleType(domain, type, baseUrl, timeoutMs, ctx, source) {
|
|
16
17
|
const url = `${baseUrl}?name=${encodeURIComponent(domain)}&type=${encodeURIComponent(type)}`;
|
|
17
18
|
return withRetry(async () => {
|
|
19
|
+
ctx.signal.throwIfAborted();
|
|
18
20
|
const response = await fetchWithTimeout(url, timeoutMs, ctx, {
|
|
19
21
|
headers: {
|
|
20
22
|
Accept: 'application/dns-json',
|
|
21
23
|
},
|
|
22
24
|
signal: ctx.signal,
|
|
23
25
|
});
|
|
24
|
-
|
|
26
|
+
const data = (await response.json());
|
|
27
|
+
ctx.signal.throwIfAborted();
|
|
28
|
+
if (data.TC === true || (data.Status !== 0 && data.Status !== 3)) {
|
|
29
|
+
throw serviceUnavailable(`DNS ${type} query via ${source} failed: ${data.TC ? 'truncated response' : `RCODE ${data.Status}`}.`, {
|
|
30
|
+
reason: 'dns_response_failed',
|
|
31
|
+
type,
|
|
32
|
+
resolver: source,
|
|
33
|
+
status: data.Status,
|
|
34
|
+
truncated: data.TC === true,
|
|
35
|
+
recovery: { hint: 'Retry the DNS query later or choose another record type.' },
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return data;
|
|
25
39
|
}, {
|
|
26
40
|
operation: `doh.fetchSingleType.${source}`,
|
|
27
41
|
context: ctx,
|
|
@@ -37,31 +51,30 @@ export class DohService {
|
|
|
37
51
|
* Returns `nxdomain: true` when NXDOMAIN (Status 3) is returned.
|
|
38
52
|
*/
|
|
39
53
|
async lookup(domain, types, ctx) {
|
|
54
|
+
ctx.signal.throwIfAborted();
|
|
40
55
|
const config = getServerConfig();
|
|
41
56
|
const records = [];
|
|
42
57
|
let nxdomain = false;
|
|
43
|
-
|
|
44
|
-
// nextdns = all types used NextDNS (either CAA-primary or Cloudflare-fallback)
|
|
45
|
-
let usedCloudflare = false;
|
|
46
|
-
await Promise.all(types.map(async (type) => {
|
|
58
|
+
const querySources = await Promise.all([...new Set(types)].map(async (type) => {
|
|
47
59
|
// CAA always via NextDNS; everything else Cloudflare first
|
|
48
60
|
const primaryUrl = type === 'CAA' ? NEXTDNS_DOH : CLOUDFLARE_DOH;
|
|
49
|
-
|
|
61
|
+
let source = type === 'CAA' ? 'nextdns' : 'cloudflare';
|
|
50
62
|
let resp;
|
|
51
63
|
try {
|
|
52
|
-
resp = await this.fetchSingleType(domain, type, primaryUrl, config.dohTimeoutMs, ctx,
|
|
53
|
-
// Only count as cloudflare when we successfully used Cloudflare (not CAA)
|
|
54
|
-
if (type !== 'CAA')
|
|
55
|
-
usedCloudflare = true;
|
|
64
|
+
resp = await this.fetchSingleType(domain, type, primaryUrl, config.dohTimeoutMs, ctx, source);
|
|
56
65
|
}
|
|
57
|
-
catch {
|
|
66
|
+
catch (error) {
|
|
67
|
+
ctx.signal.throwIfAborted();
|
|
68
|
+
if (type === 'CAA')
|
|
69
|
+
throw error;
|
|
58
70
|
// Fallback to NextDNS for non-CAA types
|
|
59
71
|
resp = await this.fetchSingleType(domain, type, NEXTDNS_DOH, config.dohTimeoutMs, ctx, 'nextdns');
|
|
72
|
+
source = 'nextdns';
|
|
60
73
|
}
|
|
61
74
|
if (resp.Status === 3) {
|
|
62
75
|
// NXDOMAIN — domain does not exist in DNS
|
|
63
76
|
nxdomain = true;
|
|
64
|
-
return;
|
|
77
|
+
return { type, source };
|
|
65
78
|
}
|
|
66
79
|
for (const answer of resp.Answer ?? []) {
|
|
67
80
|
const typeName = TYPE_NUM_TO_NAME[answer.type];
|
|
@@ -74,28 +87,62 @@ export class DohService {
|
|
|
74
87
|
data: answer.data,
|
|
75
88
|
});
|
|
76
89
|
}
|
|
90
|
+
return { type, source };
|
|
77
91
|
}));
|
|
78
|
-
const source =
|
|
79
|
-
|
|
92
|
+
const source = querySources.some((query) => query.source === 'cloudflare')
|
|
93
|
+
? 'cloudflare'
|
|
94
|
+
: 'nextdns';
|
|
95
|
+
return { domain, nxdomain, records, source, query_sources: querySources };
|
|
80
96
|
}
|
|
81
97
|
/**
|
|
82
98
|
* Perform a reverse DNS (PTR) lookup for an IP address.
|
|
83
99
|
* IPv4: reverses octets + .in-addr.arpa
|
|
84
100
|
* IPv6: reverses nibbles + .ip6.arpa
|
|
85
|
-
*
|
|
101
|
+
* Follows reachable aliases under one deadline; distinguishes absence from failure.
|
|
86
102
|
*/
|
|
87
103
|
async ptrLookup(ptrName, ctx) {
|
|
104
|
+
const signal = AbortSignal.any([
|
|
105
|
+
ctx.signal,
|
|
106
|
+
AbortSignal.timeout(getServerConfig().dohTimeoutMs),
|
|
107
|
+
]);
|
|
108
|
+
const ptrCtx = { ...ctx, signal };
|
|
109
|
+
const normalize = (name) => name.toLowerCase().replace(/\.$/, '');
|
|
110
|
+
let owner = normalize(ptrName);
|
|
111
|
+
let hops = 0;
|
|
112
|
+
const visited = new Set([owner]);
|
|
88
113
|
try {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
while (true) {
|
|
115
|
+
signal.throwIfAborted();
|
|
116
|
+
const result = await this.lookup(owner, ['PTR'], ptrCtx);
|
|
117
|
+
if (result.nxdomain)
|
|
118
|
+
return { ptr: null, ptr_status: 'not_found' };
|
|
119
|
+
let followed = false;
|
|
120
|
+
while (true) {
|
|
121
|
+
const ptr = result.records.find((record) => record.type === 'PTR' && normalize(record.name) === owner);
|
|
122
|
+
if (ptr)
|
|
123
|
+
return { ptr: normalize(ptr.data), ptr_status: 'found' };
|
|
124
|
+
const alias = result.records.find((record) => record.type === 'CNAME' && normalize(record.name) === owner);
|
|
125
|
+
if (!alias)
|
|
126
|
+
break;
|
|
127
|
+
const target = normalize(alias.data);
|
|
128
|
+
if (visited.has(target) || hops === 5)
|
|
129
|
+
throw serviceUnavailable('Reverse DNS alias loop or five-transition limit reached.');
|
|
130
|
+
visited.add(target);
|
|
131
|
+
owner = target;
|
|
132
|
+
hops++;
|
|
133
|
+
followed = true;
|
|
134
|
+
}
|
|
135
|
+
if (!followed)
|
|
136
|
+
return { ptr: null, ptr_status: 'not_found' };
|
|
137
|
+
}
|
|
96
138
|
}
|
|
97
|
-
catch {
|
|
98
|
-
|
|
139
|
+
catch (error) {
|
|
140
|
+
ctx.signal.throwIfAborted();
|
|
141
|
+
return {
|
|
142
|
+
ptr: null,
|
|
143
|
+
ptr_status: 'failed',
|
|
144
|
+
ptr_source_error: error instanceof Error ? error.message : String(error),
|
|
145
|
+
};
|
|
99
146
|
}
|
|
100
147
|
}
|
|
101
148
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doh-service.js","sourceRoot":"","sources":["../../../src/services/doh/doh-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"doh-service.js","sourceRoot":"","sources":["../../../src/services/doh/doh-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,7 +39,23 @@ export interface NormalizedDnsRecord {
|
|
|
39
39
|
export interface DnsLookupResult {
|
|
40
40
|
domain: string;
|
|
41
41
|
nxdomain: boolean;
|
|
42
|
+
query_sources: Array<{
|
|
43
|
+
type: DnsRecordType;
|
|
44
|
+
source: 'cloudflare' | 'nextdns';
|
|
45
|
+
}>;
|
|
42
46
|
records: NormalizedDnsRecord[];
|
|
43
47
|
source: 'cloudflare' | 'nextdns';
|
|
44
48
|
}
|
|
49
|
+
/** Best-effort reverse lookup distinguishes a hostname, successful absence and failure. */
|
|
50
|
+
export type PtrLookupResult = {
|
|
51
|
+
ptr: string;
|
|
52
|
+
ptr_status: 'found';
|
|
53
|
+
} | {
|
|
54
|
+
ptr: null;
|
|
55
|
+
ptr_status: 'not_found';
|
|
56
|
+
} | {
|
|
57
|
+
ptr: null;
|
|
58
|
+
ptr_status: 'failed';
|
|
59
|
+
ptr_source_error: string;
|
|
60
|
+
};
|
|
45
61
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/doh/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG,GAAG,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEjG,6BAA6B;AAC7B,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAU1D,CAAC;AAEF,uCAAuC;AACvC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,qCAAqC;AACrC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC;CAClC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/doh/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG,GAAG,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEjG,6BAA6B;AAC7B,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAU1D,CAAC;AAEF,uCAAuC;AACvC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,qCAAqC;AACrC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;IAChF,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC;CAClC;AAED,2FAA2F;AAC3F,MAAM,MAAM,eAAe,GACvB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,GACpC;IAAE,GAAG,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,WAAW,CAAA;CAAE,GACtC;IAAE,GAAG,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,QAAQ,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAAC"}
|