code wiki / _hdl_build / nx_golive_dns_gate.nx

nx_golive_dns_gate.nx source

↩ module page · 292 lines · 14442 B

1// nx_golive_dns_gate.nx -- GO-LIVE GATE: every hosted domain must be testable INTERNALLY and 2// EXTERNALLY, by construction, so the "apex works but admin.<domain> is insecure on WiFi" class 3// (2026-07-04/05 andelinwest arc) can never ship again. Data-driven from 4// knowledge/hosting/golive_dns.conf (domain|public_ip|lan_ip|lan_wildcard). Per domain: 5// [A] EXTERNAL AUTHORITY -- Porkbun API (sovereign TLS, uninterceptable): apex A == public_ip 6// AND '*.domain' A == public_ip => any subdomain reaches the edge from the internet. 7// [B] INTERNAL LAN -- query the LAN router (dnsmasq) directly: apex -> lan_ip; and when 8// lan_wildcard=1 a CANARY subdomain (nx-golive-canary.<domain>) -> lan_ip. The canary is the 9// whole point: per-host override lists pass apex/www and silently miss new subdomains; only a 10// whole-domain wildcard answers a name nobody registered. 11// [C] EDGE SERVE -- TLS 1.3 to lan_ip:443 with SNI apex (+ canary when lan_wildcard=1): served 12// cert must VALIDATE for that SNI (chain + SAN + validity vs Mozilla store) and GET / must 13// return HTTP 2xx/3xx => sni_router -> cert-select -> proxy -> daemon serve the whole domain. 14// Every RED prints its exact remediation command. Exit 0 = all GREEN, 1 = any RED. 15// Honest limit: true external-vantage serving (hairpin-free) still needs one off-LAN check 16// (cellular funcheck row); [A]+[C] are the strongest in-LAN-provable superset. 17// usage: nx_golive_dns_gate (run nx_secret_cli get porkbun first -> /tmp/nxsecret.out) 18// license_tier: ORIGINAL 19import "nx_acme_porkbun.nx" 20import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 21import "nx_dns_resolve_a_record.nx" 22import "nx_csprng.nx" 23import "nx_tls13_client_session.nx" 24import "nx_tls13_client_session_run.nx" 25import "nx_https_get_complete.nx" 26 27const GD_CONF: *u8 = "knowledge/hosting/golive_dns.conf\x00" as *u8 28// NOTE nx_cc trap (pinned 2026-07-05): INDEXING a global const pointer (CONST_X[i]) -> empty .s. 29// The canary label therefore lives as a local string literal inside gd_domain, not a global const. // unregistered label: only a wildcard answers it 30 31func gd_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 32func gd_write(s: *u8, n: i64) -> i64 { sys_write(1, s, n); return 0 } 33func gd_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 34func gd_putn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); 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 } 35// dotted ipv4 -> packed BE; also prints via gd_ip 36func gd_ipparse(s: *u8, n: i64) -> i64 { 37 var packed: i64=0; var cur: i64=0; var i: i64=0 38 while i < n { 39 let c: i64 = s[i] as i64 40 if c == 46 { packed = (packed << 8) | cur; cur = 0 } 41 else { if c >= 48 { if c <= 57 { cur = cur*10 + (c-48) } } } 42 i = i + 1 43 } 44 return (packed << 8) | cur 45} 46func gd_ip(p: i64) -> i64 { 47 gd_putn((p>>24)&0xff); gd_puts("." as *u8); gd_putn((p>>16)&0xff); gd_puts("." as *u8) 48 gd_putn((p>>8)&0xff); gd_puts("." as *u8); gd_putn(p&0xff); return 0 49} 50func gd_contains(hay: *u8, n: i64, needle: *u8) -> i64 { 51 let nl: i64 = gd_slen(needle); if nl == 0 { return 0 } 52 var i: i64 = 0 53 while i + nl <= n { var j: i64=0; var ok: i64=1; while j<nl { if hay[i+j]!=needle[j] {ok=0; j=nl} else {j=j+1} } if ok==1 { return 1 } i=i+1 } 54 return 0 55} 56 57// ---- Porkbun record check: does the zone hold an A record `name` -> `ip`? ---- 58// JSON shape (observed): {"id":"..","name":"<fqdn>","type":"A","content":"<ip>","ttl":..} 59// Scan for "name":"<fqdn>" then require "type":"A" and "content":"<ip>" within the same object window. 60func gd_pk_has_a(resp: *u8, rn: i64, fqdn: *u8, fqn: i64, ip: *u8, ipn: i64) -> i64 { 61 let pat: *u8 = sys_mmap(512) 62 var po: i64 = 0 63 let p1: *u8 = "\"name\":\"" as *u8 64 var i: i64 = 0 65 while p1[i] != (0 as u8) { pat[po] = p1[i]; po = po + 1; i = i + 1 } 66 i = 0 67 while i < fqn { pat[po] = fqdn[i]; po = po + 1; i = i + 1 } 68 pat[po] = 34 as u8; po = po + 1 // closing quote 69 pat[po] = 0 as u8 70 // find pat in resp 71 var s: i64 = 0 72 while s + po <= rn { 73 var j: i64 = 0; var ok: i64 = 1 74 while j < po { if resp[s+j] != pat[j] { ok = 0; j = po } else { j = j + 1 } } 75 if ok == 1 { 76 // object window: from match to the next '}' (Porkbun objects are flat) 77 var e: i64 = s 78 while e < rn { if (resp[e] as i64) == 125 { break } e = e + 1 } 79 let win: *u8 = resp + s 80 let wn: i64 = e - s 81 if gd_contains(win, wn, "\"type\":\"A\"" as *u8) == 1 { 82 // build "content":"<ip>" 83 let cp: *u8 = sys_mmap(128) 84 var co: i64 = 0 85 let c1: *u8 = "\"content\":\"" as *u8 86 var k: i64 = 0 87 while c1[k] != (0 as u8) { cp[co] = c1[k]; co = co + 1; k = k + 1 } 88 k = 0 89 while k < ipn { cp[co] = ip[k]; co = co + 1; k = k + 1 } 90 cp[co] = 34 as u8; co = co + 1 91 cp[co] = 0 as u8 92 if gd_contains(win, wn, cp) == 1 { return 1 } 93 } 94 } 95 s = s + 1 96 } 97 return 0 98} 99 100func gd_creds(ak: *i64, akn: *i64, sk: *i64, skn: *i64) -> i64 { 101 let raw: *u8 = sys_mmap(512) 102 let rawn: i64 = pk_readline_file("/tmp/nxsecret.out\x00" as *u8, raw, 512) 103 if rawn <= 0 { return 0 } 104 var base: i64 = 0 105 if rawn >= 3 { if (raw[0] as i64)==0xef { if (raw[1] as i64)==0xbb { if (raw[2] as i64)==0xbf { base=3 } } } } 106 var nl: i64 = base 107 while nl < rawn { if (raw[nl] as i64)==0x0a { break } nl=nl+1 } 108 ak[0] = (raw + base) as i64; akn[0] = nl - base 109 var s2: i64 = nl + 1 110 var nl2: i64 = s2 111 while nl2 < rawn { if (raw[nl2] as i64)==0x0a { break } nl2=nl2+1 } 112 sk[0] = (raw + s2) as i64; skn[0] = nl2 - s2 113 if skn[0] <= 0 { return 0 } 114 return 1 115} 116 117// ---- LAN resolve host (nul-terminated) via the router; expect packed ip. 1=match 0=no ---- 118func gd_lan_is(host: *u8, want: i64) -> i64 { 119 let r: *DnsResolveResult = nx_dns_resolve_a_record(host, gd_slen(host), NX_DNS_R_LAN_IP, sys_now_realtime_sec()) 120 if r.verdict != NX_DNS_R_OK { return 0 } 121 if r.ipv4_packed == want { return 1 } 122 return 0 123} 124 125// ---- TLS serve check: connect ip:443, SNI=host, validate cert, GET / -> 2xx/3xx. 1=green ---- 126func gd_serve(ip: i64, host: *u8, store: *TrustStore) -> i64 { 127 let hn: i64 = gd_slen(host) 128 let fd: i64 = sys_socket(2, 1, 0) 129 if fd < 0 { return 0 } 130 sys_set_socket_timeout(fd, 20) 131 let sa: *u8 = sys_mmap(16) 132 sa[0]=2 as u8; sa[1]=0 as u8; sa[2]=1 as u8; sa[3]=187 as u8 // port 443 133 sa[4]=((ip>>24)&0xff) as u8; sa[5]=((ip>>16)&0xff) as u8; sa[6]=((ip>>8)&0xff) as u8; sa[7]=(ip&0xff) as u8 134 var z: i64=8; while z<16 { sa[z]=0 as u8; z=z+1 } 135 if nx_connect_bounded(fd, sa, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(fd); return 0 } 136 let cr: *u8 = sys_mmap(32); nx_csprng_fill(cr, 32) 137 let xp: *u8 = sys_mmap(32); nx_csprng_fill(xp, 32) 138 let vc_raw: *u8 = sys_mmap(128) 139 let vc: *TlsValidationContext = vc_raw as *TlsValidationContext 140 vc.store = store; vc.sni_host = host; vc.sni_host_len = hn; vc.now_epoch = sys_now_realtime_sec() 141 vc.cached_cert = 0 as *u8; vc.cached_cert_len = 0 142 vc.cert_out = 0 as *u8; vc.cert_out_cap = 0; vc.cert_out_len = 0 143 let sr: i64 = nx_tls13_client_session_run(fd, host, hn, cr, xp, vc) 144 if sr < 0 { sys_close(fd); return 0 } 145 let s: *Tls13ClientSession = sr as *Tls13ClientSession 146 let out: *u8 = sys_mmap(65536) 147 let n: i64 = nx_https_get_complete(s, fd, "/" as *u8, 1, host, hn, out, 65536) 148 sys_close(fd) 149 if n < 12 { return 0 } 150 // "HTTP/1.1 NNN" -> code at bytes 9..11 151 let code: i64 = ((out[9] as i64)-48)*100 + ((out[10] as i64)-48)*10 + ((out[11] as i64)-48) 152 if code >= 200 { if code < 400 { return 1 } } 153 return 0 154} 155 156func gd_check_line(tag: *u8, ok: i64, fixhint: *u8) -> i64 { 157 if ok == 1 { gd_puts(" GREEN " as *u8); gd_puts(tag); gd_puts("\n" as *u8); return 0 } 158 gd_puts(" RED " as *u8); gd_puts(tag); gd_puts("\n" as *u8) 159 gd_puts(" fix: " as *u8); gd_puts(fixhint); gd_puts("\n" as *u8) 160 return 1 161} 162 163// run every check for ONE conf line (domain|public_ip|lan_ip|wildcard); returns RED count. 164func gd_domain(line: *u8, ln: i64, store: *TrustStore, have_pk: i64, ak: *u8, akn: i64, sk: *u8, skn: i64) -> i64 { 165 var b1: i64 = 0 - 1 166 var b2: i64 = 0 - 1 167 var b3: i64 = 0 - 1 168 var q: i64 = 0 169 while q < ln { 170 if (line[q] as i64) == 124 { 171 if b1 < 0 { b1 = q } 172 else { if b2 < 0 { b2 = q } else { if b3 < 0 { b3 = q } } } 173 } 174 q = q + 1 175 } 176 if b3 <= 0 { return 0 } 177 let dom: *u8 = sys_mmap(b1 + 4) 178 var ci: i64 = 0 179 while ci < b1 { dom[ci] = line[ci]; ci = ci + 1 } 180 dom[b1] = 0 as u8 181 let dn: i64 = b1 182 let o1: i64 = b1 + 1 183 let pub_s: *u8 = line + o1 184 let pubn: i64 = b2 - b1 - 1 185 let o2: i64 = b2 + 1 186 let lan_s: *u8 = line + o2 187 let lann: i64 = b3 - b2 - 1 188 let wild: i64 = (line[b3+1] as i64) - 48 189 let lan_packed: i64 = gd_ipparse(lan_s, lann) 190 gd_puts(" [" as *u8) 191 gd_puts(dom) 192 gd_puts("] public=" as *u8) 193 gd_write(pub_s, pubn) 194 gd_puts(" lan=" as *u8) 195 gd_write(lan_s, lann) 196 gd_puts(" lan_wildcard=" as *u8) 197 gd_putn(wild) 198 gd_puts("\n" as *u8) 199 200 var reds: i64 = 0 201 // ---- [A] external authority: apex + wildcard A -> public ---- 202 var a_apex: i64 = 0 203 var a_wild: i64 = 0 204 if have_pk == 1 { 205 let resp: *u8 = sys_mmap(131072) 206 let rn: *i64 = sys_mmap(8) as *i64 207 let prc: i64 = nx_porkbun_retrieve(ak, akn, sk, skn, dom, dn, store, sys_now_realtime_sec(), resp, 131072, rn) 208 if prc == NX_PORKBUN_OK { 209 a_apex = gd_pk_has_a(resp, rn[0], dom, dn, pub_s, pubn) 210 let wname: *u8 = sys_mmap(300) 211 wname[0] = 42 as u8 212 wname[1] = 46 as u8 213 var wi: i64 = 0 214 while wi < dn { wname[2+wi] = dom[wi]; wi = wi + 1 } 215 wname[2+dn] = 0 as u8 216 a_wild = gd_pk_has_a(resp, rn[0], wname, dn + 2, pub_s, pubn) 217 } 218 } 219 reds = reds + gd_check_line("[A1] porkbun apex A -> public edge" as *u8, a_apex, "nx_porkbun_publish_a <domain> apex <public_ip>" as *u8) 220 reds = reds + gd_check_line("[A2] porkbun star-wildcard A -> public edge (external: ANY subdomain reachable)" as *u8, a_wild, "nx_porkbun_publish_a <domain> star <public_ip>" as *u8) 221 222 // ---- [B] internal LAN split-horizon ---- 223 let b_apex: i64 = gd_lan_is(dom, lan_packed) 224 reds = reds + gd_check_line("[B1] LAN router resolves apex -> lan edge" as *u8, b_apex, "whole-domain dnsmasq address entry on the router via nx_aw_routerfix (see golive_dns.conf header)" as *u8) 225 if wild == 1 { 226 let can: *u8 = sys_mmap(300) 227 let canlab: *u8 = "nx-golive-canary" as *u8 228 var co: i64 = 0 229 var gi: i64 = 0 230 while canlab[gi] != (0 as u8) { can[co] = canlab[gi]; co = co + 1; gi = gi + 1 } 231 can[co] = 46 as u8 232 co = co + 1 233 gi = 0 234 while gi < dn { can[co] = dom[gi]; co = co + 1; gi = gi + 1 } 235 can[co] = 0 as u8 236 let b_can: i64 = gd_lan_is(can, lan_packed) 237 reds = reds + gd_check_line("[B2] LAN wildcard: canary subdomain -> lan edge (nothing forgettable by construction)" as *u8, b_can, "same whole-domain address entry as B1 (per-host domain lists CANNOT pass this)" as *u8) 238 // ---- [C2] edge serve for canary (wildcard cert + whole-domain routing class-proof) ---- 239 let c_can: i64 = gd_serve(lan_packed, can, store) 240 reds = reds + gd_check_line("[C2] edge serves canary SNI: valid cert + HTTP (whole-domain cert-select + route)" as *u8, c_can, "check nx_sni_route whole-domain match + wildcard cert (nx_edge_probe lan_ip 443 canary.domain /)" as *u8) 241 } 242 // ---- [C1] edge serve apex ---- 243 let c_apex: i64 = gd_serve(lan_packed, dom, store) 244 reds = reds + gd_check_line("[C1] edge serves apex SNI: valid cert + HTTP 2xx/3xx" as *u8, c_apex, "nx_edge_probe lan_ip 443 domain / (sni_router, cert, proxy chain)" as *u8) 245 return reds 246} 247 248func main() -> i64 { 249 gd_puts("=== nx_golive_dns_gate: internal+external testability contract for every hosted domain ===\n" as *u8) 250 let lr: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt\x00" as *u8, 300, 4194304) 251 if lr <= 0 { gd_puts("VERDICT RED (trust store load failed)\n" as *u8); return 1 } 252 let store: *TrustStore = lr as *TrustStore 253 let akb: *i64 = sys_mmap(8) as *i64 254 let aknb: *i64 = sys_mmap(8) as *i64 255 let skb: *i64 = sys_mmap(8) as *i64 256 let sknb: *i64 = sys_mmap(8) as *i64 257 var have_pk: i64 = gd_creds(akb, aknb, skb, sknb) 258 if have_pk != 1 { gd_puts(" (porkbun creds missing: run nx_secret_cli get porkbun first; A-checks will be RED)\n" as *u8) } 259 let ak: *u8 = akb[0] as *u8 260 let sk: *u8 = skb[0] as *u8 261 262 let cbox: *i64 = sys_mmap(16) as *i64 263 let conf: *u8 = sys_read_file(GD_CONF, cbox) 264 if (conf as i64) == 0 { gd_puts("VERDICT RED (knowledge/hosting/golive_dns.conf missing)\n" as *u8); return 1 } 265 let cn: i64 = cbox[0] 266 267 var reds: i64 = 0 268 var domains: i64 = 0 269 var p: i64 = 0 270 while p < cn { 271 var e: i64 = p 272 while e < cn { if (conf[e] as i64) == 10 { break } e = e + 1 } 273 var ln: i64 = e - p 274 if ln > 0 { if (conf[p+ln-1] as i64) == 13 { ln = ln - 1 } } 275 var skip: i64 = 0 276 if ln <= 0 { skip = 1 } 277 if skip == 0 { if (conf[p] as i64) == 35 { skip = 1 } } 278 if skip == 0 { 279 domains = domains + 1 280 reds = reds + gd_domain(conf + p, ln, store, have_pk, ak, aknb[0], sk, sknb[0]) 281 } 282 p = e + 1 283 } 284 gd_puts("domains checked: " as *u8) 285 gd_putn(domains) 286 gd_puts("\n" as *u8) 287 if reds == 0 { gd_puts("VERDICT GREEN -- every hosted domain is internally + externally testable by construction\n" as *u8); return 0 } 288 gd_puts("VERDICT RED -- failing checks: " as *u8) 289 gd_putn(reds) 290 gd_puts(" (each RED above carries its exact remediation)\n" as *u8) 291 return 1 292}