code wiki / _hdl_build / nx_web_filter.nx

nx_web_filter.nx source

↩ module page · 96 lines · 7404 B

1// nx_web_filter.nx -- SOVEREIGN content-filter engine for the Nishi browser (uBlock-class, DATA-DRIVEN). The 2// honest defense for "these sites are full of viruses": block the malvertising / trackers / crypto-miners / 3// popunders that hostile (pirate/adult) sites load, and PASS THROUGH the actual video the user came to watch. 4// It is the DEFENSIVE TWIN of nx_media_signal/nx_extract_heal: same data-driven pattern-table shape, but the 5// verdict is BLOCK/ALLOW instead of media-kind. Network-level request filtering (not DOM cosmetic hiding) is 6// ALSO anti-adblock-resistant by construction -- it leaves no hidden-element DOM fingerprint for the site to 7// detect. Rules are DATA so the blocklist adapts without code edits (same as the self-heal table). ORIGINAL 8import "nx_syscalls.nx" 9import "nx_media_signal.nx" // xt_find substring 10 11const WF_STRIDE: i64 = 4 // per-rule: [kind, pat_ptr, patlen, category] 12const WF_MAX: i64 = 4096 13const WF_BLOCK: i64 = 1 14const WF_ALLOW: i64 = 2 // exception: the CONTENT the user wants -- always passes 15// categories (what got blocked / allowed) 16const WF_AD: i64 = 1 17const WF_TRACK: i64 = 2 18const WF_MAL: i64 = 3 19const WF_MINER: i64 = 4 20const WF_POPUP: i64 = 5 21const WF_CONTENT: i64 = 6 22 23func wf_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 24func wf_new() -> *i64 { let t: *i64 = sys_mmap(8 * (1 + WF_MAX * WF_STRIDE)) as *i64; t[0] = 0; return t } 25func wf_add(t: *i64, kind: i64, pat: *u8, patlen: i64, cat: i64) -> i64 { 26 if t[0] >= WF_MAX { return 1 } 27 let b: i64 = 1 + t[0] * WF_STRIDE 28 t[b] = kind; t[b+1] = pat as i64; t[b+2] = patlen; t[b+3] = cat 29 t[0] = t[0] + 1 30 return 0 31} 32func wf_addc(t: *i64, kind: i64, pat: *u8, cat: i64) -> i64 { return wf_add(t, kind, pat, wf_slen(pat), cat) } 33// add a whitespace-separated list of block patterns (DATA -- the intelligence; extend freely). Each token is a 34// substring rule pointing INTO the literal (rodata = persistent), so no per-token copy needed. 35func wf_add_list(t: *i64, cat: i64, s: *u8) -> i64 { 36 var i: i64 = 0 37 while (s[i] & 0xff) != 0 { 38 var skip: i64 = 1 39 while skip == 1 { let c: i64 = s[i]&0xff; if c==32 { i=i+1 } else { if c==10 { i=i+1 } else { skip=0 } } } 40 if (s[i] & 0xff) == 0 { return 0 } 41 let start: i64 = i 42 var tok: i64 = 1 43 while tok == 1 { let c: i64 = s[i]&0xff; if c==0 { tok=0 } else { if c==32 { tok=0 } else { if c==10 { tok=0 } else { i=i+1 } } } } 44 let len: i64 = i - start 45 if len > 0 { wf_add(t, WF_BLOCK, ((s as i64)+start) as *u8, len, cat) } 46 } 47 return 0 48} 49// seed: ALLOW the content the user wants (wins over any block) + a real, substantial ad/tracker/miner/adult-ad 50// blocklist as DATA. Substring rules on the request URL (host or path) -- the same model as EasyList domains. 51func wf_seed(t: *i64) -> i64 { 52 // ALLOW: media the user came to watch -- ALWAYS passes (never collateral-damaged) 53 wf_addc(t, WF_ALLOW, ".m3u8" as *u8, WF_CONTENT); wf_addc(t, WF_ALLOW, ".mpd" as *u8, WF_CONTENT) 54 wf_addc(t, WF_ALLOW, ".mp4" as *u8, WF_CONTENT); wf_addc(t, WF_ALLOW, ".webm" as *u8, WF_CONTENT) 55 wf_addc(t, WF_ALLOW, ".m4s" as *u8, WF_CONTENT); wf_addc(t, WF_ALLOW, "/videoplayback" as *u8, WF_CONTENT) 56 // AD / RTB exchanges + ad servers (the bulk of what a page loads) 57 wf_add_list(t, WF_AD, "doubleclick.net googlesyndication.com googleadservices.com googletagservices.com pagead2.googlesyndication securepubads.g.doubleclick 2mdn.net adnxs.com adsrvr.org amazon-adsystem.com criteo.com criteo.net rubiconproject.com pubmatic.com openx.net casalemedia.com adform.net bidswitch.net 3lift.com sharethrough.com teads.tv smartadserver.com contextweb.com gumgum.com yieldmo.com indexww.com sonobi.com spotxchange.com spotx.tv taboola.com outbrain.com revcontent.com mgid.com adroll.com moatads.com doubleverify.com adsafeprotected.com serving-sys.com flashtalking.com mathtag.com bluekai.com krxd.net demdex.net everesttech.net omtrdc.net agkn.com rlcdn.com crwdcntrl.net exelator.com tapad.com adsymptotic.com id5-sync.com adservice.google zedo.com yieldlab adtech advertising.com adroll.net media.net adthrive ezoic pixel.io /pagead/ /adsbygoogle /adserver /doubleclick" as *u8) 58 // TRACKERS / analytics / beacons 59 wf_add_list(t, WF_TRACK, "google-analytics.com googletagmanager.com analytics.google www.googletagmanager scorecardresearch.com quantserve.com quantcount.com hotjar.com mixpanel.com segment.com segment.io amplitude.com fullstory.com mouseflow.com crazyegg.com chartbeat.com parsely.com parse.ly nr-data.net newrelic.com optimizely.com mparticle.com branch.io adjust.com appsflyer.com kochava.com cxense.com permutive.com tiqcdn.com ensighten.com connect.facebook.net facebook.com/tr ads-twitter.com analytics.twitter.com static.ads-twitter.com sc-static.net ct.pinterest.com px.ads.linkedin.com snap.licdn.com analytics.tiktok.com cloudflareinsights.com clarity.ms yandex.ru/metrika /gtag/ /collect? /pixel /b/ss /beacon" as *u8) 60 // ADULT / pirate-site ad networks (the actual malvertising vectors on those sites) 61 wf_add_list(t, WF_AD, "exoclick.com exosrv.com popads.net popcash.net juicyads.com trafficjunky.com trafficjunky.net adnium.com propellerads.com propellerclick adsterra.com hilltopads.com clickadu.com ero-advertising.com plugrush.com trafficstars.com tsyndicate.com adxpansion.com adspyglass.com magsrv.com realsrv.com a-ads.com adnium juicyadscdn stripchat-ads twinrdsrv.com" as *u8) 62 // CRYPTO-MINERS 63 wf_add_list(t, WF_MINER, "coinhive.com coin-hive.com cryptoloot.com crypto-loot.com coinimp.com minero.cc jsecoin.com cryptonight webminepool webmine.cz coinhive-manager authedmine.com" as *u8) 64 // POPUNDERS / forced popups + scam landings 65 wf_add_list(t, WF_POPUP, "popunder /pop.js /pu.php /popunder pop-under" as *u8) 66 wf_add_list(t, WF_MAL, "you-have-won verify-you-are-human /sweepstake /prize-claim /cpa/ click-here-to-win" as *u8) 67 return 0 68} 69// VERDICT: 1 = block, 0 = allow; sets out_cat to the matched category. Order = ALLOW(content) wins, then BLOCK, 70// else default-ALLOW (first-party/unknown). Content-first means the video is NEVER collateral-damaged. 71func wf_should_block(t: *i64, url: *u8, ul: i64, out_cat: *i64) -> i64 { 72 var i: i64 = 0 73 while i < t[0] { // pass 1: content allow-exceptions win 74 let b: i64 = 1 + i * WF_STRIDE 75 if t[b] == WF_ALLOW { if xt_find(url, ul, (t[b+1]) as *u8, t[b+2], 0) >= 0 { out_cat[0] = t[b+3]; return 0 } } 76 i = i + 1 77 } 78 i = 0 79 while i < t[0] { // pass 2: block rules 80 let b: i64 = 1 + i * WF_STRIDE 81 if t[b] == WF_BLOCK { if xt_find(url, ul, (t[b+1]) as *u8, t[b+2], 0) >= 0 { out_cat[0] = t[b+3]; return 1 } } 82 i = i + 1 83 } 84 out_cat[0] = 0 // default: allow (first-party / unknown) 85 return 0 86} 87// human label for a category (for the block log / UI) 88func wf_cat_name(c: i64) -> *u8 { 89 if c == WF_AD { return "ad" as *u8 } 90 if c == WF_TRACK { return "tracker" as *u8 } 91 if c == WF_MAL { return "malware/scam" as *u8 } 92 if c == WF_MINER { return "crypto-miner" as *u8 } 93 if c == WF_POPUP { return "popunder" as *u8 } 94 if c == WF_CONTENT { return "content" as *u8 } 95 return "allow" as *u8 96}