@modular-intelligence/dns-recon 1.0.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.
Files changed (3) hide show
  1. package/README.md +1073 -0
  2. package/dist/index.js +44864 -0
  3. package/package.json +35 -0
package/README.md ADDED
@@ -0,0 +1,1073 @@
1
+ # DNS Reconnaissance MCP Server
2
+
3
+ A Model Context Protocol (MCP) server for performing DNS and WHOIS reconnaissance tasks. Query DNS records, perform reverse lookups, retrieve WHOIS registration data, discover subdomains via certificate transparency, and check DNS propagation across global resolvers.
4
+
5
+ ## Overview
6
+
7
+ This MCP server provides a comprehensive toolkit for network reconnaissance and DNS enumeration. It wraps standard command-line tools (`dig`, `whois`) and the free Certificate Transparency API (crt.sh) to enable Claude and other MCP clients to:
8
+
9
+ - Query various DNS record types (A, AAAA, MX, NS, TXT, CNAME, SOA, PTR, SRV, CAA)
10
+ - Perform reverse DNS lookups
11
+ - Retrieve WHOIS registration information for domains and IP addresses
12
+ - Discover subdomains and certificate information via Certificate Transparency logs
13
+ - Perform passive subdomain enumeration from multiple sources with optional DNS brute-force
14
+ - Check DNS record propagation across global DNS resolvers
15
+ - Attempt DNS zone transfers (AXFR)
16
+
17
+ All operations include input validation and security checks to prevent injection attacks and invalid queries.
18
+
19
+ ## Tools
20
+
21
+ | Tool | Description | Use Case |
22
+ |------|-------------|----------|
23
+ | `dns_lookup` | Query DNS records with dig | Find A, MX, NS, TXT and other DNS records |
24
+ | `dns_reverse` | Reverse DNS lookup for IP | Identify hostname associated with an IP |
25
+ | `whois_lookup` | WHOIS registration data | Get registrar, nameservers, and domain/IP details |
26
+ | `cert_transparency` | Search Certificate Transparency logs | Discover subdomains via SSL/TLS certificates |
27
+ | `dns_zone_transfer` | Attempt DNS AXFR zone transfer | Test for misconfigured nameservers (usually blocked) |
28
+ | `subdomain_enum` | Multi-source passive subdomain enumeration | Discover subdomains from cert transparency with optional DNS brute-force |
29
+ | `dns_propagation` | Check DNS propagation across global resolvers | Verify DNS record consistency and global propagation |
30
+
31
+ ### dns_lookup
32
+
33
+ Query DNS records for a domain using the `dig` command.
34
+
35
+ **Input Schema:**
36
+ ```json
37
+ {
38
+ "domain": "string (required)",
39
+ "record_type": "enum: A | AAAA | MX | NS | TXT | CNAME | SOA | PTR | SRV | CAA | ANY (default: A)",
40
+ "nameserver": "string (optional, e.g., 8.8.8.8)"
41
+ }
42
+ ```
43
+
44
+ **Example Request:**
45
+ ```json
46
+ {
47
+ "domain": "example.com",
48
+ "record_type": "MX"
49
+ }
50
+ ```
51
+
52
+ **Example Response:**
53
+ ```json
54
+ {
55
+ "domain": "example.com",
56
+ "record_type": "MX",
57
+ "records": [
58
+ {
59
+ "name": "example.com",
60
+ "type": "MX",
61
+ "ttl": 3600,
62
+ "value": "10 mail.example.com"
63
+ },
64
+ {
65
+ "name": "example.com",
66
+ "type": "MX",
67
+ "ttl": 3600,
68
+ "value": "20 mail2.example.com"
69
+ }
70
+ ],
71
+ "query_time_ms": 45,
72
+ "server": "default"
73
+ }
74
+ ```
75
+
76
+ **Common Record Types:**
77
+
78
+ - **A**: IPv4 address
79
+ - **AAAA**: IPv6 address
80
+ - **MX**: Mail exchange server
81
+ - **NS**: Nameserver
82
+ - **TXT**: Text record (DKIM, SPF, DMARC, verification)
83
+ - **CNAME**: Canonical name (alias)
84
+ - **SOA**: Start of Authority
85
+ - **PTR**: Pointer record (reverse DNS)
86
+ - **SRV**: Service record
87
+ - **CAA**: Certificate Authority Authorization
88
+ - **ANY**: All record types
89
+
90
+ ### dns_reverse
91
+
92
+ Perform a reverse DNS lookup to find the hostname associated with an IP address.
93
+
94
+ **Input Schema:**
95
+ ```json
96
+ {
97
+ "ip": "string (required, IPv4 address)"
98
+ }
99
+ ```
100
+
101
+ **Example Request:**
102
+ ```json
103
+ {
104
+ "ip": "93.184.216.34"
105
+ }
106
+ ```
107
+
108
+ **Example Response:**
109
+ ```json
110
+ {
111
+ "ip": "93.184.216.34",
112
+ "hostname": "example.com",
113
+ "query_time_ms": 32
114
+ }
115
+ ```
116
+
117
+ **Note:** Many IP addresses do not have reverse DNS records configured. When no PTR record exists, `hostname` will be `null`.
118
+
119
+ ### whois_lookup
120
+
121
+ Retrieve WHOIS registration information for a domain or IP address.
122
+
123
+ **Input Schema:**
124
+ ```json
125
+ {
126
+ "query": "string (required, domain or IP address)"
127
+ }
128
+ ```
129
+
130
+ **Example Request (Domain):**
131
+ ```json
132
+ {
133
+ "query": "example.com"
134
+ }
135
+ ```
136
+
137
+ **Example Response (Domain):**
138
+ ```json
139
+ {
140
+ "query": "example.com",
141
+ "registrar": "VeriSign Global Registry Services",
142
+ "creation_date": "1995-08-14T00:00:00Z",
143
+ "expiration_date": "2025-08-13T23:59:59Z",
144
+ "updated_date": "2022-08-14T00:00:00Z",
145
+ "name_servers": [
146
+ "a.iana-servers.net",
147
+ "b.iana-servers.net"
148
+ ],
149
+ "status": [
150
+ "clientDeleteProhibited",
151
+ "clientTransferProhibited",
152
+ "clientUpdateProhibited"
153
+ ],
154
+ "raw": "[Full WHOIS output truncated to 3000 characters...]"
155
+ }
156
+ ```
157
+
158
+ **Example Request (IP Address):**
159
+ ```json
160
+ {
161
+ "query": "93.184.216.0"
162
+ }
163
+ ```
164
+
165
+ **Example Response (IP):**
166
+ ```json
167
+ {
168
+ "query": "93.184.216.0",
169
+ "registrar": "ARIN",
170
+ "creation_date": "2010-06-18T00:00:00Z",
171
+ "expiration_date": null,
172
+ "updated_date": "2010-06-18T00:00:00Z",
173
+ "name_servers": [],
174
+ "status": [],
175
+ "raw": "[Full WHOIS output truncated to 3000 characters...]"
176
+ }
177
+ ```
178
+
179
+ **Note:** The WHOIS response includes parsed fields (registrar, dates, nameservers, status) as well as the raw WHOIS output. Parsing varies by registry and type.
180
+
181
+ ### cert_transparency
182
+
183
+ Search Certificate Transparency (CT) logs via crt.sh to discover subdomains and certificate information.
184
+
185
+ **Input Schema:**
186
+ ```json
187
+ {
188
+ "domain": "string (required)",
189
+ "include_expired": "boolean (default: false)"
190
+ }
191
+ ```
192
+
193
+ **Example Request:**
194
+ ```json
195
+ {
196
+ "domain": "example.com",
197
+ "include_expired": false
198
+ }
199
+ ```
200
+
201
+ **Example Response:**
202
+ ```json
203
+ {
204
+ "domain": "example.com",
205
+ "certificate_count": 42,
206
+ "certificates": [
207
+ {
208
+ "issuer_name": "Let's Encrypt Authority X3",
209
+ "common_name": "example.com",
210
+ "name_value": "example.com\nwww.example.com\nmail.example.com",
211
+ "not_before": "2023-11-15T10:30:00Z",
212
+ "not_after": "2024-02-13T10:29:59Z",
213
+ "serial_number": "abc123def456"
214
+ },
215
+ {
216
+ "issuer_name": "DigiCert Global CA G2",
217
+ "common_name": "*.example.com",
218
+ "name_value": "*.example.com\nexample.com",
219
+ "not_before": "2023-01-10T00:00:00Z",
220
+ "not_after": "2024-01-10T23:59:59Z",
221
+ "serial_number": "xyz789uvw012"
222
+ }
223
+ ],
224
+ "unique_subdomains": [
225
+ "api.example.com",
226
+ "blog.example.com",
227
+ "example.com",
228
+ "mail.example.com",
229
+ "www.example.com"
230
+ ]
231
+ }
232
+ ```
233
+
234
+ **About Certificate Transparency:**
235
+
236
+ Certificate Transparency is a system where publicly-issued SSL/TLS certificates are logged in append-only ledgers. The crt.sh website (run by Comodo) provides free search access to these logs. This is a legitimate, legal, and widely-used reconnaissance technique. No API key is required; the service is free and public.
237
+
238
+ **Use Cases:**
239
+
240
+ - Discover subdomains without executing network queries
241
+ - Find certificate issuance history
242
+ - Identify new services that may not be DNS enumerated
243
+ - Monitoring unauthorized certificate issuance
244
+
245
+ ### subdomain_enum
246
+
247
+ Perform multi-source passive subdomain enumeration using Certificate Transparency logs and optional DNS brute-force.
248
+
249
+ **Input Parameters:**
250
+ ```typescript
251
+ {
252
+ domain: string // Required: Domain to enumerate
253
+ use_bruteforce: boolean // Optional: Enable DNS brute-force (default: false)
254
+ max_results: number // Optional: Maximum results to return 1-500 (default: 100)
255
+ }
256
+ ```
257
+
258
+ **Example Request:**
259
+ ```json
260
+ {
261
+ "domain": "example.com",
262
+ "use_bruteforce": false,
263
+ "max_results": 100
264
+ }
265
+ ```
266
+
267
+ **Example Output:**
268
+ ```json
269
+ {
270
+ "domain": "example.com",
271
+ "total_found": 12,
272
+ "sources": {
273
+ "crt.sh": 12,
274
+ "dns_bruteforce": 0
275
+ },
276
+ "subdomains": [
277
+ "api.example.com",
278
+ "blog.example.com",
279
+ "cdn.example.com",
280
+ "dev.example.com",
281
+ "example.com",
282
+ "mail.example.com",
283
+ "staging.example.com",
284
+ "static.example.com",
285
+ "support.example.com",
286
+ "test.example.com",
287
+ "wiki.example.com",
288
+ "www.example.com"
289
+ ]
290
+ }
291
+ ```
292
+
293
+ **With Brute-Force Example Request:**
294
+ ```json
295
+ {
296
+ "domain": "example.com",
297
+ "use_bruteforce": true,
298
+ "max_results": 50
299
+ }
300
+ ```
301
+
302
+ **With Brute-Force Example Output:**
303
+ ```json
304
+ {
305
+ "domain": "example.com",
306
+ "total_found": 18,
307
+ "sources": {
308
+ "crt.sh": 12,
309
+ "dns_bruteforce": 6
310
+ },
311
+ "subdomains": [
312
+ "admin.example.com",
313
+ "api.example.com",
314
+ "app.example.com",
315
+ "blog.example.com",
316
+ "cdn.example.com",
317
+ "dashboard.example.com",
318
+ "dev.example.com",
319
+ "docs.example.com",
320
+ "example.com",
321
+ "ftp.example.com",
322
+ "mail.example.com",
323
+ "staging.example.com",
324
+ "static.example.com",
325
+ "support.example.com",
326
+ "test.example.com",
327
+ "wiki.example.com",
328
+ "www.example.com"
329
+ ]
330
+ }
331
+ ```
332
+
333
+ **How It Works:**
334
+
335
+ The tool uses multiple passive enumeration sources:
336
+
337
+ 1. **Certificate Transparency (crt.sh)**: Queries public CT logs for SSL/TLS certificates issued to the domain and extracts all Subject Alternative Names (SANs). This is the primary source and requires no DNS queries.
338
+
339
+ 2. **DNS Brute-Force (Optional)**: If enabled, attempts to resolve common subdomain names (www, mail, api, admin, etc.) by querying Google and Cloudflare DNS. This actively probes for resolvable subdomains.
340
+
341
+ The results are merged, deduplicated, sorted alphabetically, and limited by the max_results parameter.
342
+
343
+ ### dns_propagation
344
+
345
+ Check DNS record propagation across multiple global resolvers to verify record consistency and propagation status.
346
+
347
+ **Input Parameters:**
348
+ ```typescript
349
+ {
350
+ domain: string // Required: Domain to check
351
+ record_type: "A" | "AAAA" | "MX" | "NS" | "TXT" | "CNAME" // Required: DNS record type (default: A)
352
+ }
353
+ ```
354
+
355
+ **Example Request:**
356
+ ```json
357
+ {
358
+ "domain": "example.com",
359
+ "record_type": "A"
360
+ }
361
+ ```
362
+
363
+ **Example Output:**
364
+ ```json
365
+ {
366
+ "domain": "example.com",
367
+ "record_type": "A",
368
+ "is_consistent": true,
369
+ "responding_resolvers": 8,
370
+ "total_resolvers": 8,
371
+ "propagation_percentage": 100,
372
+ "results": [
373
+ {
374
+ "resolver": "Google",
375
+ "ip": "8.8.8.8",
376
+ "location": "Global",
377
+ "records": [
378
+ "93.184.216.34"
379
+ ],
380
+ "latency_ms": 12
381
+ },
382
+ {
383
+ "resolver": "Google Secondary",
384
+ "ip": "8.8.4.4",
385
+ "location": "Global",
386
+ "records": [
387
+ "93.184.216.34"
388
+ ],
389
+ "latency_ms": 15
390
+ },
391
+ {
392
+ "resolver": "Cloudflare",
393
+ "ip": "1.1.1.1",
394
+ "location": "Global",
395
+ "records": [
396
+ "93.184.216.34"
397
+ ],
398
+ "latency_ms": 11
399
+ },
400
+ {
401
+ "resolver": "Cloudflare Secondary",
402
+ "ip": "1.0.0.1",
403
+ "location": "Global",
404
+ "records": [
405
+ "93.184.216.34"
406
+ ],
407
+ "latency_ms": 14
408
+ },
409
+ {
410
+ "resolver": "OpenDNS",
411
+ "ip": "208.67.222.222",
412
+ "location": "US",
413
+ "records": [
414
+ "93.184.216.34"
415
+ ],
416
+ "latency_ms": 28
417
+ },
418
+ {
419
+ "resolver": "Quad9",
420
+ "ip": "9.9.9.9",
421
+ "location": "Global",
422
+ "records": [
423
+ "93.184.216.34"
424
+ ],
425
+ "latency_ms": 13
426
+ },
427
+ {
428
+ "resolver": "Level3",
429
+ "ip": "4.2.2.1",
430
+ "location": "US",
431
+ "records": [
432
+ "93.184.216.34"
433
+ ],
434
+ "latency_ms": 32
435
+ },
436
+ {
437
+ "resolver": "Comodo",
438
+ "ip": "8.26.56.26",
439
+ "location": "US",
440
+ "records": [
441
+ "93.184.216.34"
442
+ ],
443
+ "latency_ms": 26
444
+ }
445
+ ]
446
+ }
447
+ ```
448
+
449
+ **Inconsistent Records Example:**
450
+ ```json
451
+ {
452
+ "domain": "example.com",
453
+ "record_type": "MX",
454
+ "is_consistent": false,
455
+ "responding_resolvers": 7,
456
+ "total_resolvers": 8,
457
+ "propagation_percentage": 87,
458
+ "results": [
459
+ {
460
+ "resolver": "Google",
461
+ "ip": "8.8.8.8",
462
+ "location": "Global",
463
+ "records": [
464
+ "10 mail1.example.com",
465
+ "20 mail2.example.com"
466
+ ],
467
+ "latency_ms": 14
468
+ },
469
+ {
470
+ "resolver": "Cloudflare",
471
+ "ip": "1.1.1.1",
472
+ "location": "Global",
473
+ "records": [
474
+ "10 mail-new.example.com"
475
+ ],
476
+ "latency_ms": 12
477
+ }
478
+ ]
479
+ }
480
+ ```
481
+
482
+ **Global Resolvers Included:**
483
+
484
+ The tool queries the following public DNS resolvers distributed globally:
485
+
486
+ - Google (8.8.8.8, 8.8.4.4) - Global
487
+ - Cloudflare (1.1.1.1, 1.0.0.1) - Global
488
+ - OpenDNS (208.67.222.222) - US
489
+ - Quad9 (9.9.9.9) - Global
490
+ - Level3 (4.2.2.1) - US
491
+ - Comodo (8.26.56.26) - US
492
+
493
+ **Use Cases:**
494
+
495
+ - Verify DNS record propagation after updates
496
+ - Check for DNS inconsistencies across resolvers
497
+ - Detect if a new DNS record has reached all major resolvers
498
+ - Monitor DNS cache status globally
499
+ - Troubleshoot DNS configuration issues
500
+
501
+ ### dns_zone_transfer
502
+
503
+ Attempt a DNS zone transfer (AXFR) against a nameserver. Zone transfers are typically restricted, but misconfigured servers may allow them.
504
+
505
+ **Input Schema:**
506
+ ```json
507
+ {
508
+ "domain": "string (required)",
509
+ "nameserver": "string (required, IP or nameserver domain)"
510
+ }
511
+ ```
512
+
513
+ **Example Request:**
514
+ ```json
515
+ {
516
+ "domain": "example.com",
517
+ "nameserver": "ns1.example.com"
518
+ }
519
+ ```
520
+
521
+ **Example Response (Successful Transfer):**
522
+ ```json
523
+ {
524
+ "domain": "example.com",
525
+ "nameserver": "ns1.example.com",
526
+ "success": true,
527
+ "record_count": 28,
528
+ "records": [
529
+ {
530
+ "name": "example.com",
531
+ "type": "SOA",
532
+ "ttl": 3600,
533
+ "value": "ns1.example.com. hostmaster.example.com. 2023101401 10800 3600 604800 86400"
534
+ },
535
+ {
536
+ "name": "www",
537
+ "type": "A",
538
+ "ttl": 3600,
539
+ "value": "93.184.216.34"
540
+ },
541
+ {
542
+ "name": "mail",
543
+ "type": "A",
544
+ "ttl": 3600,
545
+ "value": "93.184.216.35"
546
+ }
547
+ ],
548
+ "message": "Zone transfer successful: 28 records retrieved"
549
+ }
550
+ ```
551
+
552
+ **Example Response (Transfer Refused):**
553
+ ```json
554
+ {
555
+ "domain": "example.com",
556
+ "nameserver": "8.8.8.8",
557
+ "success": false,
558
+ "record_count": 0,
559
+ "records": [],
560
+ "message": "Zone transfer refused by nameserver (this is expected — most servers restrict AXFR)"
561
+ }
562
+ ```
563
+
564
+ **Important Notes:**
565
+
566
+ - Zone transfers are rarely permitted on modern nameservers as they expose the entire zone file
567
+ - Most responses will be "refused" — this is expected and indicates proper security
568
+ - Successful transfers are rare and indicate a misconfiguration worth investigating
569
+ - Only attempt against nameservers you are authorized to test
570
+
571
+ ## Prerequisites
572
+
573
+ This server requires:
574
+
575
+ 1. **dig** (DNS lookup utility)
576
+ - Included in `bind-tools` or `dnsutils` package
577
+ - macOS: Included by default
578
+ - Linux: `sudo apt-get install dnsutils` (Debian/Ubuntu) or `sudo yum install bind-utils` (RedHat/CentOS)
579
+
580
+ 2. **whois** (WHOIS client)
581
+ - macOS: Included by default
582
+ - Linux: `sudo apt-get install whois` (most distributions)
583
+
584
+ 3. **Node.js/Bun Runtime**
585
+ - Bun 1.0+ recommended for optimal performance
586
+ - Or Node.js 18+ with compatible runtime
587
+
588
+ No API keys are required. The crt.sh Certificate Transparency API is completely free and public.
589
+
590
+ ## Installation
591
+
592
+ ### 1. Install Bun
593
+
594
+ If you don't have Bun installed, install it from [bun.sh](https://bun.sh):
595
+
596
+ ```bash
597
+ curl -fsSL https://bun.sh/install | bash
598
+ ```
599
+
600
+ ### 2. Clone or navigate to the server directory
601
+
602
+ ```bash
603
+ cd /path/to/dns-recon
604
+ ```
605
+
606
+ ### 3. Install dependencies
607
+
608
+ ```bash
609
+ bun install
610
+ ```
611
+
612
+ ### 4. Build the server
613
+
614
+ ```bash
615
+ bun run build
616
+ ```
617
+
618
+ This creates a compiled binary in the `dist/` directory.
619
+
620
+ ### 5. Verify installation
621
+
622
+ ```bash
623
+ # Test that dig and whois are available
624
+ dig -v
625
+ whois -v
626
+
627
+ # Test the server startup (will hang until interrupted with Ctrl+C)
628
+ bun run start
629
+ ```
630
+
631
+ ## Usage
632
+
633
+ ### Via Claude Desktop
634
+
635
+ Add this to your `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`):
636
+
637
+ ```json
638
+ {
639
+ "mcpServers": {
640
+ "dns-recon": {
641
+ "command": "bun",
642
+ "args": ["run", "/absolute/path/to/dns-recon/src/index.ts"]
643
+ }
644
+ }
645
+ }
646
+ ```
647
+
648
+ Or with the built binary:
649
+
650
+ ```json
651
+ {
652
+ "mcpServers": {
653
+ "dns-recon": {
654
+ "command": "bun",
655
+ "args": ["/absolute/path/to/dns-recon/dist/index.js"]
656
+ }
657
+ }
658
+ }
659
+ ```
660
+
661
+ ### Via Claude Code (MCP Settings)
662
+
663
+ Create or update `~/.mcp/settings.json`:
664
+
665
+ ```json
666
+ {
667
+ "servers": {
668
+ "dns-recon": {
669
+ "command": "bun",
670
+ "args": ["run", "/absolute/path/to/dns-recon/src/index.ts"],
671
+ "env": {}
672
+ }
673
+ }
674
+ }
675
+ ```
676
+
677
+ ### Stdio Transport
678
+
679
+ The server uses stdio transport (stdin/stdout) for MCP communication. This is the standard transport for MCP servers and is used by Claude Desktop and compatible clients.
680
+
681
+ ### Testing Manually
682
+
683
+ Use the `test-client.js` pattern or invoke tools programmatically:
684
+
685
+ ```bash
686
+ # Start the server
687
+ bun run start &
688
+
689
+ # The server will wait for MCP protocol messages on stdin
690
+ # Each tool can be invoked via the standard MCP tool_call interface
691
+ ```
692
+
693
+ ## Examples
694
+
695
+ ### Query A Records
696
+
697
+ Find the IPv4 address of a domain:
698
+
699
+ ```
700
+ User: "Get the A records for example.com"
701
+ ```
702
+
703
+ Response:
704
+ ```json
705
+ {
706
+ "domain": "example.com",
707
+ "record_type": "A",
708
+ "records": [
709
+ {
710
+ "name": "example.com",
711
+ "type": "A",
712
+ "ttl": 3600,
713
+ "value": "93.184.216.34"
714
+ }
715
+ ],
716
+ "query_time_ms": 42,
717
+ "server": "default"
718
+ }
719
+ ```
720
+
721
+ ### Discover Subdomains
722
+
723
+ Find subdomains via certificate transparency:
724
+
725
+ ```
726
+ User: "Discover subdomains of example.com using certificate transparency"
727
+ ```
728
+
729
+ Response:
730
+ ```json
731
+ {
732
+ "domain": "example.com",
733
+ "certificate_count": 15,
734
+ "unique_subdomains": [
735
+ "api.example.com",
736
+ "example.com",
737
+ "staging.example.com",
738
+ "www.example.com"
739
+ ],
740
+ "certificates": [...]
741
+ }
742
+ ```
743
+
744
+ ### Enumerate Subdomains with Brute-Force
745
+
746
+ Find all subdomains using passive and active techniques:
747
+
748
+ ```
749
+ User: "Enumerate subdomains for example.com with DNS brute-force"
750
+ ```
751
+
752
+ Response:
753
+ ```json
754
+ {
755
+ "domain": "example.com",
756
+ "total_found": 18,
757
+ "sources": {
758
+ "crt.sh": 12,
759
+ "dns_bruteforce": 6
760
+ },
761
+ "subdomains": [
762
+ "admin.example.com",
763
+ "api.example.com",
764
+ "app.example.com",
765
+ "blog.example.com",
766
+ "cdn.example.com",
767
+ "dashboard.example.com",
768
+ "dev.example.com",
769
+ "docs.example.com",
770
+ "example.com",
771
+ "ftp.example.com",
772
+ "mail.example.com",
773
+ "staging.example.com",
774
+ "static.example.com",
775
+ "support.example.com",
776
+ "test.example.com",
777
+ "wiki.example.com",
778
+ "www.example.com"
779
+ ]
780
+ }
781
+ ```
782
+
783
+ ### Check DNS Propagation
784
+
785
+ Verify DNS record propagation globally:
786
+
787
+ ```
788
+ User: "Check if A records for example.com have propagated to all major DNS resolvers"
789
+ ```
790
+
791
+ Response:
792
+ ```json
793
+ {
794
+ "domain": "example.com",
795
+ "record_type": "A",
796
+ "is_consistent": true,
797
+ "responding_resolvers": 8,
798
+ "total_resolvers": 8,
799
+ "propagation_percentage": 100,
800
+ "results": [
801
+ {
802
+ "resolver": "Google",
803
+ "ip": "8.8.8.8",
804
+ "location": "Global",
805
+ "records": ["93.184.216.34"],
806
+ "latency_ms": 12
807
+ },
808
+ {
809
+ "resolver": "Cloudflare",
810
+ "ip": "1.1.1.1",
811
+ "location": "Global",
812
+ "records": ["93.184.216.34"],
813
+ "latency_ms": 11
814
+ }
815
+ ]
816
+ }
817
+ ```
818
+
819
+ ### Check Mail Configuration
820
+
821
+ Find MX records for a domain:
822
+
823
+ ```
824
+ User: "What are the mail servers for example.com?"
825
+ ```
826
+
827
+ Response:
828
+ ```json
829
+ {
830
+ "domain": "example.com",
831
+ "record_type": "MX",
832
+ "records": [
833
+ {
834
+ "name": "example.com",
835
+ "type": "MX",
836
+ "ttl": 3600,
837
+ "value": "10 mail.example.com"
838
+ },
839
+ {
840
+ "name": "example.com",
841
+ "type": "MX",
842
+ "ttl": 3600,
843
+ "value": "20 mail2.example.com"
844
+ }
845
+ ],
846
+ "query_time_ms": 35,
847
+ "server": "default"
848
+ }
849
+ ```
850
+
851
+ ### Retrieve Domain Registration Info
852
+
853
+ Get WHOIS information:
854
+
855
+ ```
856
+ User: "Who registered example.com and when?"
857
+ ```
858
+
859
+ Response:
860
+ ```json
861
+ {
862
+ "query": "example.com",
863
+ "registrar": "VeriSign Global Registry Services",
864
+ "creation_date": "1995-08-14T00:00:00Z",
865
+ "expiration_date": "2025-08-13T23:59:59Z",
866
+ "updated_date": "2022-08-14T00:00:00Z",
867
+ "name_servers": [
868
+ "a.iana-servers.net",
869
+ "b.iana-servers.net"
870
+ ],
871
+ "status": ["clientDeleteProhibited"],
872
+ "raw": "[raw WHOIS data]"
873
+ }
874
+ ```
875
+
876
+ ### Reverse DNS Lookup
877
+
878
+ Find hostname from IP:
879
+
880
+ ```
881
+ User: "What domain is hosted at 93.184.216.34?"
882
+ ```
883
+
884
+ Response:
885
+ ```json
886
+ {
887
+ "ip": "93.184.216.34",
888
+ "hostname": "example.com",
889
+ "query_time_ms": 28
890
+ }
891
+ ```
892
+
893
+ ## Security Considerations
894
+
895
+ ### Input Validation
896
+
897
+ All inputs are validated before execution:
898
+
899
+ - **Domain names** must match the pattern `[a-zA-Z0-9][a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}` and not exceed 253 characters
900
+ - **IPv4 addresses** must match standard dotted-decimal notation with octets 0-255
901
+ - **Nameservers** can be either valid IP addresses or domain names (same validation as above)
902
+ - **Record types** are restricted to a whitelist: A, AAAA, MX, NS, TXT, CNAME, SOA, PTR, SRV, CAA, ANY
903
+
904
+ ### Command Injection Prevention
905
+
906
+ - All inputs are passed as separate arguments to `execFile`, not through shell interpretation
907
+ - Special characters are not expanded or interpreted
908
+ - No shell metacharacters (`;`, `|`, `&`, `>`, `<`) can be injected
909
+
910
+ ### Network Limitations
911
+
912
+ - Commands have a 30-second timeout (except zone transfers which use 15 seconds)
913
+ - Output is buffered with a 5MB limit to prevent memory exhaustion
914
+ - Only standard, authorized network tools (`dig`, `whois`) are invoked
915
+
916
+ ### WHOIS and Privacy
917
+
918
+ - WHOIS lookups retrieve publicly available information
919
+ - Some registries implement GDPR privacy masking for personal details
920
+ - Use responsibly and comply with your local regulations
921
+
922
+ ### Rate Limiting
923
+
924
+ - This server does not implement rate limiting
925
+ - When integrating with Claude or automation, respect the rate limits of:
926
+ - Your configured DNS servers (typically very lenient)
927
+ - The whois registry (varies, typically 1-2 requests per second)
928
+ - crt.sh (very lenient, no documented rate limit)
929
+
930
+ ### Legal and Ethical Use
931
+
932
+ DNS reconnaissance and WHOIS lookups are completely legal, public operations. However:
933
+
934
+ - Only perform reconnaissance on systems you own or have explicit permission to test
935
+ - Zone transfer attempts should only be made against infrastructure you're authorized to test
936
+ - Use this server for authorized security testing, research, and legitimate business purposes
937
+ - Do not use for harassment, unauthorized access attempts, or illegal surveillance
938
+
939
+ ## Troubleshooting
940
+
941
+ ### "Command not found: dig"
942
+
943
+ Ensure bind-tools/dnsutils is installed:
944
+ - macOS: Should be pre-installed; try `/usr/bin/dig`
945
+ - Linux: Install with `sudo apt-get install dnsutils` or equivalent
946
+
947
+ ### "Command not found: whois"
948
+
949
+ Ensure whois is installed:
950
+ - macOS: Should be pre-installed; try `/usr/bin/whois`
951
+ - Linux: Install with `sudo apt-get install whois`
952
+
953
+ ### "Invalid domain name format"
954
+
955
+ Domain must:
956
+ - Start with alphanumeric character
957
+ - Contain only alphanumerics, dots, and hyphens
958
+ - End with at least 2-letter TLD
959
+ - Not exceed 253 characters
960
+
961
+ Valid: `example.com`, `sub.example.co.uk`, `test-domain.org`
962
+ Invalid: `-example.com`, `example`, `example..com`, `example.c`
963
+
964
+ ### "Invalid IPv4 address format"
965
+
966
+ IP must be four decimal numbers 0-255 separated by dots.
967
+
968
+ Valid: `93.184.216.34`, `8.8.8.8`, `1.1.1.1`
969
+ Invalid: `256.1.1.1`, `1.1.1`, `192.168.0.1.1`
970
+
971
+ ### "Command timed out"
972
+
973
+ The operation exceeded the timeout limit (30 seconds for most queries, 15 seconds for zone transfers). This typically indicates:
974
+ - A very slow DNS server
975
+ - Network connectivity issues
976
+ - A nameserver that doesn't respond quickly
977
+
978
+ Try:
979
+ - Specifying a different nameserver
980
+ - Checking your internet connection
981
+ - Using a public DNS server like 8.8.8.8
982
+
983
+ ### "crt.sh API error"
984
+
985
+ The Certificate Transparency API is temporarily unavailable. Try again in a few moments. This is rare as crt.sh has excellent uptime.
986
+
987
+ ## Development
988
+
989
+ ### Project Structure
990
+
991
+ ```
992
+ dns-recon/
993
+ ├── src/
994
+ │ ├── index.ts # Main server setup and tool registration
995
+ │ ├── types.ts # TypeScript interfaces for responses
996
+ │ ├── schemas.ts # Zod validation schemas
997
+ │ ├── security.ts # Input validation functions
998
+ │ ├── cli-executor.ts # Command execution wrapper
999
+ │ └── tools/
1000
+ │ ├── dns-lookup.ts # dig-based DNS queries
1001
+ │ ├── dns-reverse.ts # Reverse DNS lookups
1002
+ │ ├── whois-lookup.ts # WHOIS data retrieval
1003
+ │ ├── cert-transparency.ts # crt.sh integration
1004
+ │ ├── dns-zone-transfer.ts # AXFR zone transfers
1005
+ │ ├── subdomain-enum.ts # Passive subdomain enumeration
1006
+ │ └── dns-propagation.ts # DNS propagation checking
1007
+ ├── dist/ # Compiled output (generated by `bun build`)
1008
+ ├── package.json # Dependencies and scripts
1009
+ └── README.md # This file
1010
+ ```
1011
+
1012
+ ### Adding a New Tool
1013
+
1014
+ 1. Create a new file in `src/tools/` with a schema and function
1015
+ 2. Export the schema and function
1016
+ 3. Import in `src/index.ts`
1017
+ 4. Register with `server.tool()` in main
1018
+
1019
+ Example:
1020
+
1021
+ ```typescript
1022
+ // src/tools/my-tool.ts
1023
+ import { z } from "zod";
1024
+ import { domainSchema } from "../schemas.js";
1025
+
1026
+ export const myToolSchema = z.object({
1027
+ domain: domainSchema,
1028
+ });
1029
+
1030
+ export async function myTool(input: z.infer<typeof myToolSchema>) {
1031
+ // Implementation
1032
+ return { result: "..." };
1033
+ }
1034
+ ```
1035
+
1036
+ Then in `src/index.ts`:
1037
+
1038
+ ```typescript
1039
+ import { myToolSchema, myTool } from "./tools/my-tool.js";
1040
+
1041
+ server.tool("my_tool", "Description", myToolSchema.shape, toolHandler(myTool));
1042
+ ```
1043
+
1044
+ ### Testing
1045
+
1046
+ The server uses stdio transport, so testing requires:
1047
+ 1. Starting the server
1048
+ 2. Sending MCP protocol messages to stdin
1049
+ 3. Reading responses from stdout
1050
+
1051
+ Or use Claude Desktop/Claude Code with the config above.
1052
+
1053
+ ## Performance
1054
+
1055
+ - **DNS lookups**: Typically 20-100ms depending on server and query complexity
1056
+ - **Reverse DNS**: Typically 20-50ms
1057
+ - **WHOIS lookups**: Typically 200-500ms due to internet latency
1058
+ - **Certificate Transparency**: Typically 100-300ms (via HTTPS to crt.sh)
1059
+ - **Subdomain enumeration**: Typically 500-2000ms (depends on CT log size and brute-force)
1060
+ - **DNS propagation**: Typically 500-3000ms (queries 8 resolvers in parallel)
1061
+ - **Zone transfers**: Variable, 15-second timeout
1062
+
1063
+ Most operations complete within sub-second timeframes for typical domains.
1064
+
1065
+ ## License
1066
+
1067
+ MIT
1068
+
1069
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1070
+
1071
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1072
+
1073
+ See LICENSE file for full text.