code wiki / (root) / nx_ipfilter_fetch.nx

nx_ipfilter_fetch.nx source

↩ module page · 82 lines · 5014 B

1// nx_ipfilter_fetch.nx -- compile a live plaintext CIDR blocklist into ipfilter.bin over sovereign TLS. Default 2// source = firehol_level1.netset (canonical "known-bad": hijacked netblocks, DROP, etc. -- plaintext CIDR, so 3// no gz-inflate needed). ⚠HONEST: this is a general malicious-IP list, NOT a torrent-monitor-specific list; 4// a P2P-monitor list (I-BlockList level1) is gzipped -> needs our gz inflater first (a later rung). Output: 5// 8 bytes/entry [start u32 LE][end u32 LE]. argv[1]=out path (default ipfilter.bin), argv[2]=URL. 6// license_tier: ORIGINAL depends: syscalls, TLS stack, nx_ipfilter (ipf_ip/ipf_put_u32le) 7import "nx_syscalls.nx" 8import "nx_x509_trust_store.nx" 9import "nx_trust_store_load_from_certdata.nx" 10import "nx_https_fetch_follow.nx" 11import "nx_ipfilter.nx" 12const K_MAGIC_4194304: i64 = 4194304 13const K_MAGIC_12582912: i64 = 12582912 14const K_MAGIC_80000: i64 = 80000 15 16func if_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 17func if_n(v: i64) -> i64 { if v==0 { sys_write(1,"0" as *u8,1); return 0 } var m: i64=v; if m<0 { sys_write(1,"-" as *u8,1); m=0-m } let t: *u8=sys_mmap(28); var k: i64=0; while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } while k>0 { k=k-1; sys_write(1,(((t as i64)+k) as *u8),1) } return 0 } 18 19// parse one CIDR line [ls,le) -> out[0]=start, out[1]=end (u32). return 1 if valid. 20func if_parse_cidr(buf: *u8, ls: i64, le: i64, oct: *i64, out: *i64) -> i64 { 21 oct[0]=0; oct[1]=0; oct[2]=0; oct[3]=0 22 var oi: i64=0; var cur: i64=0; var prefix: i64=32; var past: i64=0; var anyd: i64=0 23 var i: i64=ls 24 while i<le { 25 let c: i64 = buf[i] as i64 26 if c>=48 { if c<=57 { cur=cur*10+(c-48); anyd=1 } } 27 if c==46 { if past==0 { if oi<4 { oct[oi]=cur } oi=oi+1; cur=0 } } // '.' 28 if c==47 { if oi<4 { oct[oi]=cur } oi=oi+1; cur=0; past=1 } // '/' 29 if c<48 { if c!=46 { if c!=47 { i=le } } } // any other (space/CR/#) -> stop 30 if c>57 { i=le } 31 if i<le { i=i+1 } 32 } 33 if past==1 { prefix=cur } else { if oi<4 { oct[oi]=cur; oi=oi+1 } } 34 if anyd==0 { return 0 } 35 if oi<4 { return 0 } 36 if prefix<0 { return 0 } 37 if prefix>32 { return 0 } 38 let ip: i64 = ipf_ip(oct[0], oct[1], oct[2], oct[3]) 39 let hostmask: i64 = (0xFFFFFFFF >> prefix) & 0xFFFFFFFF 40 let netmask: i64 = 0xFFFFFFFF & (0xFFFFFFFF - hostmask) 41 out[0] = ip & netmask 42 out[1] = (ip & netmask) | hostmask 43 return 1 44} 45 46func main(argc: i64, argv: *i64) -> i64 { 47 var outp: *u8 = "ipfilter.bin" as *u8 48 if argc>1 { outp = argv[1] as *u8 } 49 var url: *u8 = "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level1.netset" as *u8 50 if argc>2 { url = argv[2] as *u8 } 51 let r: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt" as *u8, 512, K_MAGIC_4194304) 52 if r <= 0 { if_p("ipfilter-fetch: CA load failed -> keeping existing ipfilter.bin (no-op)\n" as *u8); sys_exit(0); return 0 } 53 let store: *TrustStore = r as *TrustStore 54 let cap: i64 = K_MAGIC_12582912; let buf: *u8 = sys_mmap(cap) // 12MB (firehol level1 is a few MB) 55 let status: *i64 = sys_mmap(8) as *i64 56 let n: i64 = nx_https_fetch_follow(url, store, buf, cap, 6, status) 57 if_p("ipfilter-fetch: status=" as *u8); if_n(status[0]); if_p(" bytes=" as *u8); if_n(n); if_p("\n" as *u8) 58 if n <= 0 { if_p(" fetch failed -> keeping existing (no-op)\n" as *u8); sys_exit(0); return 0 } 59 // skip HTTP headers 60 var body: i64=0; var bi: i64=0; var fnd: i64=0 61 while fnd==0 { if bi+3>=n { fnd=1 } else { if buf[bi]==(13 as u8) { if buf[bi+1]==(10 as u8) { if buf[bi+2]==(13 as u8) { if buf[bi+3]==(10 as u8) { body=bi+4; fnd=1 } } } } if fnd==0 { bi=bi+1 } } } 62 // parse CIDR lines -> pack into out binary 63 let MAXP: i64 = K_MAGIC_80000 64 let ob: *u8 = sys_mmap(MAXP*8 + 64); var oo: i64=0 65 let oct: *i64 = sys_mmap(64) as *i64; let rng: *i64 = sys_mmap(16) as *i64 66 var ls: i64=body; var cnt: i64=0 67 while ls<n { 68 var le: i64=ls; var eol: i64=0 69 while eol==0 { if le>=n { eol=1 } else { if buf[le]==(10 as u8) { eol=1 } else { le=le+1 } } } 70 if le>ls { if buf[ls]!=(35 as u8) { // skip '#' comments 71 if if_parse_cidr(buf, ls, le, oct, rng)==1 { if cnt<MAXP { 72 oo=ipf_put_u32le(ob, oo, rng[0]); oo=ipf_put_u32le(ob, oo, rng[1]); cnt=cnt+1 73 } } 74 } } 75 ls=le+1 76 } 77 if cnt<=0 { if_p(" 0 ranges parsed -> keeping existing (no-op)\n" as *u8); sys_exit(0); return 0 } 78 let wf: i64 = sys_openat_wr(outp, 0x1a4); if wf<0 { if_p(" cannot write " as *u8); if_p(outp); if_p("\n" as *u8); sys_exit(1); return 1 } 79 sys_write(wf, ob, oo); sys_close(wf) 80 if_p("ipfilter-fetch: compiled " as *u8); if_n(cnt); if_p(" ranges -> " as *u8); if_p(outp); if_p(" (" as *u8); if_n(oo); if_p(" bytes)\n" as *u8) 81 sys_exit(0); return 0 82}