code wiki / _hdl_build / nx_conn_cap_gate.nx

nx_conn_cap_gate.nx source

↩ module page · 97 lines · 5884 B

1// nx_conn_cap_gate.nx -- gate for the access-wall DDoS/abuse CONNECTION layer (nx_conn_cap) + a read-only 2// verify of the kernel SYN-cookie edge defense (/proc/sys/net/ipv4/tcp_syncookies). Proves: per-IP cap (allow 3// up to cap, reject beyond), release frees a token, different IPs are independent, table saturation FAILS-CLOSED 4// (a new flooding IP is rejected), cc_count tracks, and full release frees the slot. Positive AND negative 5// controls. Appends "ACCESSGATE row=nx_conn_cap ddos-conn ... verdict=PASS" to knowledge/status/access_gate.log 6// on all-pass. NB the request brute-force layer is nx_rate_limit (self-test GREEN under the harness; the daemon 7// calls nx_rl_try_consume -> rate_ok -> aw_decide, proven DENY_RATE in nx_access_wall_gate). license_tier: ORIGINAL 8import "nx_conn_cap.nx" 9import "nx_syscalls.nx" 10 11func cg_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func cg_num(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; 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{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 } 13func cg_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var k: i64=0; while s[k]!=(0 as u8){dst[o]=s[k];o=o+1;k=k+1} return o } 14func cg_catnum(dst: *u8, off: i64, v: i64) -> i64 { var o: i64=off; let t: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; 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{dst[o]=t[k-1-i];o=o+1;i=i+1} return o } 15func cg_row(id: i64, ok: i64, what: *u8) -> i64 { cg_w("CCROW " as *u8); cg_num(id); cg_w(" " as *u8); if ok==1 { cg_w("PASS " as *u8) } else { cg_w("FAIL " as *u8) } cg_w(what); cg_w("\n" as *u8); return ok } 16func mkip(a: i64, b: i64, c: i64, d: i64) -> i64 { return (a << 24) | (b << 16) | (c << 8) | d } 17 18// read the kernel SYN-cookie sysctl: 0=off, 1=on, 2=always; -1 if unreadable. 19func cg_syn_state() -> i64 { 20 let fd: i64 = sys_openat_rd("/proc/sys/net/ipv4/tcp_syncookies" as *u8) 21 if fd < 0 { return 0 - 1 } 22 let buf: *u8 = sys_mmap(16) 23 let r: i64 = sys_read(fd, buf, 15) 24 sys_close(fd) 25 if r <= 0 { return 0 - 1 } 26 let c: i64 = buf[0] as i64 27 if c >= 48 { if c <= 57 { return c - 48 } } 28 return 0 - 1 29} 30 31func main() -> i64 { 32 let ips: *i64 = sys_mmap(8*16) as *i64 33 let cnts: *i64 = sys_mmap(8*16) as *i64 34 let nbox: *i64 = sys_mmap(16) as *i64 35 nbox[0] = 0 36 let slots: i64 = 4 37 let cap: i64 = 3 38 let ipA: i64 = mkip(203,0,113,1) 39 let ipB: i64 = mkip(203,0,113,2) 40 41 var pass: i64 = 0 42 var rows: i64 = 0 43 var ok: i64 = 0 44 45 // R0: per-IP cap -- allow up to cap, reject beyond 46 ok = 0 47 if cc_acquire(ips,cnts,nbox,slots,ipA,cap)==1 { if cc_acquire(ips,cnts,nbox,slots,ipA,cap)==1 { if cc_acquire(ips,cnts,nbox,slots,ipA,cap)==1 { if cc_acquire(ips,cnts,nbox,slots,ipA,cap)==0 { ok=1 } } } } 48 rows=rows+1; pass=pass+cg_row(0, ok, "per-IP cap: 3 allowed, 4th rejected (cap=3)" as *u8) 49 50 // R1: cc_count tracks the concurrent count 51 ok = 0; if cc_count(ips,cnts,nbox,ipA)==3 { ok=1 } 52 rows=rows+1; pass=pass+cg_row(1, ok, "cc_count tracks concurrent (=3)" as *u8) 53 54 // R2: release frees a token -> acquire succeeds again 55 ok = 0; cc_release(ips,cnts,nbox,ipA); if cc_count(ips,cnts,nbox,ipA)==2 { if cc_acquire(ips,cnts,nbox,slots,ipA,cap)==1 { ok=1 } } 56 rows=rows+1; pass=pass+cg_row(2, ok, "release frees a token; re-acquire ok" as *u8) 57 58 // R3: different IPs independent (ipA at cap does not block ipB) 59 ok = 0; if cc_acquire(ips,cnts,nbox,slots,ipB,cap)==1 { ok=1 } 60 rows=rows+1; pass=pass+cg_row(3, ok, "different IPs independent (ipB allowed)" as *u8) 61 62 // R4 (NEG): table saturation fails-closed -- a separate tiny table (slots=2), fill 2 IPs, reject a 3rd 63 let i2: *i64 = sys_mmap(8*8) as *i64 64 let c2: *i64 = sys_mmap(8*8) as *i64 65 let n2: *i64 = sys_mmap(16) as *i64 66 n2[0] = 0 67 ok = 0 68 if cc_acquire(i2,c2,n2,2,mkip(10,0,0,1),cap)==1 { if cc_acquire(i2,c2,n2,2,mkip(10,0,0,2),cap)==1 { if cc_acquire(i2,c2,n2,2,mkip(10,0,0,3),cap)==0 { ok=1 } } } 69 rows=rows+1; pass=pass+cg_row(4, ok, "table saturated -> new flooding IP rejected (fail-closed, neg)" as *u8) 70 71 // R5: full release frees the slot (nbox shrinks). ipB has 1 -> release -> slot freed 72 ok = 0 73 let before: i64 = nbox[0] 74 cc_release(ips,cnts,nbox,ipB) 75 if cc_count(ips,cnts,nbox,ipB)==0 { if nbox[0]==before-1 { ok=1 } } 76 rows=rows+1; pass=pass+cg_row(5, ok, "full release frees the slot (table compacts)" as *u8) 77 78 // R6: kernel SYN-cookie edge defense is READABLE (verify); report the value (1/2 = on) 79 let syn: i64 = cg_syn_state() 80 ok = 0; if syn >= 0 { ok = 1 } 81 cg_w(" syn-cookies tcp_syncookies="); cg_num(syn); cg_w(" (1=on,2=always; enable on the NAS = ops step)\n" as *u8) 82 rows=rows+1; pass=pass+cg_row(6, ok, "kernel SYN-cookie state readable (L0 edge verify)" as *u8) 83 84 cg_w("NX-CONN-CAP-GATE rows=" as *u8); cg_num(rows); cg_w(" pass=" as *u8); cg_num(pass); cg_w("\n" as *u8) 85 if pass == rows { 86 let line: *u8 = sys_mmap(256) 87 var off: i64 = cg_cat(line, 0, "ACCESSGATE row=nx_conn_cap ddos-conn rows=" as *u8) 88 off = cg_catnum(line, off, rows); off = cg_cat(line, off, " pass=" as *u8); off = cg_catnum(line, off, pass) 89 off = cg_cat(line, off, " verdict=PASS\n" as *u8) 90 let gf: i64 = sys_openat_append("knowledge/status/access_gate.log" as *u8, 0x1a4) 91 if gf >= 0 { sys_write(gf, line, off); sys_close(gf) } 92 cg_w("NX-CONN-CAP-GATE verdict=PASS -- DDoS connection layer recorded in access_gate.log\n" as *u8) 93 sys_exit(0); return 0 94 } 95 cg_w("NX-CONN-CAP-GATE verdict=FAIL -- NOT recorded (no fake-green)\n" as *u8) 96 sys_exit(1); return 1 97}