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}