code wiki / _hdl_build / nx_dns_probe.nx
nx_dns_probe.nx source
↩ module page · 64 lines · 3292 B
1// nx_dns_probe.nx -- SOVEREIGN A-record resolver probe (zero shell). Resolves a list of hostnames via
2// the SAME nx_dns_resolve_default the sovereign HTTPS client uses, and prints each name -> dotted IPv4
3// (or FAIL). Purpose: ground-truth the edge DNS (apex vs capability subdomains) so a funcheck
4// TLS-HANDSHAKE-FAIL can be told apart from a DNS-inconsistency (e.g. subdomains pointing at a
5// public IP that does not hairpin from the LAN vantage). Composes nx_https_url_connect's resolver.
6// usage: nx_dns_probe <host> [<host> ...] (defaults to the andelinwest edge set)
7// license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_dns_resolve_a_record.nx"
10const K_MAGIC_151060489: i64 = 151060489
11
12func dp_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
13func dp_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
14func dp_putn(v: i64) -> i64 {
15 if v==0 { sys_write(1,"0" as *u8,1); return 0 }
16 let t: *u8=sys_mmap(24); var m: i64=v; var k: i64=0
17 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
18 let o: *u8=sys_mmap(24); var w: i64=0; var q: i64=k-1
19 while q>=0 { o[w]=t[q]; w=w+1; q=q-1 }
20 sys_write(1,o,w); return 0
21}
22// print packed-BE ipv4 as a.b.c.d
23func dp_ip(packed: i64) -> i64 {
24 dp_putn((packed >> 24) & 0xff); dp_puts("." as *u8)
25 dp_putn((packed >> 16) & 0xff); dp_puts("." as *u8)
26 dp_putn((packed >> 8) & 0xff); dp_puts("." as *u8)
27 dp_putn(packed & 0xff)
28 return 0
29}
30// resolve `host` via a SPECIFIC resolver IP (packed BE) and print the answer inline.
31func dp_via(host: *u8, resolver: i64, label: *u8) -> i64 {
32 let now: i64 = sys_now_realtime_sec()
33 let r: *DnsResolveResult = nx_dns_resolve_a_record(host, dp_slen(host), resolver, now)
34 dp_puts(" " as *u8); dp_puts(label); dp_puts(" -> " as *u8)
35 if r.verdict != NX_DNS_R_OK { dp_puts("DNS-FAIL(" as *u8); dp_putn(r.verdict); dp_puts(")\n" as *u8); return 0 }
36 if r.ipv4_packed == 0 { dp_puts("NO-A-RECORD\n" as *u8); return 0 }
37 dp_ip(r.ipv4_packed); dp_puts("\n" as *u8)
38 return 0
39}
40// query the SAME host across multiple resolvers -- if a PUBLIC resolver (Google) disagrees with the
41// LAN answer, the discrepancy IS split-horizon (a local resolver rewriting the apex to the LAN IP);
42// if every public resolver agrees on a private 192.168.x, the PUBLIC record is genuinely broken.
43func dp_multi(host: *u8) -> i64 {
44 dp_puts(" " as *u8); dp_puts(host); dp_puts(":\n" as *u8)
45 dp_via(host, NX_DNS_R_CLOUDFLARE_IP, "cloudflare 1.1.1.1" as *u8)
46 dp_via(host, NX_DNS_R_GOOGLE_IP, "google 8.8.8.8" as *u8)
47 dp_via(host, K_MAGIC_151060489, "quad9 9.9.9.9" as *u8) // corrected 9.9.9.9
48 dp_via(host, NX_DNS_R_LAN_IP, "lan-router " as *u8)
49 return 0
50}
51
52func main(argc: i64, argv: *i64) -> i64 {
53 dp_puts("=== nx_dns_probe: A-record across resolvers (split-horizon vs true-public discriminator) ===\n" as *u8)
54 if argc > 1 {
55 var i: i64 = 1
56 while i < argc { dp_multi(argv[i] as *u8); i = i + 1 }
57 return 0
58 }
59 dp_multi("andelinwest.com" as *u8)
60 dp_multi("admin.andelinwest.com" as *u8)
61 dp_multi("mail.andelinwest.com" as *u8)
62 dp_multi("nishifamily.com" as *u8)
63 return 0
64}