code wiki / _hdl_build / nx_doh_probe.nx
nx_doh_probe.nx source
↩ module page · 77 lines · 3881 B
1// nx_doh_probe.nx -- SOVEREIGN DNS-over-HTTPS probe: the TRUE public A record even when the LAN
2// transparently intercepts port-53 UDP (split-horizon). Queries dns.google's RFC-8484-style JSON API
3// (https://dns.google/resolve?name=<host>&type=A) over the sovereign TLS-1.3 client + Mozilla trust
4// store -- HTTPS the interceptor cannot rewrite -- and prints the "data":"a.b.c.d" answers. This is the
5// discriminator: if DoH returns a PUBLIC ip but nx_dns_probe (plain UDP) returns a PRIVATE 192.168.x,
6// the LAN is doing split-horizon and the PUBLIC record is fine; if DoH ALSO returns the private ip,
7// the authoritative record is genuinely broken (external users can't reach it).
8// usage: nx_doh_probe [<host> ...] (defaults to the andelinwest/nishifamily edge set)
9// license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_trust_store_load_from_certdata.nx"
12import "nx_https_fetch_follow.nx"
13const K_MAGIC_65536: i64 = 65536
14const K_MAGIC_4194304: i64 = 4194304
15
16func dh_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
17func dh_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
18func dh_putn(v: i64) -> i64 { let b: *u8=sys_mmap(24); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(24); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
19
20// find every occurrence of `"data":"` in body and print the quoted value (an A-record answer or CNAME)
21func dh_print_data(body: *u8, n: i64) -> i64 {
22 let key: *u8 = "\"data\":\"" as *u8
23 let kl: i64 = 8
24 var found: i64 = 0
25 var i: i64 = 0
26 while i + kl <= n {
27 var m: i64 = 1
28 var j: i64 = 0
29 while j < kl { if (body[i+j] as i64) != (key[j] as i64) { m = 0; j = kl } else { j = j + 1 } }
30 if m == 1 {
31 var k: i64 = i + kl
32 dh_puts(" data=" as *u8)
33 while k < n { if (body[k] as i64) == 34 { k = n } else { sys_write(1, ((body as i64)+k) as *u8, 1); k = k + 1 } }
34 dh_puts("\n" as *u8)
35 found = found + 1
36 i = i + kl
37 } else { i = i + 1 }
38 }
39 if found == 0 { dh_puts(" (no data field -- check Status/Answer below)\n" as *u8) }
40 return found
41}
42
43func dh_one(store: *TrustStore, host: *u8) -> i64 {
44 let url: *u8 = sys_mmap(512)
45 var o: i64 = 0
46 let p1: *u8 = "https://dns.google/resolve?type=A&name=" as *u8
47 var i: i64 = 0
48 while p1[i] != (0 as u8) { url[o] = p1[i]; o = o + 1; i = i + 1 }
49 i = 0
50 while host[i] != (0 as u8) { url[o] = host[i]; o = o + 1; i = i + 1 }
51 url[o] = 0 as u8
52 dh_puts(" " as *u8); dh_puts(host); dh_puts(" (DoH dns.google):\n" as *u8)
53 let out: *u8 = sys_mmap(K_MAGIC_65536)
54 let stbox: *i64 = sys_mmap(16) as *i64
55 stbox[0] = 0
56 let n: i64 = nx_https_fetch_follow(url, store, out, K_MAGIC_65536, 4, stbox)
57 if n <= 0 { dh_puts(" FETCH-FAIL rc=" as *u8); dh_putn(n); dh_puts(" status=" as *u8); dh_putn(stbox[0]); dh_puts("\n" as *u8); return 0 }
58 dh_print_data(out, n)
59 return 0
60}
61
62func main(argc: i64, argv: *i64) -> i64 {
63 dh_puts("=== nx_doh_probe: TRUE public A record over DNS-over-HTTPS (bypasses LAN :53 interception) ===\n" as *u8)
64 let r: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt\x00" as *u8, 512, K_MAGIC_4194304)
65 if r <= 0 { dh_puts("certdata load failed\n" as *u8); return 1 }
66 let store: *TrustStore = r as *TrustStore
67 if argc > 1 {
68 var i: i64 = 1
69 while i < argc { dh_one(store, argv[i] as *u8); i = i + 1 }
70 return 0
71 }
72 dh_one(store, "andelinwest.com" as *u8)
73 dh_one(store, "admin.andelinwest.com" as *u8)
74 dh_one(store, "mail.andelinwest.com" as *u8)
75 dh_one(store, "nishifamily.com" as *u8)
76 return 0
77}