#!/usr/bin/env ucode let fs = require("fs"); let common = require("core.common"); let uci_core = require("core.uci"); let rag = require("diagnostics.rag"); let fuzzer_runner = require("diagnostics.fuzzer_runner"); let as_string = common.as_string; let read_json_file = common.read_json_file; let write_json_file = common.write_json_file; let command_from_args = common.command_from_args; let command_output = common.command_output; let command_status = common.command_status; let command_success = common.command_success; let command_success_from_args = common.command_success_from_args; let shell_quote = common.shell_quote; let object_or_empty = common.object_or_empty; let array_or_empty = common.array_or_empty; const CONFIG_NAME = getenv("TACHYON_CONFIG_NAME") || "tachyon"; const LIB_DIR = getenv("TACHYON_LIB") || "/usr/lib/tachyon"; const STATE_DIR = getenv("TACHYON_FUZZER_STATE_DIR") || "/var/run/tachyon"; const STATE_FILE = STATE_DIR + "/fuzzer-state.json"; const PID_FILE = STATE_DIR + "/fuzzer-worker.pid"; const JOBS_DIR = STATE_DIR + "/fuzzer"; const HISTORY_FILE = "/etc/tachyon/fuzzer_history.json"; const BYEDPI_PORT = 11089; const NFQUEUE_QNUM_ZAPRET = 298; const NFQUEUE_QNUM_ZAPRET2 = 299; const FUZZER_FWMARK = "0x40000000"; const FUZZER_OUTBOUND_MARK = getenv("NFT_OUTBOUND_MARK") || "0x08000000"; function get_job_dir(job_id) { if (!job_id || job_id == "") return null; return JOBS_DIR + "/" + job_id; } function ensure_job_dir(job_id) { if (!job_id || job_id == "") return null; let d = JOBS_DIR + "/" + job_id; system(sprintf("mkdir -p %s 2>/dev/null", shell_quote(d))); return d; } // ── History Persistence ────────────────────────────────────────────────────── function load_history() { let data = read_json_file(HISTORY_FILE); if (data && type(data) == "object" && data.entries && type(data.entries) == "array") { return data; } return { entries: [] }; } function save_history(history) { common.ensure_dir("/etc/tachyon"); while (length(history.entries) > 50) { shift(history.entries); } write_json_file(HISTORY_FILE, history); } function append_history(entry) { let history = load_history(); push(history.entries, { timestamp: entry.timestamp || clock()[0], engine: entry.engine || "unknown", target: entry.target || "unknown", mode: entry.mode || "presets", best_strategy: entry.best_strategy || null, total_tested: entry.total_tested || 0, working_count: entry.working_count || 0, dpi_detection: entry.dpi_detection || null, duration_sec: entry.duration_sec || 0 }); save_history(history); } function get_history(limit) { let history = load_history(); let entries = history.entries || []; let n = int(limit) || 0; if (n > 0 && length(entries) > n) { let start = length(entries) - n; let sliced = []; for (let i = start; i < length(entries); i++) { push(sliced, entries[i]); } entries = sliced; } return entries; } function resolve_binary(paths) { for (let p in paths) { if (p && fs.stat(p) != null) return p; } return null; } function get_zapret2_bin() { return resolve_binary([ getenv("ZAPRET2_NFQWS2_BIN"), "/opt/zapret2/nfq2/nfqws2", "/opt/zapret2/nfq/nfqws2", "/opt/zapret2/nfqws2", "/usr/bin/nfqws2" ]); } function get_zapret_bin() { return resolve_binary([ getenv("ZAPRET_NFQWS_BIN"), "/opt/zapret/nfq/nfqws", "/opt/zapret/nfqws", "/usr/bin/nfqws" ]); } function get_byedpi_bin() { return resolve_binary([ getenv("BYEDPI_BIN"), "/opt/byedpi/ciadpi", "/usr/bin/ciadpi" ]); } function get_zapret2_lua_flags(args_str) { if (index(args_str, "--lua-init") >= 0) return ""; let candidate_dirs = [ getenv("ZAPRET2_PROVIDER_LUA_DIR"), LIB_DIR + "/providers/zapret2/lua", "/usr/lib/tachyon/providers/zapret2/lua", "/opt/zapret2/lua", "/opt/zapret2/files/lua", "/opt/zapret2/share/zapret/lua", "/opt/zapret2/init.d/sysv/lua", "/opt/zapret/lua", "/opt/zapret/files/lua", "/usr/share/zapret2/lua", "/usr/share/zapret/lua", "/etc/zapret2/lua", "/etc/zapret/lua", "/usr/lib/zapret2/lua", "/usr/lib/zapret/lua" ]; let lua_scripts = [ "zapret-lib.lua", "zapret-antidpi.lua", "zapret-auto.lua" ]; let flags = ""; for (let script in lua_scripts) { let found = null; for (let d in candidate_dirs) { if (!d || fs.stat(d) == null) continue; let p = d + "/" + script; if (fs.stat(p) != null) { found = p; break; } if (fs.stat(p + ".gz") != null) { found = p + ".gz"; break; } } if (found != null) flags += sprintf("--lua-init=@%s ", found); } return flags; } let _has_timeout = null; function get_timeout_prefix(sec) { sec = sec || 8; if (_has_timeout === null) { _has_timeout = (system("command -v timeout >/dev/null 2>&1") == 0); } return _has_timeout ? sprintf("timeout %d ", sec) : ""; } function wrap_cmd_timeout(cmd, sec, pid_file) { sec = sec || 8; if (_has_timeout === null) { _has_timeout = (system("command -v timeout >/dev/null 2>&1") == 0); } if (pid_file && pid_file != "") { if (_has_timeout) { return sprintf("( echo $$ > %s; timeout -s KILL %d %s )", shell_quote(pid_file), sec, cmd); } return sprintf("( echo $$ > %s; %s )", shell_quote(pid_file), cmd); } if (_has_timeout) { return sprintf("timeout -s KILL %d %s", sec, cmd); } return cmd; } let _fuzzer_curl_dns_flags = null; function get_fuzzer_curl_dns_flags() { if (_fuzzer_curl_dns_flags !== null) return _fuzzer_curl_dns_flags; let t_pre = get_timeout_prefix(2); if (system(sprintf("%scurl -so /dev/null --doh-url https://1.1.1.1/dns-query --connect-timeout 2 -m 2 https://1.1.1.1/ 2>/dev/null", t_pre)) == 0) { _fuzzer_curl_dns_flags = "--doh-url https://1.1.1.1/dns-query "; return _fuzzer_curl_dns_flags; } if (system(sprintf("%scurl -so /dev/null --doh-url https://8.8.8.8/dns-query --connect-timeout 2 -m 2 https://8.8.8.8/ 2>/dev/null", t_pre)) == 0) { _fuzzer_curl_dns_flags = "--doh-url https://8.8.8.8/dns-query "; return _fuzzer_curl_dns_flags; } if (system("curl --dns-servers 8.8.8.8 -V >/dev/null 2>&1") == 0) { _fuzzer_curl_dns_flags = "--dns-servers 8.8.8.8,1.1.1.1 "; return _fuzzer_curl_dns_flags; } _fuzzer_curl_dns_flags = ""; return _fuzzer_curl_dns_flags; } let _fuzzer_host_cache = {}; function get_resolved_host_flags(url) { let m = match(url, /^https?:\/\/([^\/:]+)/); if (!m || !m[1]) return ""; let host = m[1]; if (match(host, /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) || index(host, ":") >= 0) return ""; if (!fuzzer_runner.is_valid_hostname(host)) return ""; if (exists(_fuzzer_host_cache, host)) return _fuzzer_host_cache[host]; let safe_host = shell_quote(host); let ip = null; // 1. Try Cloudflare DoH JSON let p = fs.popen(sprintf("curl -s -m 3 --connect-timeout 2 -H 'accept: application/dns-json' 'https://1.1.1.1/dns-query?name=%s&type=A'", safe_host), "r"); let out = p ? p.read("all") : ""; if (p) p.close(); if (out && out != "") { try { let data = json(out); if (data && data.Answer) { for (let ans in data.Answer) { if (ans.type == 1 && ans.data && match(ans.data, /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/)) { ip = ans.data; break; } } } } catch (e) {} } // 2. Try Google DoH JSON if Cloudflare failed if (!ip) { let gp = fs.popen(sprintf("curl -s -m 3 --connect-timeout 2 -H 'accept: application/dns-json' 'https://8.8.8.8/dns-query?name=%s&type=A'", safe_host), "r"); let gout = gp ? gp.read("all") : ""; if (gp) gp.close(); if (gout && gout != "") { try { let gdata = json(gout); if (gdata && gdata.Answer) { for (let ans in gdata.Answer) { if (ans.type == 1 && ans.data && match(ans.data, /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/)) { ip = ans.data; break; } } } } catch (e) {} } } // 3. Fallback: nslookup via 1.1.1.1 or system if (!ip) { let np = fs.popen(sprintf("nslookup %s 1.1.1.1 2>/dev/null", safe_host), "r"); let nout = np ? np.read("all") : ""; if (np) np.close(); if (nout && nout != "") { let lines = split(nout, "\n"); let name_seen = false; for (let line in lines) { if (index(line, "Name:") >= 0) { name_seen = true; continue; } if (name_seen) { let nm = match(line, /Address:[ \t]+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/); if (nm && nm[1]) { ip = nm[1]; break; } } } } } if (ip) { let flags = sprintf("--resolve %s:443:%s --resolve %s:80:%s ", host, ip, host, ip); _fuzzer_host_cache[host] = flags; return flags; } _fuzzer_host_cache[host] = ""; return ""; } const KNOWN_BLOB_FILES = { tls_max: { file: "tls_clienthello_max_ru.bin", size: 654, desc: "Max.ru authentic ClientHello" }, tls_google: { file: "tls_clienthello_www_google_com.bin", size: 681, desc: "Google authentic ClientHello" }, tls_gosuslugi: { file: "tls_clienthello_gosuslugi_ru.bin", size: 517, desc: "Gosuslugi Russian Government ClientHello" }, tls_sber: { file: "tls_clienthello_sberbank_ru.bin", size: 517, desc: "Sberbank authentic ClientHello" }, tls_iana: { file: "tls_clienthello_iana_org.bin", size: 517, desc: "IANA root authority ClientHello" }, tls_vk: { file: "tls_clienthello_vk_com.bin", size: 517, desc: "VK authentic ClientHello" }, tls_onetrust: { file: "tls_clienthello_www_onetrust_com.bin", size: 664, desc: "OneTrust CDN ClientHello" }, quic_google: { file: "quic_initial_www_google_com.bin", size: 1200, desc: "Google QUIC Initial" }, quic_yt1: { file: "quic_initial_rr1---sn-xguxaxjvh-n8me_googlevideo_com_kyber_1.bin", size: 1230, desc: "GoogleVideo Kyber QUIC Initial" }, quic_vk: { file: "quic_initial_vk_com.bin", size: 1357, desc: "VK QUIC Initial" }, stun_fake: { file: "stun.bin", size: 100, desc: "STUN discovery packet" }, discord_udp: { file: "stun.bin", size: 100, desc: "Discord Voice UDP fake packet" } }; function get_zapret2_blob_dir() { let candidate_dirs = [ getenv("ZAPRET2_PROVIDER_FILES_DIR") ? (getenv("ZAPRET2_PROVIDER_FILES_DIR") + "/fake") : null, "/opt/zapret2/files/fake", "/opt/zapret/files/fake", "/usr/share/zapret2/files/fake", "/usr/share/zapret/files/fake", "/etc/zapret2/files/fake", "/etc/zapret/files/fake", LIB_DIR + "/providers/zapret2/files/fake", "/usr/lib/tachyon/providers/zapret2/files/fake" ]; for (let d in candidate_dirs) { if (d && fs.stat(d) != null) return d; } return "/opt/zapret2/files/fake"; } function resolve_zapret2_blobs(args_str) { if (!args_str || args_str == "") return ""; let candidate_dirs = [ getenv("ZAPRET2_PROVIDER_FILES_DIR") ? (getenv("ZAPRET2_PROVIDER_FILES_DIR") + "/fake") : null, "/opt/zapret2/files/fake", "/opt/zapret/files/fake", "/usr/share/zapret2/files/fake", "/usr/share/zapret/files/fake", "/etc/zapret2/files/fake", "/etc/zapret/files/fake", LIB_DIR + "/providers/zapret2/files/fake", "/usr/lib/tachyon/providers/zapret2/files/fake" ]; let blob_flags = ""; for (let name, info in KNOWN_BLOB_FILES) { if ((index(args_str, "blob=" + name) >= 0 || index(args_str, "seqovl_pattern=" + name) >= 0) && index(args_str, "--blob=" + name + ":") < 0) { let actual_path = null; for (let d in candidate_dirs) { if (!d || fs.stat(d) == null) continue; let p = d + "/" + info.file; if (fs.stat(p) != null) { actual_path = p; break; } } if (actual_path != null) { blob_flags += sprintf("--blob=%s:@%s ", name, actual_path); } } } return blob_flags; } function setup_fuzzer_direct_nftables(qnum, is_udp) { system("nft add table inet tachyon_fuzzer 2>/dev/null"); system("nft 'add chain inet tachyon_fuzzer output { type filter hook output priority -200 ; policy accept; }' 2>/dev/null"); system(sprintf("nft add rule inet tachyon_fuzzer output meta mark %s counter return 2>/dev/null", FUZZER_FWMARK)); system("nft 'add rule inet tachyon_fuzzer output ip daddr { 1.1.1.1, 1.0.0.1, 8.8.8.8, 8.8.4.4, 77.88.8.8 } counter return' 2>/dev/null"); system("nft 'add rule inet tachyon_fuzzer output ip6 daddr { 2606:4700:4700::1111, 2606:4700:4700::1001, 2001:4860:4860::8888, 2001:4860:4860::8844 } counter return' 2>/dev/null"); if (is_udp) { system(sprintf("nft 'add rule inet tachyon_fuzzer output meta l4proto { tcp, udp } th dport { 80, 443, 2053, 2083, 2087, 2096, 8443, 19294-19344, 50000-65535 } counter queue num %d bypass' 2>/dev/null", qnum)); } else { system(sprintf("nft 'add rule inet tachyon_fuzzer output meta l4proto tcp tcp dport { 80, 443, 2053, 2083, 2087, 2096, 8443 } counter queue num %d bypass' 2>/dev/null", qnum)); } // Route hook with priority -155 (before TachyonTable's -150) marks test traffic with FUZZER_OUTBOUND_MARK (direct outbound mark) // This guarantees that TachyonTable's mangle_output immediately returns and test traffic goes DIRECT to WAN without Sing-box TProxy system("nft 'add chain inet tachyon_fuzzer bypass_singbox { type route hook output priority -155 ; policy accept; }' 2>/dev/null"); system(sprintf("nft add rule inet tachyon_fuzzer bypass_singbox meta mark %s counter return 2>/dev/null", FUZZER_FWMARK)); system(sprintf("nft 'add rule inet tachyon_fuzzer bypass_singbox meta l4proto tcp tcp dport { 80, 443, 2053, 2083, 2087, 2096, 8443 } meta mark set meta mark | %s counter' 2>/dev/null", FUZZER_OUTBOUND_MARK)); if (is_udp) { system(sprintf("nft 'add rule inet tachyon_fuzzer bypass_singbox meta l4proto udp udp dport { 80, 443, 19294-19344, 50000-65535 } meta mark set meta mark | %s counter' 2>/dev/null", FUZZER_OUTBOUND_MARK)); } } function validate_strategy_args(engine, args_val) { return fuzzer_runner.validate_strategy_args(engine, args_val); } const PATTERNS_FILE = "/etc/tachyon/fuzzer_patterns.json"; const DEFAULT_PATTERNS = { zapret2: { splits: [ "1", "2", "3", "midsld", "sniext+2", "sniext+4", "1,midsld", "1,sniext+2" ], foolings: [ "badseq", "md5sig", "badack", "datanoack", "fakeddrop" ], ttls: [ 2, 3, 4, 5, 6, 8 ], seqovls: [ "1", "2" ], wsizes: [ "1" ], blobs: [ "tls_max", "tls_google", "tls_gosuslugi", "tls_sber", "tls_iana" ], syndata: true, repeats: [ 6, 8 ], payloads: [ "tls_client_hello", "http_req", "quic_initial" ] }, zapret: { splits: [ "1", "2", "midsld", "sniext+4", "1,midsld" ], foolings: [ "badseq", "md5sig", "badack", "datanoack" ], ttls: [ 2, 3, 4, 6, 8 ], split_modes: [ "split2", "disorder2", "fake,split2", "fake,disorder2" ] }, byedpi: { splits: [ "1", "2", "1+sniext", "midsld" ], disorders: [ "1", "2" ], ttls: [ 2, 3, 4, 6, 8 ], oobs: [ "1", "2" ], autos: [ "t,r,a,s", "r,s", "t,a" ], tlsrecs: [ "1+sniext" ], ipfrags: [ "24" ] }, custom_strategies: [] }; function get_patterns_config() { let custom = read_json_file(PATTERNS_FILE); if (custom && type(custom) == "object") { return { zapret2: custom.zapret2 || DEFAULT_PATTERNS.zapret2, zapret: custom.zapret || DEFAULT_PATTERNS.zapret, byedpi: custom.byedpi || DEFAULT_PATTERNS.byedpi, custom_strategies: custom.custom_strategies || [] }; } return DEFAULT_PATTERNS; } function save_patterns_config(cfg_obj) { if (!cfg_obj || type(cfg_obj) != "object") { print(sprintf("%J\n", { success: false, error: "Invalid patterns configuration object" })); return; } common.ensure_dir("/etc/tachyon"); write_json_file(PATTERNS_FILE, cfg_obj); print(sprintf("%J\n", { success: true, message: "Patterns configuration saved successfully" })); } function reset_patterns_config() { try { fs.unlink(PATTERNS_FILE); } catch(e) {} print(sprintf("%J\n", { success: true, message: "Patterns configuration reset to factory defaults", patterns: DEFAULT_PATTERNS })); } // Target Suites & Definitions const TARGET_SUITES = { youtube_suite: { name: "YouTube Full Suite (Web + Static CDN + Stream)", urls: [ { name: "Web Interface", url: "https://www.youtube.com", weight: 25, required: true, probe_kind: "tls_http" }, { name: "Static Assets (i.ytimg)", url: "https://i.ytimg.com/generate_204", weight: 25, required: false, probe_kind: "tls_http" }, { name: "GoogleVideo Stream CDN", url: "https://redirector.googlevideo.com/generate_204", weight: 50, required: true, probe_kind: "streaming" } ] }, discord_suite: { name: "Discord Full Suite (API + WSS Gateway + CDN)", urls: [ { name: "API Gateway", url: "https://discord.com/api/v9/gateway", weight: 40, required: true, probe_kind: "tls_http" }, { name: "Global Assets CDN", url: "https://cdn.discordapp.com/generate_204", weight: 30, required: false, probe_kind: "tls_http" }, { name: "Discord Web Portal", url: "https://discord.com/login", weight: 30, required: true, probe_kind: "tls_http" } ] }, twitch_suite: { name: "Twitch Live Suite (Web + HLS Video + CDN)", urls: [ { name: "Web Portal", url: "https://www.twitch.tv", weight: 40, required: true, probe_kind: "tls_http" }, { name: "Static Assets CDN", url: "https://static-cdn.jtvnw.net/", weight: 30, required: false, probe_kind: "tls_http" }, { name: "HLS Usher API", url: "https://usher.ttvnw.net/", weight: 30, required: true, probe_kind: "tls_http" } ] }, twitter_suite: { name: "X / Twitter Suite (Web + API + CDN)", urls: [ { name: "X Web Portal", url: "https://x.com", weight: 40, required: true, probe_kind: "tls_http" }, { name: "API Endpoint", url: "https://api.x.com/", weight: 30, required: true, probe_kind: "tls_http" }, { name: "Twimg Media CDN", url: "https://pbs.twimg.com/", weight: 30, required: false, probe_kind: "tls_http" } ] }, chatgpt_suite: { name: "ChatGPT / OpenAI Suite (Web + Static CDN)", urls: [ { name: "ChatGPT Portal", url: "https://chatgpt.com", weight: 60, required: true, probe_kind: "tls_http" }, { name: "Static Assets CDN", url: "https://cdn.oaistatic.com/", weight: 40, required: false, probe_kind: "tls_http" } ] }, instagram_suite: { name: "Instagram / Meta Suite (Web + Static CDN)", urls: [ { name: "Web Interface", url: "https://www.instagram.com", weight: 60, required: true, probe_kind: "tls_http" }, { name: "CDN Static Assets", url: "https://static.cdninstagram.com/", weight: 40, required: false, probe_kind: "tls_http" } ] }, telegram_suite: { name: "Telegram Suite (Web + API)", urls: [ { name: "Web App", url: "https://web.telegram.org", weight: 50, required: true, probe_kind: "tls_http" }, { name: "Bot API", url: "https://api.telegram.org", weight: 50, required: true, probe_kind: "tls_http" } ] }, rutracker_suite: { name: "RuTracker Suite (HTTP / HTTPS)", urls: [ { name: "Main Portal", url: "https://rutracker.org", weight: 60, required: true, probe_kind: "tls_http" }, { name: "CDN Static Logo", url: "https://static.rutracker.cc/logo/logo-3.png", weight: 40, required: false, probe_kind: "tls_http" } ] } }; const TARGET_URLS = { youtube_suite: "https://www.youtube.com", youtube: "https://www.youtube.com", youtube_web: "https://www.youtube.com", discord_suite: "https://discord.com/api/v9/gateway", discord: "https://discord.com/api/v9/gateway", twitch_suite: "https://www.twitch.tv", twitch: "https://www.twitch.tv", twitter_suite: "https://x.com", twitter: "https://x.com", chatgpt_suite: "https://chatgpt.com", chatgpt: "https://chatgpt.com", instagram_suite: "https://www.instagram.com", instagram: "https://www.instagram.com", rutracker_suite: "https://rutracker.org", rutracker: "https://rutracker.org", telegram_suite: "https://web.telegram.org", telegram: "https://web.telegram.org", quic_http3: "https://www.google.com" }; // Strategy Matrices (Expanded Elite Production Suite) const STRATEGIES_ZAPRET2 = [ // ── 1. REAL-WORLD PRODUCTION CHAMPIONS (From Active Router Config) ───────── { id: "z2_paws_max_multisplit", name: "PAWS Spoofing (Max.ru, tcp_ts) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:blob=tls_max:repeats=8:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1:seqovl=664:seqovl_pattern=tls_max", description: "PAWS TCP timestamp evasion with authentic Max.ru ClientHello pattern overlap. Top-tier TSPU bypass." }, { id: "z2_paws_google_multisplit", name: "PAWS Spoofing (Google, tcp_ts) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:blob=tls_google:repeats=8:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1:seqovl=681:seqovl_pattern=tls_google", description: "PAWS spoofing using authentic Google ClientHello blob and exact 681-byte sequence overlap." }, { id: "z2_paws_gosuslugi_multisplit", name: "PAWS Spoofing (Gosuslugi Whitelist) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:blob=tls_gosuslugi:repeats=6:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1,midsld:seqovl=517:seqovl_pattern=tls_gosuslugi", description: "Mimics official Russian Government Gosuslugi portal ClientHello with PAWS RFC 7323 drop." }, { id: "z2_paws_sber_multisplit", name: "PAWS Spoofing (Sberbank Whitelist) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:blob=tls_sber:repeats=6:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1,midsld:seqovl=517:seqovl_pattern=tls_sber", description: "Mimics Sberbank TLS ClientHello with ancient TCP timestamp." }, { id: "z2_paws_iana_multisplit", name: "PAWS Spoofing (IANA Root) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:blob=tls_iana:repeats=6:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1,midsld:seqovl=517:seqovl_pattern=tls_iana", description: "Authentic IANA ClientHello with PAWS timestamp spoofing." }, // ── 2. TCP SYN DATA SUITE ────────────────────────────────────────────────── { id: "z2_syndata_multidisorder", name: "TCP SYN Data + Multidisorder (pos=1,midsld)", engine: "zapret2", args: "--lua-desync=syndata --lua-desync=multidisorder:pos=1,midsld", description: "Injects payload into TCP SYN packet and disorders following segments. Bypasses stateful DPI." }, { id: "z2_syndata_multisplit", name: "TCP SYN Data + Multisplit (pos=1,midsld)", engine: "zapret2", args: "--lua-desync=syndata --lua-desync=multisplit:pos=1,midsld:seqovl=1:fooling=badseq", description: "Combines SYN data injection with segmented SNI payload and badseq fooling." }, { id: "z2_syndata_wsize", name: "TCP SYN Data + Window Clamp (wsize=1)", engine: "zapret2", args: "--lua-desync=syndata --lua-desync=multisplit:pos=1,midsld:wsize=1", description: "SYN data payload followed by 1-byte TCP window segments." }, // ── 3. DUAL-STAGE & COMPOSITE DESYNC SUITE ──────────────────────────────── { id: "z2_dual_fake_max", name: "Dual Fake (STUN + Max.ru, tcp_ts) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:blob=stun_fake:repeats=6:tcp_ts=-600000:tcp_ts_up --lua-desync=fake:blob=tls_max:repeats=6:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1:seqovl=664:seqovl_pattern=tls_max", description: "Consecutive fake STUN and TLS packets with PAWS timestamps before overlapped multisplit." }, { id: "z2_fake_repeats8_multisplit", name: "Burst Fake (repeats=8, tcp_ts) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:blob=tls_google:repeats=8:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1,midsld:seqovl=2:fooling=badseq", description: "High-intensity 8-packet fake burst with PAWS timestamp before segmented payload." }, // ── 4. YOUTUBE 4K & GOOGLEVIDEO STREAM CDN SUITE ─────────────────────────── { id: "z2_yt_multisplit_midsld", name: "YouTube 4K Multisplit + MidSLD", engine: "zapret2", args: "--lua-desync=multisplit:pos=1,midsld:seqovl=1:fooling=badseq", description: "Optimized for GoogleVideo 4K chunk streams and TSPU TLS desync." }, { id: "z2_yt_multisplit_sniext", name: "SNI Extension Split + Badseq", engine: "zapret2", args: "--lua-desync=multisplit:pos=1,sniext+4:seqovl=1:fooling=badseq", description: "Splits deep into SNI extensions to fool next-gen DPI signatures." }, { id: "z2_aggressive_combo", name: "Aggressive Triple-Split + SeqOvl 2", engine: "zapret2", args: "--lua-desync=multisplit:pos=1,midsld,sniext+2:seqovl=2:fooling=badseq", description: "High-entropy triple fragmentation for heavily filtered regions." }, { id: "z2_wsize_seqovl_combo", name: "Window Clamp (wsize=1) + SeqOvl", engine: "zapret2", args: "--lua-desync=multisplit:pos=1,midsld:wsize=1:seqovl=1:fooling=badseq", description: "Combines 1-byte window clamp with sequence overlap." }, { id: "z2_wsize_multisplit", name: "Window Size Clamp (wsize=1)", engine: "zapret2", args: "--lua-desync=multisplit:pos=1,midsld:wsize=1:fooling=badseq", description: "Forces single-byte TCP window segments to evade reassembly." }, // ── 5. DISCORD FULL-STACK & VOICE/RTC SUITE ──────────────────────────────── { id: "z2_discord_fullstack", name: "Discord Full-Stack Multi-Profile", engine: "zapret2", args: "--filter-tcp=443 --lua-desync=fake:blob=tls_max:repeats=8:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1:seqovl=664:seqovl_pattern=tls_max --new --filter-tcp=2053,2083,2087,2096,8443 --filter-l7=tls --payload=tls_client_hello --lua-desync=fake:blob=tls_google:repeats=6:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1:seqovl=681:seqovl_pattern=tls_google --new --filter-udp=19294-19344,50000-50100 --filter-l7=discord,stun --payload=discord_ip_discovery,stun --lua-desync=fake:blob=discord_udp:repeats=6", description: "Production multi-profile: HTTPS, alternate Cloudflare edge ports, and Discord Voice/STUN UDP." }, { id: "z2_discord_udp", name: "Discord Voice UDP Desync", engine: "zapret2", args: "--filter-udp=19294-19344,50000-65535 --filter-l7=discord,stun --payload=discord_ip_discovery,stun --lua-desync=fake:blob=discord_udp:repeats=6", description: "UDP fake packet desync for Discord RTC and Voice channels." }, { id: "z2_quic_http3_udp", name: "QUIC / HTTP3 UDP Fake Desync (Google Kyber)", engine: "zapret2", args: "--filter-udp=443 --filter-l7=quic --payload=quic_initial --lua-desync=fake:blob=quic_google:repeats=11", description: "UDP fake desync using 1200-byte Google QUIC Initial blob with 11 repeats." }, // ── 6. ADVANCED REORDER & FAKED SEGMENTS ──────────────────────────────────── { id: "z2_fakedsplit_badseq", name: "Faked Split (pos=1,midsld) + BadSeq", engine: "zapret2", args: "--lua-desync=fakedsplit:pos=1,midsld:fooling=badseq", description: "Splits real stream and inserts fake packets between fragments." }, { id: "z2_fakeddisorder", name: "Faked Disorder (pos=1,midsld)", engine: "zapret2", args: "--lua-desync=fakeddisorder:pos=1,midsld:fooling=badseq", description: "Inserts out-of-order fake fragments with invalid sequence fooling." }, { id: "z2_hostfakesplit", name: "Hostfake Split (pos=1,midsld)", engine: "zapret2", args: "--lua-desync=hostfakesplit:pos=1,midsld:fooling=badseq", description: "Replaces host header/SNI in first split packet with dummy host." }, { id: "z2_tcpseg_multisplit", name: "TCPSeg (size=40) + Multisplit (pos=midsld)", engine: "zapret2", args: "--lua-desync=tcpseg:size=40 --lua-desync=multisplit:pos=midsld:fooling=badseq", description: "Forces low TCP MSS segment size before mid-SLD desync." }, { id: "z2_multidisorder_midsld", name: "Classic Multidisorder (pos=1,midsld)", engine: "zapret2", args: "--lua-desync=multidisorder:pos=1,midsld:fooling=badseq", description: "Sends out-of-order segments at start and mid-SLD with badseq fooling." }, { id: "z2_split_pos1", name: "Classic Multisplit (pos=1)", engine: "zapret2", args: "--lua-desync=multisplit:pos=1:fooling=badseq", description: "Standard 2-fragment multisplit desync for compatibility." }, { id: "z2_disorder_pos2", name: "Classic Multidisorder (pos=2)", engine: "zapret2", args: "--lua-desync=multidisorder:pos=2:fooling=badseq", description: "Sends out-of-order segment with badseq fooling." }, // ── 7. LOW-TTL ADAPTIVE MATRIX ───────────────────────────────────────────── { id: "z2_fake_ttl3_md5sig", name: "Fake (TTL=3, MD5Sig) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:ttl=3:fooling=md5sig --lua-desync=multisplit:pos=1,midsld", description: "Aggressive low-TTL MD5Sig injection for close TSPU hops." }, { id: "z2_fake_ttl4_badseq", name: "Fake (TTL=4, BadSeq) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:ttl=4:fooling=badseq --lua-desync=multisplit:pos=1,midsld", description: "Low-TTL fake ClientHello with badseq fooling and multisplit segmentation." }, { id: "z2_fake_ttl5_md5sig", name: "Fake (TTL=5, MD5Sig) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:ttl=5:fooling=md5sig --lua-desync=multisplit:pos=1,midsld", description: "MD5Sig TCP option drops packet at DPI while reaching end server." }, { id: "z2_fake_ttl6_badack", name: "Fake (TTL=6, BadACK) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:ttl=6:fooling=badack --lua-desync=multisplit:pos=1,sniext+2", description: "BadACK fooling invalidates packet in DPI state tracking." }, { id: "z2_fake_badseq_mid", name: "Fake Packet (TTL=8) + MidSLD Split", engine: "zapret2", args: "--lua-desync=fake:ttl=8:fooling=badseq --lua-desync=multisplit:pos=midsld", description: "Injects fake ClientHello before segmented payload." }, { id: "z2_fake_datanoack", name: "Fake (TTL=8, DataNoAck) + Multisplit", engine: "zapret2", args: "--lua-desync=fake:ttl=8:fooling=datanoack --lua-desync=multisplit:pos=1", description: "DataNoAck fooling confuses stateful DPI without triggering ACK RST." }, { id: "z2_oob_pos1", name: "OOB Out-of-Band Data (pos=1)", engine: "zapret2", args: "--lua-desync=oob:pos=1", description: "TCP Out-Of-Band URG flag packet to desynchronize DPI reassembly." }, // ── 8. BLOCKCHECKW & BLOCKCHECK2 COMBAT STRATEGIES ───────────────────────── { id: "z2_bc_multisplit_7point", name: "7-Point MultiSplit (ClientHello Full Spectrum)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=multisplit:pos=1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1", description: "Splits at start, SNI extension, host header, mid-SLD, and end of host. Top blockcheck2 bypass." }, { id: "z2_bc_multidisorder_7point", name: "7-Point MultiDisorder (ClientHello Full Spectrum)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=multidisorder:pos=1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1", description: "Disorders all critical TLS ClientHello headers. Devastates stateful DPI reassembly." }, { id: "z2_bc_multisplit_1220", name: "Tri-Point MultiSplit (pos=1,midsld,1220)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=multisplit:pos=1,midsld,1220", description: "Splits at start, mid-SLD, and packet boundary (1220 B)." }, { id: "z2_bc_multidisorder_1220", name: "Tri-Point MultiDisorder (pos=1,midsld,1220)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=multidisorder:pos=1,midsld,1220", description: "Disorders stream at start, mid-SLD, and MTU boundary (1220 B)." }, { id: "z2_bc_tcpseg_rep260", name: "TCP Segment Desync (repeats=260, pos=0,1)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=tcpseg:pos=0,1:ip_id=rnd:repeats=260", description: "Forces randomized IP ID TCP segmentation burst with 260 repeats to overflow DPI state table." }, { id: "z2_bc_tcpseg_rep100_midsld", name: "TCP Segment Desync (repeats=100, midsld)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=tcpseg:pos=0,midsld:ip_id=rnd:repeats=100", description: "Mid-SLD TCP segmentation with 100 repeats." }, { id: "z2_bc_oob_midsld", name: "OOB Desync (urp=midsld)", engine: "zapret2", args: "--in-range=-s1 --lua-desync=oob:urp=midsld", description: "TCP Out-Of-Band packet with urgent pointer pointing directly to mid-domain." }, { id: "z2_bc_oob_b", name: "OOB Desync (urp=b)", engine: "zapret2", args: "--in-range=-s1 --lua-desync=oob:urp=b", description: "TCP Out-Of-Band with beginning urgent pointer offset." }, { id: "z2_bc_seqovl_sniext", name: "Exact SeqOvl Pattern Overlap (sniext+1, Max.ru)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=multidisorder:pos=sniext+1:seqovl=sniext:seqovl_pattern=tls_max", description: "Disorders at SNI extension with exact sequence overlap pattern." }, { id: "z2_bc_seqovl_midsld", name: "Exact SeqOvl Pattern Overlap (midsld, Google)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=multidisorder:pos=midsld:seqovl=midsld-1:seqovl_pattern=tls_google", description: "Disorders at mid-SLD with exact sequence overlap pattern from Google ClientHello." }, { id: "z2_bc_lua_padencap", name: "Dynamic Lua TLS Mod (padencap + dupsid) + MultiSplit", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=luaexec:code=desync.patmod=tls_mod(fake_default_tls,'rnd,dupsid,padencap',desync.reasm_data) --lua-desync=multisplit:pos=10,sniext+1:seqovl=#patmod:seqovl_pattern=patmod", description: "Dynamically pads and encapsulates ClientHello payload via Lua runtime." }, { id: "z2_bc_tcp_ack_offset", name: "TCP ACK Offset Spoofing (-66000) + TS_UP", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=fake:blob=tls_max:tcp_ack=-66000:tcp_ts_up:repeats=6", description: "Injects fake packets with corrupted ACK number and ascending TCP timestamps." }, { id: "z2_bc_tcp_flags_unset_ack", name: "TCP Flags Manipulation (Unset ACK)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=fake:blob=tls_google:tcp_flags_unset=ACK:repeats=6", description: "Fake packets with ACK flag cleared, accepted only by DPI state trackers." }, { id: "z2_bc_tcp_flags_set_syn", name: "TCP Flags Manipulation (Set SYN on Data)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=fake:blob=tls_max:tcp_flags_set=SYN:repeats=6", description: "Sets SYN flag on ClientHello fake packets to trigger DPI state desynchronization." }, { id: "z2_bc_badsum", name: "BadSum Checksum Invalidation", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=fake:blob=tls_google:badsum:repeats=6", description: "Packets with invalid L4 checksum are dropped by remote server NIC but inspected by DPI." }, { id: "z2_bc_autottl_1", name: "Auto-TTL Adaptive Probe (autottl=-1, 3-20)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=fake:blob=tls_max:ip_autottl=-1,3-20:repeats=6", description: "Dynamically calculates hop distance to target and injects fake packets right before DPI hop." }, { id: "z2_bc_autottl_2", name: "Auto-TTL Adaptive Probe (autottl=-2, 3-20)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=fake:blob=tls_google:ip_autottl=-2,3-20:repeats=6", description: "Auto-TTL probe with 2 hops before target." }, { id: "z2_bc_pktmod", name: "PktMod Packet Mutation (ip_ttl=1)", engine: "zapret2", args: "--payload=tls_client_hello --lua-desync=fake:blob=tls_max:ip_ttl=1:repeats=6 --payload=empty --out-range=s1 0) { for (let cs in cfg.custom_strategies) { if (cs && cs.engine == "zapret2" && cs.args) { add(cs.name || "Custom Zapret v2", cs.args, cs.description || "User custom strategy"); } } } let splits = p.splits || [ "1", "2", "3", "midsld", "sniext+2", "sniext+4", "1,midsld", "1,sniext+2" ]; let foolings = p.foolings || [ "badseq", "md5sig", "badack", "datanoack", "fakeddrop" ]; let ttls = p.ttls || [ 2, 3, 4, 5, 6, 8 ]; let seqovls = p.seqovls || [ "1", "2" ]; let wsizes = p.wsizes || [ "1" ]; let blobs = p.blobs || [ "tls_max", "tls_google", "tls_gosuslugi", "tls_sber", "tls_iana" ]; let repeats_list = p.repeats || [ 6, 8 ]; // 1. Multisplit combinations for (let pos in splits) { for (let fooling in foolings) { add(sprintf("Multisplit (pos=%s, %s)", pos, fooling), sprintf("--lua-desync=multisplit:pos=%s:fooling=%s", pos, fooling), "Multisplit position and fooling method"); } for (let sq in seqovls) { add(sprintf("Multisplit + SeqOvl %s (pos=%s, badseq)", sq, pos), sprintf("--lua-desync=multisplit:pos=%s:seqovl=%s:fooling=badseq", pos, sq), "Multisplit with sequence overlap"); } for (let w in wsizes) { add(sprintf("Multisplit + Window %s (pos=%s, badseq)", w, pos), sprintf("--lua-desync=multisplit:pos=%s:wsize=%s:fooling=badseq", pos, w), "Multisplit with TCP window size clamping"); } } // 2. Multidisorder combinations for (let pos in [ "2", "midsld", "1,midsld" ]) { for (let fooling in [ "badseq", "md5sig", "badack" ]) { add(sprintf("Multidisorder (pos=%s, %s)", pos, fooling), sprintf("--lua-desync=multidisorder:pos=%s:fooling=%s", pos, fooling), "Out-of-order segment delivery with fooling"); } } // 3. PAWS Timestamp Spoofing with Authentic Blobs (Top-tier TSPU evasion) for (let blob in blobs) { for (let rep in repeats_list) { for (let pos in [ "1", "1,midsld", "midsld" ]) { add(sprintf("Fake PAWS (%s, rep=%d) + Multisplit (pos=%s)", blob, rep, pos), sprintf("--lua-desync=fake:blob=%s:repeats=%d:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=%s", blob, rep, pos), "PAWS ancient TCP timestamp spoofing with authentic ClientHello blob"); let dis_pos = (pos == "1") ? "2" : pos; add(sprintf("Fake PAWS (%s, rep=%d) + Multidisorder (pos=%s)", blob, rep, dis_pos), sprintf("--lua-desync=fake:blob=%s:repeats=%d:tcp_ts=-600000:tcp_ts_up --lua-desync=multidisorder:pos=%s", blob, rep, dis_pos), "PAWS ancient TCP timestamp spoofing with multidisorder segments"); } } } // 4. Exact SeqOvl Pattern Overlaps let blob_patterns = [ { name: "tls_max", size: 664 }, { name: "tls_google", size: 681 }, { name: "tls_gosuslugi", size: 517 }, { name: "tls_sber", size: 517 } ]; for (let bp in blob_patterns) { add(sprintf("SeqOvl Pattern %s (%d B, pos=1)", bp.name, bp.size), sprintf("--lua-desync=multisplit:pos=1:seqovl=%d:seqovl_pattern=%s", bp.size, bp.name), "Sequence overlap filled with authentic ClientHello pattern"); add(sprintf("Fake PAWS (%s) + SeqOvl Pattern (%d B)", bp.name, bp.size), sprintf("--lua-desync=fake:blob=%s:repeats=8:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1:seqovl=%d:seqovl_pattern=%s", bp.name, bp.size, bp.name), "Combined PAWS fake burst and pattern sequence overlap"); } // 5. TCP SYN Data combinations for (let pos in [ "1", "1,midsld", "midsld" ]) { let dis_pos = (pos == "1") ? "2" : pos; add(sprintf("SYN Data + Multidisorder (pos=%s)", dis_pos), sprintf("--lua-desync=syndata --lua-desync=multidisorder:pos=%s", dis_pos), "TCP SYN data payload with out-of-order data segments"); add(sprintf("SYN Data + Multisplit (pos=%s, seqovl=1)", pos), sprintf("--lua-desync=syndata --lua-desync=multisplit:pos=%s:seqovl=1:fooling=badseq", pos), "TCP SYN data payload with multisplit sequence overlap"); add(sprintf("SYN Data + Window Clamp (wsize=1, pos=%s)", pos), sprintf("--lua-desync=syndata --lua-desync=multisplit:pos=%s:wsize=1:fooling=badseq", pos), "TCP SYN data payload with 1-byte window clamp"); } // 6. Low-TTL Fake combinations for (let ttl in ttls) { for (let fooling in [ "badseq", "md5sig", "badack" ]) { for (let pos in [ "1", "1,midsld", "midsld" ]) { add(sprintf("Fake (TTL=%d, %s) + Multisplit (pos=%s)", ttl, fooling, pos), sprintf("--lua-desync=fake:ttl=%d:fooling=%s --lua-desync=multisplit:pos=%s", ttl, fooling, pos), "Low-TTL fake injection followed by multisplit payload"); let dis_pos = (pos == "1") ? "2" : pos; add(sprintf("Fake (TTL=%d, %s) + Multidisorder (pos=%s)", ttl, fooling, dis_pos), sprintf("--lua-desync=fake:ttl=%d:fooling=%s --lua-desync=multidisorder:pos=%s", ttl, fooling, dis_pos), "Low-TTL fake injection followed by multidisorder payload"); } } } // 7. Fakedsplit, Fakeddisorder & Hostfakesplit for (let pos in [ "1", "1,midsld", "midsld" ]) { add(sprintf("Fakedsplit (pos=%s, badseq)", pos), sprintf("--lua-desync=fakedsplit:pos=%s:fooling=badseq", pos), "Stream splitting with embedded fake packets"); let dis_pos = (pos == "1") ? "2" : pos; add(sprintf("Fakeddisorder (pos=%s, badseq)", dis_pos), sprintf("--lua-desync=fakeddisorder:pos=%s:fooling=badseq", dis_pos), "Out-of-order stream with embedded fake fragments"); add(sprintf("Hostfakesplit (pos=%s, badseq)", pos), sprintf("--lua-desync=hostfakesplit:pos=%s:fooling=badseq", pos), "Host header substitution in initial packet"); } // 8. Blockcheck2 & Blockcheckw Heavy Multi-Split Chains let multi_chains = [ "1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1", "1,midsld,1220", "1,sniext+1,host+1", "10,sniext+4" ]; for (let chain in multi_chains) { add(sprintf("7-Point MultiSplit (%s)", chain), sprintf("--payload=tls_client_hello --lua-desync=multisplit:pos=%s", chain), "Full-spectrum ClientHello multisplit fragmentation"); add(sprintf("7-Point MultiDisorder (%s)", chain), sprintf("--payload=tls_client_hello --lua-desync=multidisorder:pos=%s", chain), "Full-spectrum ClientHello multidisorder fragmentation"); } // 9. TCP Segmentation & OOB combinations for (let rep in [ 20, 100, 260 ]) { add(sprintf("TCPSegment (repeats=%d, pos=0,1)", rep), sprintf("--payload=tls_client_hello --lua-desync=tcpseg:pos=0,1:ip_id=rnd:repeats=%d", rep), "Randomized IP-ID TCP segmentation burst"); add(sprintf("TCPSegment (repeats=%d, midsld)", rep), sprintf("--payload=tls_client_hello --lua-desync=tcpseg:pos=0,midsld:ip_id=rnd:repeats=%d", rep), "Mid-SLD TCP segmentation burst"); } for (let urp in [ "midsld", "b", "2" ]) { add(sprintf("OOB Desync (urp=%s)", urp), sprintf("--in-range=-s1 --lua-desync=oob:urp=%s", urp), "TCP Out-Of-Band URG packet with urgent pointer offset"); } // 10. Advanced TCP flag & ACK offsets with authentic blobs for (let blob in [ "tls_max", "tls_google" ]) { add(sprintf("TCP ACK Offset (-66000, %s)", blob), sprintf("--payload=tls_client_hello --lua-desync=fake:blob=%s:tcp_ack=-66000:tcp_ts_up:repeats=6", blob), "Corrupted TCP ACK offset with PAWS ascending timestamps"); add(sprintf("TCP Flags Unset ACK (%s)", blob), sprintf("--payload=tls_client_hello --lua-desync=fake:blob=%s:tcp_flags_unset=ACK:repeats=6", blob), "Fake packets with ACK flag cleared"); add(sprintf("BadSum Checksum Invalidation (%s)", blob), sprintf("--payload=tls_client_hello --lua-desync=fake:blob=%s:badsum:repeats=6", blob), "Corrupted L4 checksum fake packets"); add(sprintf("Auto-TTL Adaptive Probe (%s, autottl=-1,3-20)", blob), sprintf("--payload=tls_client_hello --lua-desync=fake:blob=%s:ip_autottl=-1,3-20:repeats=6", blob), "Adaptive distance TTL calculation before DPI hop"); } return list; } function generate_combinatorial_zapret() { let cfg = get_patterns_config(); let p = cfg.zapret || DEFAULT_PATTERNS.zapret; let list = []; let seen = {}; let add = function(name, args, desc) { args = trim(as_string(args)); if (args == "" || seen[args]) return; if (!validate_strategy_args("zapret", args)) return; seen[args] = true; push(list, { id: sprintf("z1_gen_%d", length(list) + 1), name: name, engine: "zapret", args: args, description: desc }); }; for (let s in STRATEGIES_ZAPRET) add(s.name, s.args, s.description); if (cfg.custom_strategies && length(cfg.custom_strategies) > 0) { for (let cs in cfg.custom_strategies) { if (cs && cs.engine == "zapret" && cs.args) { add(cs.name || "Custom Zapret v1", cs.args, cs.description || "User custom strategy"); } } } let modes = p.split_modes || [ "split2", "disorder2", "fake,split2", "fake,disorder2" ]; let positions = p.splits || [ "1", "2", "midsld" ]; for (let mode in modes) { for (let pos in positions) { for (let fooling in [ "badseq", "md5sig", "badack" ]) { if (index(mode, "fake") >= 0) { for (let ttl in [ 3, 4, 8 ]) { add(sprintf("%s (pos=%s, TTL=%d, %s)", mode, pos, ttl, fooling), sprintf("--dpi-desync=%s --dpi-desync-split-pos=%s --dpi-desync-ttl=%d --dpi-desync-fooling=%s", mode, pos, ttl, fooling), "Fake desync with split pos and fooling"); } } else { add(sprintf("%s (pos=%s, %s)", mode, pos, fooling), sprintf("--dpi-desync=%s --dpi-desync-split-pos=%s --dpi-desync-fooling=%s", mode, pos, fooling), "Desync with split pos and fooling"); } } } } return list; } function generate_combinatorial_byedpi() { let cfg = get_patterns_config(); let p = cfg.byedpi || DEFAULT_PATTERNS.byedpi; let list = []; let seen = {}; let add = function(name, args, desc) { args = trim(as_string(args)); if (args == "" || seen[args]) return; if (!validate_strategy_args("byedpi", args)) return; seen[args] = true; push(list, { id: sprintf("bd_gen_%d", length(list) + 1), name: name, engine: "byedpi", args: args, description: desc }); }; for (let s in STRATEGIES_BYEDPI) add(s.name, s.args, s.description); if (cfg.custom_strategies && length(cfg.custom_strategies) > 0) { for (let cs in cfg.custom_strategies) { if (cs && cs.engine == "byedpi" && cs.args) { add(cs.name || "Custom ByeDPI", cs.args, cs.description || "User custom strategy"); } } } let splits = p.splits || [ "1", "2", "1+sniext", "midsld" ]; let disorders = p.disorders || [ "1", "2" ]; let oobs = p.oobs || [ "1", "2" ]; let autos = p.autos || [ "t,r,a,s", "r,s", "t,a" ]; // 1. Classic adaptive combinations for (let a in autos) { for (let o in oobs) { for (let d in disorders) { add(sprintf("Auto (%s) + OOB=%s + Disorder=%s", a, o, d), sprintf("-o %s --auto=%s -d %s", o, a, d), "Adaptive auto mode with OOB and disorder"); } for (let s in splits) { add(sprintf("Auto (%s) + OOB=%s + Split=%s", a, o, s), sprintf("-o %s --auto=%s -s %s", o, a, s), "Adaptive auto mode with OOB and split"); } } } // 2. Fake with split & disorder for (let ttl in [ 3, 4, 8 ]) { for (let s in [ "1", "1+sniext", "midsld" ]) { for (let d in [ "1", "2" ]) { add(sprintf("Split=%s + Disorder=%s + Fake (TTL=%d)", s, d, ttl), sprintf("--split %s --disorder %s --fake -1 --ttl %d", s, d, ttl), "Fake injection with split and disorder"); } } } // 3. Multi-split ladder chains (Combinatorial combat suites) let ladder_bases = [ { name: "Ladder 3-Step", args: "-d1 -d3+s -s6+s" }, { name: "Ladder 5-Step", args: "-d1 -d3+s -s6+s -d9+s -s12+s" }, { name: "Ladder 8-Step", args: "-d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s" }, { name: "Ladder 10-Step", args: "-d1 -d3+s -s6+s -d9+s -s12+s -d15+s -s20+s -d25+s -s30+s -d35+s" }, { name: "Split Ladder 6-Step", args: "-s1 -s3+s -s6+s -s9+s -s12+s -s15+s" }, { name: "Disorder Ladder 6-Step", args: "-d1 -d3+s -d6+s -d9+s -d12+s -d15+s" } ]; let reverse_tails = [ "", " -r1+s", " -r2+s" ]; let sack_options = [ " -S", "" ]; let auto_tails = [ " -a1 -As", " -a1", " --auto=r,s", "" ]; for (let lb in ladder_bases) { for (let rt in reverse_tails) { for (let so in sack_options) { for (let at in auto_tails) { let comb_args = trim(sprintf("%s%s%s%s", lb.args, rt, so, at)); add(sprintf("%s%s%s%s", lb.name, rt != "" ? " + Rev" : "", so != "" ? " + SACK" : "", at != "" ? " + Auto" : ""), comb_args, "Multi-stage ladder split & disorder chain for resilient DPI bypass"); } } } } // 4. Fake packet with multi-split ladder for (let ttl in [ 3, 4, 6, 8 ]) { add(sprintf("Fake (TTL=%d) + 4-Step Ladder + SACK Drop", ttl), sprintf("-s1+s -d2+s -s3+s -d4+s -f-1 -t%d -r1+s -S -a1", ttl), "Fake handshake packet followed by 4-step SNI ladder and SACK suppression"); add(sprintf("Fake (TTL=%d) + TLS Record Split + SACK Drop", ttl), sprintf("--tlsrec 1+sniext -s1+s -d2+s -f-1 -t%d -S -a1", ttl), "TLS record boundary split with fake packet and SACK drop"); } return list; } function generate_adaptive_strategies(engine, target) { let list = []; let seen = {}; let add = function(name, args, desc, rationale) { args = trim(as_string(args)); if (args == "" || seen[args]) return; if (!validate_strategy_args(engine == "all" ? "zapret2" : engine, args)) return; seen[args] = true; push(list, { id: sprintf("adapt_%s_%d", engine, length(list) + 1), name: name, engine: engine == "all" ? "zapret2" : engine, args: args, description: desc || "Adaptive evolved strategy", rationale: rationale || "Synthesized from parameter attribution and target profile" }); }; // 1. Seed from Prior History: inject historic winning strategies for this target & engine let history_res = get_history(20); if (history_res && length(history_res) > 0) { for (let h in history_res) { if (h && h.target == target && h.best_strategy && (engine == "all" || h.engine == engine)) { let bs = h.best_strategy; if (bs.args && !seen[bs.args]) { add("⭐ Prior Winner: " + (bs.name || "Historical Best"), bs.args, "Previously verified effective on this target", "Historical success seed"); } } } } // 2. High-probability domain seeds based on engine if (engine == "zapret2" || engine == "all") { for (let blob in [ "tls_max", "tls_google", "tls_gosuslugi", "tls_sber" ]) { let seq = (blob == "tls_max") ? 664 : (blob == "tls_google" ? 681 : 517); add(sprintf("PAWS (%s) + Multisplit pos=1", blob), sprintf("--lua-desync=fake:blob=%s:repeats=8:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1:seqovl=%d:seqovl_pattern=%s", blob, seq, blob), "PAWS timestamp desync with authentic blob overlap"); add(sprintf("PAWS (%s) + Multisplit pos=1,midsld", blob), sprintf("--lua-desync=fake:blob=%s:repeats=6:tcp_ts=-600000:tcp_ts_up --lua-desync=multisplit:pos=1,midsld:seqovl=%d:seqovl_pattern=%s", blob, seq, blob), "PAWS with midsld multisplit"); } add("SYN Data + Multisplit pos=1,midsld (badseq)", "--lua-desync=syndata --lua-desync=multisplit:pos=1,midsld:seqovl=1:fooling=badseq", "TCP SYN payload injection with badseq fooling"); add("SYN Data + Multidisorder pos=1,midsld", "--lua-desync=syndata --lua-desync=multidisorder:pos=1,midsld", "TCP SYN payload injection with segment disordering"); add("SYN Data + Window Clamp wsize=1", "--lua-desync=syndata --lua-desync=multisplit:pos=1,midsld:wsize=1", "SYN data injection with 1-byte TCP window clamping"); for (let fooling in [ "badseq", "fakeddrop", "badack" ]) { for (let ttl in [ 3, 4, 6 ]) { for (let pos in [ "1", "1,midsld", "sniext+4" ]) { add(sprintf("Fake (%s, ttl=%d) + Multisplit %s", fooling, ttl, pos), sprintf("--lua-desync=fake:blob=tls_max:repeats=6:ttl=%d:fooling=%s --lua-desync=multisplit:pos=%s", ttl, fooling, pos), "Evolved fake desync parameter combination"); } } } } if (engine == "zapret" || engine == "all") { for (let split_mode in [ "split2", "fake,split2", "disorder2", "fake,disorder2" ]) { for (let ttl in [ 2, 3, 4, 6, 8 ]) { for (let pos in [ "1", "2", "midsld", "sniext+4" ]) { let fooling = index(split_mode, "fake") >= 0 ? " --dpi-desync-fooling=badseq" : ""; add(sprintf("%s (pos=%s, ttl=%d)", split_mode, pos, ttl), sprintf("--dpi-desync=%s --dpi-desync-split-pos=%s --dpi-desync-ttl=%d%s", split_mode, pos, ttl, fooling), "Adaptive parameter combination for Zapret v1"); } } } } if (engine == "byedpi" || engine == "all") { for (let a in [ "t,r,a,s", "r,s", "t,a" ]) { for (let o in [ "1", "2" ]) { for (let d in [ "1", "2" ]) { add(sprintf("Auto (%s) + OOB %s + Disorder %s", a, o, d), sprintf("-o %s --auto=%s -d %s", o, a, d), "Adaptive auto mode with OOB and disorder"); } for (let s in [ "1", "1+sniext", "midsld" ]) { add(sprintf("Auto (%s) + OOB %s + Split %s", a, o, s), sprintf("-o %s --auto=%s -s %s", o, a, s), "Adaptive auto mode with OOB and split"); } } } for (let ttl in [ 3, 4, 8 ]) { for (let s in [ "1", "1+sniext", "midsld" ]) { add(sprintf("Fake (TTL=%d) + Split %s", ttl, s), sprintf("--split %s --fake -1 --ttl %d", s, ttl), "ByeDPI fake injection with split"); } } } // Check memory budget: if low RAM (<32MB), cap to 20 strategies let avail_kb = fuzzer_runner.get_system_memory_kb(); if (avail_kb < 32768 && length(list) > 20) { let capped = []; for (let i = 0; i < 20; i++) push(capped, list[i]); return capped; } return list; } function get_strategies_for_engine(engine, mode, target) { engine = lc(as_string(engine)); mode = lc(trim(as_string(mode || "presets"))); let cfg = get_patterns_config(); if (mode == "custom" || mode == "user") { let custom_list = []; for (let cs in cfg.custom_strategies) { if (cs && (engine == "all" || cs.engine == engine) && cs.args) { push(custom_list, { id: cs.id || sprintf("custom_%d", length(custom_list) + 1), name: cs.name || "Custom Strategy", engine: cs.engine || engine, args: cs.args, description: cs.description || "" }); } } return custom_list; } if (mode == "adaptive" || mode == "smart") { return generate_adaptive_strategies(engine, target || "youtube_suite"); } if (mode == "combinatorial" || mode == "deep_fuzz" || mode == "deep") { let combo = []; if (engine == "zapret2") combo = generate_combinatorial_zapret2(); else if (engine == "zapret") combo = generate_combinatorial_zapret(); else if (engine == "byedpi") combo = generate_combinatorial_byedpi(); else if (engine == "all") { for (let s in generate_combinatorial_zapret2()) push(combo, s); for (let s in generate_combinatorial_zapret()) push(combo, s); for (let s in generate_combinatorial_byedpi()) push(combo, s); } let avail_kb = fuzzer_runner.get_system_memory_kb(); if (avail_kb < 32768 && length(combo) > 30) { let capped = []; for (let i = 0; i < 30; i++) push(capped, combo[i]); return capped; } return combo; } let base = []; if (engine == "zapret2") base = STRATEGIES_ZAPRET2; else if (engine == "zapret") base = STRATEGIES_ZAPRET; else if (engine == "byedpi") base = STRATEGIES_BYEDPI; else if (engine == "all") { for (let s in STRATEGIES_ZAPRET2) push(base, s); for (let s in STRATEGIES_ZAPRET) push(base, s); for (let s in STRATEGIES_BYEDPI) push(base, s); } let result = []; let seen_args = {}; // Seed prior winners from history if available let history_res = get_history(10); if (history_res && length(history_res) > 0) { for (let h in history_res) { if (h && target && h.target == target && h.best_strategy && (engine == "all" || h.engine == engine)) { let bs = h.best_strategy; if (bs.args && !seen_args[bs.args]) { seen_args[bs.args] = true; push(result, { id: sprintf("hist_%s_1", bs.engine || engine), name: "⭐ " + (bs.name || "Historical Best"), engine: bs.engine || engine, args: bs.args, description: "Previously verified winner on this target" }); } } } } for (let s in base) { if (!seen_args[s.args]) { seen_args[s.args] = true; push(result, s); } } for (let cs in cfg.custom_strategies) { if (cs && (engine == "all" || cs.engine == engine) && cs.args && !seen_args[cs.args]) { seen_args[cs.args] = true; push(result, { id: cs.id || sprintf("custom_%d", length(result) + 1), name: cs.name || "Custom Strategy", engine: cs.engine || engine, args: cs.args, description: cs.description || "User custom strategy" }); } } return result; } function resolve_target_url(target_key, custom_url) { if (custom_url && custom_url != "") return custom_url; return TARGET_URLS[target_key] || TARGET_URLS.youtube; } function resolve_target_urls_list(target_key, custom_url) { if (custom_url && custom_url != "") { return [ { name: "Custom Target", url: custom_url, weight: 100, required: true, probe_kind: "tls_http" } ]; } target_key = as_string(target_key || "youtube_suite"); if (target_key == "quic_http3") { return [ { name: "Google QUIC Initial / HTTP3", url: "https://www.google.com", weight: 100, required: true, probe_kind: "quic" } ]; } let suite = TARGET_SUITES[target_key]; if (suite && suite.urls && length(suite.urls) > 0) { return suite.urls; } let single = TARGET_URLS[target_key] || TARGET_URLS.youtube; return [ { name: target_key, url: single, weight: 100, required: true, probe_kind: (target_key == "quic_http3" ? "quic" : "tls_http") } ]; } function ensure_state_dir() { common.ensure_dir(STATE_DIR); } function save_fuzzer_state(state) { ensure_state_dir(); common.write_json_file(STATE_FILE, state); if (state && state.job_id) { let job_dir = get_job_dir(state.job_id); if (job_dir) { common.write_json_file(job_dir + "/state.json", state); } } } function safe_json_parse(str) { if (!str || str == "") return null; let obj = null; try { obj = json(str); } catch (e) { obj = null; } return obj; } function query_llm(provider, api_key, custom_url, prompt_text, model_override) { provider = lc(trim(as_string(provider || "openai"))); model_override = trim(as_string(model_override || "")); if (provider == "anthropic" || provider == "claude") { let api_url = "https://api.anthropic.com/v1/messages"; let model = model_override != "" ? model_override : "claude-3-5-haiku-20241022"; let body = { model, max_tokens: 1000, messages: [{ role: "user", content: prompt_text }] }; let cmd = sprintf( "curl -s -m 35 --connect-timeout 10 -X POST -H 'x-api-key: %s' -H 'anthropic-version: 2023-06-01' -H 'content-type: application/json' -d %s %s 2>/dev/null", shell_quote(api_key), shell_quote(sprintf("%J", body)), shell_quote(api_url) ); let pipe = fs.popen(cmd, "r"); let output = pipe ? pipe.read("all") : ""; if (pipe) pipe.close(); let parsed = safe_json_parse(output); if (parsed && parsed.content && type(parsed.content) == "array" && length(parsed.content) > 0) { return parsed.content[0].text; } return null; } let base_url = "https://api.openai.com/v1"; let default_model = "gpt-4o-mini"; if (provider == "deepseek") { base_url = "https://api.deepseek.com/v1"; default_model = "deepseek-chat"; } else if (provider == "openrouter") { base_url = "https://openrouter.ai/api/v1"; default_model = "deepseek/deepseek-chat"; } else if (provider == "ollama") { base_url = custom_url && custom_url != "" ? custom_url : "http://127.0.0.1:11434/v1"; default_model = "llama3.2"; } else if (provider == "lmstudio" || provider == "custom") { base_url = custom_url && custom_url != "" ? custom_url : "http://127.0.0.1:1234/v1"; default_model = "local-model"; } base_url = replace(base_url, /\/+$/, ""); let api_url = base_url + "/chat/completions"; let model = model_override != "" ? model_override : default_model; let body = { model, messages: [ { role: "system", content: "You are a network censorship and DPI bypass expert. Always return responses formatted strictly as requested." }, { role: "user", content: prompt_text } ], temperature: 0.3 }; let auth_header = api_key != "" ? sprintf("-H 'Authorization: Bearer %s'", api_key) : ""; let cmd = sprintf( "curl -s -m 35 --connect-timeout 10 -X POST %s -H 'Content-Type: application/json' -d %s %s 2>/dev/null", auth_header, shell_quote(sprintf("%J", body)), shell_quote(api_url) ); let pipe = fs.popen(cmd, "r"); let output = pipe ? pipe.read("all") : ""; if (pipe) pipe.close(); let parsed = safe_json_parse(output); if (parsed && parsed.choices && type(parsed.choices) == "array" && length(parsed.choices) > 0) { let msg = parsed.choices[0].message; if (msg && msg.content) { return msg.content; } } return null; } function parse_llm_json(raw_text) { raw_text = trim(as_string(raw_text)); if (raw_text == "") return null; let direct = safe_json_parse(raw_text); if (direct && type(direct) == "object") return direct; let m = match(raw_text, /```json\s*([\s\S]*?)\s*```/); if (m && m[1]) { let parsed = safe_json_parse(m[1]); if (parsed && type(parsed) == "object") return parsed; } m = match(raw_text, /\{[\s\S]*\}/); if (m && m[0]) { let parsed = safe_json_parse(m[0]); if (parsed && type(parsed) == "object") return parsed; } return null; } function synthesize_ai_strategies(engine, target, custom_url, user_prompt) { let current = get_fuzzer_state(); if (current.running) { print(sprintf("%J\n", { success: false, error: "Fuzzer is currently running a benchmark" })); return; } engine = lc(as_string(engine || "zapret2")); target = trim(as_string(target || "youtube_suite")); user_prompt = trim(as_string(user_prompt || "")); let target_url = resolve_target_url(target, custom_url); let baseline = run_probe(engine, "", target, custom_url); let query_text = sprintf("%s %s %s", engine, target, user_prompt); let rag_docs = rag.retrieve(query_text, 4); let uci = uci_core.cursor(); let ai_sec = uci.get_all(CONFIG_NAME, "ai") || {}; let provider = ai_sec.provider || "openai"; let api_key = ai_sec.api_key || ""; let ai_custom_url = ai_sec.custom_url || ""; let model_override = ai_sec.model || ""; let prompt = sprintf( "You are an expert DPI Bypass Engineer specializing in OpenWrt, Zapret, Zapret2 (nfqws2), and ByeDPI (ciadpi).\n" + "We need to bypass censorship / TSPU blocking for target service '%s' (%s) using engine '%s'.\n\n" + "LIVE PROBE DIAGNOSTICS:\n" + "- Direct HTTP Code: %d\n" + "- Connect Time: %d ms\n" + "- TTFB: %d ms\n" + "- Probe Error: %s\n" + "- User Notes / ISP Context: %s\n\n" + "TECHNICAL KNOWLEDGE BASE FRAGMENTS:\n%s\n\n" + "TASK:\n" + "1. Analyze why this target is blocked or throttled.\n" + "2. Formulate 3 to 5 highly effective, syntactically valid DPI desync strategies for '%s'.\n" + "3. Output MUST be strictly valid JSON matching this schema:\n" + "{\n" + ' "analysis": "Brief 1-2 sentence diagnosis of the blocking pattern",\n' + ' "strategies": [\n' + ' {\n' + ' "id": "ai_strat_1",\n' + ' "name": "Human-readable descriptive strategy name",\n' + ' "args": "Exact command-line arguments string for the engine",\n' + ' "description": "Why this combination should bypass the block"\n' + ' }\n' + ' ]\n' + "}\n\n" + "RULES FOR STRATEGY ARGS:\n" + "- For zapret2: use valid options like '--lua-desync=multisplit:pos=1,midsld:seqovl=1:fooling=badseq' or '--lua-desync=fake:ttl=4:fooling=badseq --lua-desync=multisplit:pos=1,midsld'. DO NOT include binary name.\n" + "- For zapret: use valid options like '--dpi-desync=fake,split2 --dpi-desync-split-pos=1,midsld --dpi-desync-fooling=badseq --dpi-desync-ttl=4'. DO NOT include binary name.\n" + "- For byedpi: use valid options like '-s 1 -d 1 --auto=t,r,s -o 1'. DO NOT include binary name.\n\n" + "JSON OUTPUT:", target, target_url, engine, baseline.http_code, baseline.handshake_ms, baseline.ttfb_ms, baseline.error != "" ? baseline.error : "none", user_prompt != "" ? user_prompt : "None provided", rag_docs, engine ); let raw_reply = query_llm(provider, api_key, ai_custom_url, prompt, model_override); if (!raw_reply) { print(sprintf("%J\n", { success: false, error: "Failed to receive response from AI provider. Check API key and network connectivity." })); return; } let parsed_json = parse_llm_json(raw_reply); if (!parsed_json || !parsed_json.strategies || type(parsed_json.strategies) != "array" || length(parsed_json.strategies) == 0) { print(sprintf("%J\n", { success: false, error: "AI returned non-JSON or invalid format", raw_response: raw_reply })); return; } let valid_strategies = []; for (let i = 0; i < length(parsed_json.strategies); i++) { let st = parsed_json.strategies[i]; if (st && st.args && validate_strategy_args(engine, st.args)) { push(valid_strategies, { id: st.id || sprintf("ai_strat_%d", i + 1), name: st.name || sprintf("AI Strategy %d", i + 1), engine, args: trim(st.args), description: st.description || "" }); } } if (length(valid_strategies) == 0) { print(sprintf("%J\n", { success: false, error: "All AI strategies failed syntax validation for engine " + engine, raw_strategies: parsed_json.strategies })); return; } let custom_file = STATE_DIR + "/fuzzer_ai_strategies.json"; ensure_state_dir(); common.write_json_file(custom_file, valid_strategies); print(sprintf("%J\n", { success: true, engine, target, target_url, analysis: parsed_json.analysis || "AI strategy synthesis complete", strategies: valid_strategies, custom_file })); } function get_fuzzer_state() { let state = common.read_json_file(STATE_FILE); if (!state || type(state) != "object") { return { running: false, job_id: null, engine: "zapret2", target: "youtube_suite", progress_pct: 0, current_index: 0, total_strategies: 0, current_strategy: null, results: [], best_strategy: null, error: null, started_at: 0, finished_at: 0 }; } if (state.running) { let is_alive = false; let pid_str = fs.readfile(PID_FILE); if (pid_str) { let pid = trim(as_string(pid_str)); if (pid != "" && match(pid, /^[0-9]+$/) != null) { is_alive = (system(sprintf("kill -0 %s >/dev/null 2>&1", pid)) == 0); } } if (!is_alive && state.job_id) { let j_dir = get_job_dir(state.job_id); if (j_dir) { let j_pid_str = fs.readfile(j_dir + "/worker.pid"); if (j_pid_str) { let j_pid = trim(as_string(j_pid_str)); if (j_pid != "" && match(j_pid, /^[0-9]+$/) != null) { is_alive = (system(sprintf("kill -0 %s >/dev/null 2>&1", j_pid)) == 0); } } } } if (!is_alive) { state.running = false; if (!state.error && state.progress_pct < 100) { state.error = "Worker process exited unexpectedly"; } if (state.finished_at == 0) { state.finished_at = clock()[0]; } save_fuzzer_state(state); } } return state; } function kill_pid_file(path) { fuzzer_runner.kill_pid_file(path); } function cleanup_temp_daemons(job_id) { if (job_id) { let job_dir = get_job_dir(job_id); if (job_dir) { kill_pid_file(job_dir + "/engine.pid"); kill_pid_file(job_dir + "/probe.pid"); } } kill_pid_file(STATE_DIR + "/fuzzer_byedpi.pid"); kill_pid_file(STATE_DIR + "/fuzzer_zapret.pid"); kill_pid_file(STATE_DIR + "/fuzzer_zapret2.pid"); kill_pid_file(STATE_DIR + "/fuzzer_probe.pid"); // Directly parse /proc/net/netfilter/nfnetlink_queue to terminate any process bound to fuzzer queues for (let w = 0; w < 5; w++) { let nfq = fs.readfile("/proc/net/netfilter/nfnetlink_queue"); let found = false; if (nfq) { let lines = split(trim(nfq), "\n"); for (let line in lines) { let cols = split(trim(line), /[ \t]+/); if (length(cols) >= 2) { let q = int(cols[0]); let p = int(cols[1]); if ((q == NFQUEUE_QNUM_ZAPRET || q == NFQUEUE_QNUM_ZAPRET2) && p > 0) { found = true; system(sprintf("kill -9 %d >/dev/null 2>&1", p)); } } } } if (!found) break; system("sleep 0.1"); } // Terminate any stray nfqws / nfqws2 / ciadpi fuzzer daemons let self_pid = fs.readlink("/proc/self"); let procs = fs.glob("/proc/[0-9]*"); if (procs) { for (let p_dir in procs) { let p_id = replace(p_dir, "/proc/", ""); if (p_id != self_pid) { let cmdline = fs.readfile(p_dir + "/cmdline"); if (cmdline && (index(cmdline, "nfqws") >= 0 || index(cmdline, "ciadpi") >= 0)) { if (index(cmdline, "qnum=298") >= 0 || index(cmdline, "qnum=299") >= 0 || index(cmdline, "11089") >= 0) { system(sprintf("kill -9 %s >/dev/null 2>&1", p_id)); } } } } } // Ensure ByeDPI port is released system(sprintf("fuser -k %d/tcp >/dev/null 2>&1", BYEDPI_PORT)); // Notice: global kill of curl processes removed to avoid killing external curl operations system("nft delete table inet tachyon_fuzzer >/dev/null 2>&1"); try { fs.unlink(STATE_DIR + "/fuzzer_daemon_err.log"); } catch (e) {} } function parse_curl_output(output, result) { result = result || {}; output = trim(as_string(output)); if (output == "") { result.success = false; result.http_code = 0; result.handshake_ms = 0; result.ttfb_ms = 0; result.speed_kbps = 0; result.data_bytes = 0; result.data_verified = false; result.dpi_verdict = "timeout"; result.score = 0; result.error = "Probe timeout or connection refused"; return result; } // In case there are multiple lines (e.g. warnings or messages), find the tab-delimited metrics line let lines = split(output, "\n"); let target_line = ""; for (let l in lines) { let tl = trim(l); if (index(tl, "\t") >= 0) { target_line = tl; break; } } if (target_line == "") target_line = trim(lines[length(lines) - 1]); let parts = split(target_line, "\t"); if (length(parts) < 4) { result.success = false; result.http_code = 0; result.score = 0; result.data_bytes = 0; result.data_verified = false; result.dpi_verdict = "malformed"; result.error = "Malformed probe metrics output"; return result; } let http_code = int(parts[0]); let appconnect = 1.0 * parts[1]; let starttransfer = 1.0 * parts[2]; let speed_bytes = 1.0 * parts[3]; let size_download = length(parts) >= 5 ? int(parts[4]) : 0; let exit_code = length(parts) >= 6 ? int(parts[5]) : 0; result.http_code = http_code; result.handshake_ms = int(appconnect * 1000.0); result.ttfb_ms = int(starttransfer * 1000.0); result.speed_kbps = int(speed_bytes / 1024.0); result.data_bytes = size_download; // Check for HTTP 400 (Server Receives Fakes - desync corruption) if (http_code == 400) { result.success = false; result.score = 0; result.data_verified = false; result.dpi_verdict = "server_fakes"; result.error = "HTTP 400 (Remote server rejected corrupted/fake packet payload)"; return result; } // Check for 16KB DPI Throttling (TSPU stream drop / connection reset after 10-28KB) if (exit_code != 0 && size_download >= 10240 && size_download <= 28672) { result.success = false; result.score = 0; result.data_verified = false; result.dpi_verdict = "throttled_16k"; result.error = sprintf("16KB DPI Data Throttle (stream killed after %d B, curl exit %d)", size_download, exit_code); return result; } if (exit_code != 0 && http_code == 0) { result.success = false; result.score = 0; result.data_verified = false; result.dpi_verdict = "dropped"; result.error = sprintf("Connection dropped by DPI (curl exit %d)", exit_code); return result; } if (exit_code != 0 && http_code >= 200 && http_code < 400) { result.success = false; result.score = 0; result.data_verified = false; result.dpi_verdict = "transfer_failed"; result.error = sprintf("Data transfer aborted after %d B (curl exit %d)", size_download, exit_code); return result; } // Any valid HTTP response from origin (including 401/403/404/405 when hitting endpoints without auth headers) if ((http_code >= 200 && http_code < 400) || http_code == 401 || http_code == 403 || http_code == 404 || http_code == 405) { result.success = true; let base_score = (http_code >= 200 && http_code < 400) ? 100 : 85; let latency_score = max(0, 1000 - result.ttfb_ms); let speed_score = int(result.speed_kbps / 10.0); let data_bonus = size_download >= 32768 ? 50 : (size_download >= 1024 ? 20 : 0); result.score = base_score + latency_score + speed_score + data_bonus; result.error = ""; result.data_verified = size_download >= 32768; result.dpi_verdict = size_download >= 32768 ? "verified_32k" : "available"; } else { result.success = false; result.score = 0; result.data_verified = false; result.dpi_verdict = "failed"; result.error = http_code > 0 ? sprintf("HTTP Status %d", http_code) : "Connection dropped by DPI"; } return result; } // ── DPI Type Detection ────────────────────────────────────────────────────── // Probes the target without any bypass to determine how it's being blocked. // Returns: { type: "rst"|"throttle"|"dns_block"|"ip_block"|"unknown"|"none", // confidence: 0-100, details: string, recommended_engines: string[] } function detect_dpi_type(target_key, custom_url) { let urls_list = resolve_target_urls_list(target_key, custom_url); let target_url = urls_list[0] ? urls_list[0].url : "https://www.google.com"; let dns_flags = get_fuzzer_curl_dns_flags(); let result = { type: "unknown", confidence: 0, details: "", recommended_engines: [], probe_metrics: { http_code: 0, handshake_ms: 0, ttfb_ms: 0, speed_kbps: 0, error: "" } }; // Direct probe with bypass of Sing-box TProxy system("nft add table inet tachyon_fuzzer 2>/dev/null"); system("nft 'add chain inet tachyon_fuzzer bypass_singbox { type route hook output priority -155 ; policy accept; }' 2>/dev/null"); system(sprintf("nft 'add rule inet tachyon_fuzzer bypass_singbox meta l4proto tcp tcp dport { 80, 443 } meta mark set meta mark | %s counter' 2>/dev/null", FUZZER_OUTBOUND_MARK)); let target_flags = get_resolved_host_flags(target_url); if (target_flags == "") target_flags = dns_flags; let curl_cmd = wrap_cmd_timeout( sprintf( "curl %s-so /dev/null -w '%%{http_code}\\t%%{time_appconnect}\\t%%{time_starttransfer}\\t%%{speed_download}\\t%%{size_download}' -L --connect-timeout 4 --max-time 6 %s 2>&1; printf '\\t%%d\\n' $?", target_flags, shell_quote(target_url) ), 8 ); let pipe = fs.popen(curl_cmd, "r"); let output = pipe ? pipe.read("all") : ""; if (pipe) pipe.close(); output = trim(output); cleanup_temp_daemons(); let metrics = {}; parse_curl_output(output, metrics); result.probe_metrics = { http_code: metrics.http_code || 0, handshake_ms: metrics.handshake_ms || 0, ttfb_ms: metrics.ttfb_ms || 0, speed_kbps: metrics.speed_kbps || 0, data_bytes: metrics.data_bytes || 0, dpi_verdict: metrics.dpi_verdict || "unknown", error: metrics.error || "" }; // Also check for DNS-level blocking let domain = target_url; let dm = match(domain, /https?:\/\/([^/]+)/); if (dm && dm[1]) domain = dm[1]; let dns_cmd = wrap_cmd_timeout(sprintf("nslookup %s 2>&1", shell_quote(domain)), 4); let dns_pipe = fs.popen(dns_cmd, "r"); let dns_out = dns_pipe ? dns_pipe.read("all") : ""; if (dns_pipe) dns_pipe.close(); let dns_blocked = false; if (index(dns_out, "NXDOMAIN") >= 0 || index(dns_out, "can't resolve") >= 0 || index(dns_out, "** server can't find") >= 0) { dns_blocked = true; } // Analyze failure patterns let http_code = metrics.http_code || 0; let handshake = metrics.handshake_ms || 0; let ttfb = metrics.ttfb_ms || 0; let error_str = metrics.error || ""; if (dns_blocked) { result.type = "dns_block"; result.confidence = 90; result.details = sprintf("DNS resolution failed for %s — likely DNS-level blocking or hijacking", domain); result.recommended_engines = ["byedpi", "zapret2"]; } else if (metrics.dpi_verdict == "throttled_16k" || (http_code == 200 && metrics.data_bytes >= 10240 && metrics.data_bytes <= 28672)) { result.type = "throttle"; result.confidence = 95; result.details = sprintf("16KB DPI throttling detected on %s — handshake succeeded but stream dropped at ~16KB data transfer", domain); result.recommended_engines = ["byedpi", "zapret2"]; } else if ((http_code == 0 && handshake == 0) && (index(error_str, "timed out") >= 0 || index(error_str, "Connection timed out") >= 0 || index(error_str, "ETIMEDOUT") >= 0)) { result.type = "ip_block"; result.confidence = 95; result.details = sprintf("TCP connect timed out before TLS handshake for %s — host is blocked at the IP layer. DPI bypass cannot unblock this; route via Sing-box VPN/Proxy outbound instead.", domain); result.recommended_engines = []; } else if (index(error_str, "Connection reset") >= 0 || index(error_str, "ECONNRESET") >= 0) { result.type = "rst"; result.confidence = 85; result.details = sprintf("TCP RST received from DPI — active TCP reset injection detected"); result.recommended_engines = ["zapret2", "zapret"]; } else if (http_code == 0 || index(error_str, "Connection refused") >= 0 || index(error_str, "ECONNREFUSED") >= 0) { result.type = "rst"; result.confidence = 70; result.details = sprintf("Connection refused — likely RST or blackhole by DPI"); result.recommended_engines = ["zapret2", "zapret"]; } else if (handshake > 2000) { result.type = "throttle"; result.confidence = 75; result.details = sprintf("Very slow TLS handshake (%dms) — likely DPI deep inspection causing delay", handshake); result.recommended_engines = ["zapret2", "zapret"]; } else if (ttfb > 3000 && http_code >= 200 && http_code < 400) { result.type = "throttle"; result.confidence = 65; result.details = sprintf("High TTFB (%dms) despite successful connection — likely bandwidth throttling", ttfb); result.recommended_engines = ["zapret2", "byedpi"]; } else if ((http_code >= 200 && http_code < 400) || (http_code >= 401 && http_code <= 405)) { result.type = "none"; result.confidence = 95; result.details = sprintf("Target accessible — no DPI blocking detected (HTTP %d, TTFB %dms)", http_code, ttfb); result.recommended_engines = []; } else { result.type = "unknown"; result.confidence = 30; result.details = sprintf("Inconclusive — HTTP %d, error: %s", http_code, error_str != "" ? error_str : "none"); result.recommended_engines = ["zapret2", "zapret", "byedpi"]; } return result; } // ── Strategy Priority Reranking (based on DPI type) ───────────────────────── function rerank_strategies_by_dpi(strategies, dpi_type) { if (!dpi_type || dpi_type.type == "none" || dpi_type.type == "unknown") return strategies; let priority_ids = []; if (dpi_type.type == "rst") { priority_ids = ["badseq", "md5sig", "multisplit", "disorder"]; } else if (dpi_type.type == "throttle") { priority_ids = ["multisplit", "seqovl", "wsize", "split2"]; } else if (dpi_type.type == "dns_block") { priority_ids = ["fake", "ttl=3", "ttl=4", "sniext"]; } if (length(priority_ids) == 0) return strategies; let scored = []; for (let s in strategies) { let score = 0; let args_lower = lc(as_string(s.args)); let name_lower = lc(as_string(s.name)); for (let pid in priority_ids) { if (index(args_lower, pid) >= 0 || index(name_lower, pid) >= 0) { score += 10; } } push(scored, { strat: s, score: score }); } for (let i = 0; i < length(scored) - 1; i++) { for (let j = i + 1; j < length(scored); j++) { if (scored[j].score > scored[i].score) { let tmp = scored[i]; scored[i] = scored[j]; scored[j] = tmp; } } } let result = []; for (let item in scored) { push(result, item.strat); } return result; } function run_probe(engine, args_str, target_key, custom_url, job_id) { cleanup_temp_daemons(job_id); if (job_id && job_id != "") { ensure_job_dir(job_id); } let job_dir = get_job_dir(job_id); let probe_pid_path = job_dir ? (job_dir + "/probe.pid") : (STATE_DIR + "/fuzzer_probe.pid"); try { fs.unlink(probe_pid_path); } catch (e) {} let urls_list = resolve_target_urls_list(target_key, custom_url); let total_urls = length(urls_list); let caps = fuzzer_runner.get_system_capabilities(); let result = { success: false, http_code: 0, handshake_ms: 0, ttfb_ms: 0, speed_kbps: 0, score: 0, error: "", sub_probes: [] }; engine = lc(as_string(engine)); let is_udp = index(args_str, "--filter-udp") >= 0 || index(args_str, "--dpi-desync-any-protocol") >= 0 || target_key == "quic_http3"; let tok_res = fuzzer_runner.tokenize_strategy_args(args_str); if (!tok_res.valid) { result.error = "Invalid strategy arguments: " + tok_res.error; return result; } if (engine == "byedpi") { let bin = get_byedpi_bin(); if (!bin) { result.error = "ByeDPI binary not found"; return result; } let pid_path = job_dir ? (job_dir + "/engine.pid") : (STATE_DIR + "/fuzzer_byedpi.pid"); let stderr_log = job_dir ? (job_dir + "/daemon_err.log") : (STATE_DIR + "/fuzzer_daemon_err.log"); try { fs.unlink(pid_path); } catch (e) {} try { fs.unlink(stderr_log); } catch (e) {} let argv = fuzzer_runner.build_byedpi_argv(bin, BYEDPI_PORT, tok_res.tokens); let spawn_cmd = "cd /tmp && " + common.command_from_args(argv) + " 2>" + shell_quote(stderr_log); system(common.background_command_with_pid(spawn_cmd, ">/dev/null", ">" + shell_quote(pid_path))); let pid_running = false; for (let wait_i = 0; wait_i < 15; wait_i++) { system("sleep 0.1"); let pid_str = fs.readfile(pid_path); if (pid_str) { let pid = trim(as_string(pid_str)); if (pid != "" && match(pid, /^[0-9]+$/) != null && system(sprintf("kill -0 %s >/dev/null 2>&1", pid)) == 0) { pid_running = true; break; } } } if (!pid_running) { let err_content = fs.readfile(stderr_log); let err_msg = err_content ? trim(as_string(err_content)) : ""; if (err_msg != "") { let first_line = split(err_msg, "\n")[0]; result.error = sprintf("Daemon failed to start: %s", first_line); } else { result.error = "ByeDPI daemon failed to start (invalid arguments)"; } cleanup_temp_daemons(job_id); return result; } // Ensure ciadpi direct outbound connections bypass Sing-Box TProxy system("nft add table inet tachyon_fuzzer 2>/dev/null"); system("nft 'add chain inet tachyon_fuzzer bypass_singbox { type route hook output priority -155 ; policy accept; }' 2>/dev/null"); system(sprintf("nft 'add rule inet tachyon_fuzzer bypass_singbox meta l4proto tcp tcp dport { 80, 443 } meta mark set meta mark | %s counter' 2>/dev/null", FUZZER_OUTBOUND_MARK)); let passed_count = 0; let max_speed = 0; let sum_data_bytes = 0; let all_data_verified = true; let last_http = 0; let last_dpi_verdict = "available"; let required_failed = false; for (let target_item in urls_list) { let is_req = (target_item.required !== false); let p_kind = target_item.probe_kind || "tls_http"; let extra_flags = ""; if (p_kind == "quic" || target_key == "quic_http3") { if (!caps.http3) { let single_res = { target_name: target_item.name, url: target_item.url, required: is_req, weight: target_item.weight || 100, http_code: 0, handshake_ms: 0, ttfb_ms: 0, speed_kbps: 0, data_bytes: 0, data_verified: false, dpi_verdict: "unsupported_proto", score: 0, success: false, error: "HTTP/3 (QUIC) not supported by router curl binary" }; push(result.sub_probes, single_res); if (is_req) { required_failed = true; result.error = single_res.error; } break; } extra_flags = "--http3-only "; } else if (p_kind == "streaming") { extra_flags = "-r 0-65535 "; } let curl_cmd = wrap_cmd_timeout( sprintf( "curl %s-x socks5h://127.0.0.1:%d -so /dev/null -w '%%{http_code}\\t%%{time_appconnect}\\t%%{time_starttransfer}\\t%%{speed_download}\\t%%{size_download}' -L --connect-timeout 4 --max-time 6 %s 2>/dev/null; printf '\\t%%d\\n' $?", extra_flags, BYEDPI_PORT, shell_quote(target_item.url) ), 8, probe_pid_path ); let pipe = fs.popen(curl_cmd, "r"); let output = pipe ? pipe.read("all") : ""; if (pipe) pipe.close(); try { fs.unlink(probe_pid_path); } catch (e) {} let single_res = parse_curl_output(output, {}); single_res.target_name = target_item.name; single_res.url = target_item.url; single_res.required = is_req; single_res.weight = target_item.weight || 100; push(result.sub_probes, single_res); if (single_res.success) { passed_count++; sum_data_bytes += single_res.data_bytes || 0; if (!single_res.data_verified) all_data_verified = false; if (single_res.speed_kbps > max_speed) max_speed = single_res.speed_kbps; last_http = single_res.http_code; last_dpi_verdict = single_res.dpi_verdict || "available"; } else { all_data_verified = false; if (last_http == 0) last_http = single_res.http_code; if (single_res.error && result.error == "") result.error = single_res.error; last_dpi_verdict = single_res.dpi_verdict || "failed"; if (is_req) { required_failed = true; break; } } } cleanup_temp_daemons(job_id); if (required_failed || passed_count == 0) { result.success = false; result.http_code = last_http; result.data_bytes = sum_data_bytes; result.data_verified = false; result.dpi_verdict = last_dpi_verdict; result.score = 0; if (result.error == "") { result.error = sprintf("Required endpoint failed (%d of %d endpoints passed)", passed_count, total_urls); } } else { result.success = true; result.http_code = last_http > 0 ? last_http : 200; result.speed_kbps = max_speed; result.data_bytes = int(sum_data_bytes / (1.0 * total_urls)); result.data_verified = all_data_verified; result.dpi_verdict = all_data_verified ? "verified_32k" : last_dpi_verdict; result.error = ""; let total_w = 0; let weighted_score = 0.0; let weighted_ttfb = 0.0; let weighted_hs = 0.0; for (let sp in result.sub_probes) { let w = sp.weight || 10; total_w += w; weighted_score += (sp.score * w); weighted_ttfb += (sp.ttfb_ms * w); weighted_hs += (sp.handshake_ms * w); } result.score = total_w > 0 ? int(weighted_score / (1.0 * total_w)) : 0; result.ttfb_ms = total_w > 0 ? int(weighted_ttfb / (1.0 * total_w)) : 0; result.handshake_ms = total_w > 0 ? int(weighted_hs / (1.0 * total_w)) : 0; } return result; } if (engine == "zapret" || engine == "zapret2") { cleanup_temp_daemons(job_id); let is_z2 = engine == "zapret2"; let bin = is_z2 ? get_zapret2_bin() : get_zapret_bin(); let qnum = is_z2 ? NFQUEUE_QNUM_ZAPRET2 : NFQUEUE_QNUM_ZAPRET; let pid_path = job_dir ? (job_dir + "/engine.pid") : (is_z2 ? (STATE_DIR + "/fuzzer_zapret2.pid") : (STATE_DIR + "/fuzzer_zapret.pid")); let stderr_log = job_dir ? (job_dir + "/daemon_err.log") : (STATE_DIR + "/fuzzer_daemon_err.log"); try { fs.unlink(pid_path); } catch (e) {} try { fs.unlink(stderr_log); } catch (e) {} if (!bin) { result.error = (is_z2 ? "Zapret v2" : "Zapret v1") + " binary not found"; return result; } let lua_init_flags = ""; let blob_flags = ""; if (is_z2) { lua_init_flags = get_zapret2_lua_flags(args_str); blob_flags = resolve_zapret2_blobs(args_str); if (index(args_str, "--lua-desync") >= 0 && lua_init_flags == "" && index(args_str, "--lua-init") < 0) { result.error = "Missing Zapret2 Lua library: zapret-antidpi.lua not found in /opt/zapret2/lua or system paths"; cleanup_temp_daemons(job_id); return result; } } let filter_prefix = ""; if (is_z2 && index(args_str, "--filter-tcp") < 0 && index(args_str, "--filter-l7") < 0) { filter_prefix = "--filter-tcp=443 --filter-l7=tls --payload=tls_client_hello "; } if (is_z2 && is_udp && index(args_str, "--filter-udp") < 0) { filter_prefix += "--filter-udp=443 --payload=quic_initial "; } let fwmark_flag = ""; if (is_z2) { if (index(args_str, "--fwmark") < 0) fwmark_flag = sprintf("--fwmark=%s ", FUZZER_FWMARK); } else { if (index(args_str, "--dpi-desync-fwmark") < 0) fwmark_flag = sprintf("--dpi-desync-fwmark=%s ", FUZZER_FWMARK); } let argv = fuzzer_runner.build_zapret_argv(bin, qnum, fwmark_flag, lua_init_flags, blob_flags, filter_prefix, tok_res.tokens); let spawn_cmd = "cd /tmp && " + common.command_from_args(argv) + " 2>" + shell_quote(stderr_log); system(common.background_command_with_pid(spawn_cmd, ">/dev/null", ">" + shell_quote(pid_path))); let pid_running = false; for (let wait_i = 0; wait_i < 15; wait_i++) { system("sleep 0.1"); let pid_str = fs.readfile(pid_path); if (pid_str) { let pid = trim(as_string(pid_str)); if (pid != "" && match(pid, /^[0-9]+$/) != null && system(sprintf("kill -0 %s >/dev/null 2>&1", pid)) == 0) { pid_running = true; break; } } } if (!pid_running) { let err_content = fs.readfile(stderr_log); let err_msg = err_content ? trim(as_string(err_content)) : ""; if (err_msg != "") { let lines = split(err_msg, "\n"); let err_line = ""; for (let i = length(lines) - 1; i >= 0; i--) { let l = trim(lines[i]); if (l == "") continue; if (index(l, "version") < 0 && index(l, "Running as") < 0 && index(l, "LUA v") < 0 && index(l, "JIT:") < 0 && index(l, "we have") < 0 && index(l, "initializing") < 0 && index(l, "opening nfq") < 0 && index(l, "unbinding") < 0 && index(l, "binding") < 0 && index(l, "setting copy") < 0 && index(l, "chdir") < 0) { err_line = l; break; } } if (err_line == "") err_line = split(err_msg, "\n")[0]; result.error = sprintf("Daemon failed to start: %s", err_line); } else { result.error = sprintf("Daemon %s failed to start (invalid arguments or missing Lua library)", is_z2 ? "nfqws2" : "nfqws"); } cleanup_temp_daemons(job_id); return result; } setup_fuzzer_direct_nftables(qnum, is_udp); let passed_count = 0; let max_speed = 0; let sum_data_bytes = 0; let all_data_verified = true; let last_http = 0; let last_dpi_verdict = "available"; let dns_flags = get_fuzzer_curl_dns_flags(); let required_failed = false; for (let target_item in urls_list) { let is_req = (target_item.required !== false); let p_kind = target_item.probe_kind || "tls_http"; let extra_flags = ""; if (p_kind == "quic" || target_key == "quic_http3") { if (!caps.http3) { let single_res = { target_name: target_item.name, url: target_item.url, required: is_req, weight: target_item.weight || 100, http_code: 0, handshake_ms: 0, ttfb_ms: 0, speed_kbps: 0, data_bytes: 0, data_verified: false, dpi_verdict: "unsupported_proto", score: 0, success: false, error: "HTTP/3 (QUIC) not supported by router curl binary" }; push(result.sub_probes, single_res); if (is_req) { required_failed = true; result.error = single_res.error; } break; } extra_flags = "--http3-only "; } else if (p_kind == "streaming") { extra_flags = "-r 0-65535 "; } let target_flags = get_resolved_host_flags(target_item.url); if (target_flags == "") target_flags = dns_flags; let curl_cmd = wrap_cmd_timeout( sprintf( "curl %s%s-so /dev/null -w '%%{http_code}\\t%%{time_appconnect}\\t%%{time_starttransfer}\\t%%{speed_download}\\t%%{size_download}' -L --connect-timeout 4 --max-time 6 %s 2>/dev/null; printf '\\t%%d\\n' $?", extra_flags, target_flags, shell_quote(target_item.url) ), 8, probe_pid_path ); let pipe = fs.popen(curl_cmd, "r"); let output = pipe ? pipe.read("all") : ""; if (pipe) pipe.close(); try { fs.unlink(probe_pid_path); } catch (e) {} let single_res = parse_curl_output(output, {}); single_res.target_name = target_item.name; single_res.url = target_item.url; single_res.required = is_req; single_res.weight = target_item.weight || 100; push(result.sub_probes, single_res); if (single_res.success) { passed_count++; sum_data_bytes += single_res.data_bytes || 0; if (!single_res.data_verified) all_data_verified = false; if (single_res.speed_kbps > max_speed) max_speed = single_res.speed_kbps; last_http = single_res.http_code; last_dpi_verdict = single_res.dpi_verdict || "available"; } else { all_data_verified = false; if (last_http == 0) last_http = single_res.http_code; if (single_res.error && result.error == "") result.error = single_res.error; last_dpi_verdict = single_res.dpi_verdict || "failed"; if (is_req) { required_failed = true; break; } } } cleanup_temp_daemons(job_id); if (required_failed || passed_count == 0) { result.success = false; result.http_code = last_http; result.data_bytes = sum_data_bytes; result.data_verified = false; result.dpi_verdict = last_dpi_verdict; result.score = 0; if (result.error == "") { result.error = sprintf("Required endpoint failed (%d of %d endpoints passed)", passed_count, total_urls); } } else { result.success = true; result.http_code = last_http > 0 ? last_http : 200; result.speed_kbps = max_speed; result.data_bytes = int(sum_data_bytes / (1.0 * total_urls)); result.data_verified = all_data_verified; result.dpi_verdict = all_data_verified ? "verified_32k" : last_dpi_verdict; result.error = ""; let total_w = 0; let weighted_score = 0.0; let weighted_ttfb = 0.0; let weighted_hs = 0.0; for (let sp in result.sub_probes) { let w = sp.weight || 10; total_w += w; weighted_score += (sp.score * w); weighted_ttfb += (sp.ttfb_ms * w); weighted_hs += (sp.handshake_ms * w); } result.score = total_w > 0 ? int(weighted_score / (1.0 * total_w)) : 0; result.ttfb_ms = total_w > 0 ? int(weighted_ttfb / (1.0 * total_w)) : 0; result.handshake_ms = total_w > 0 ? int(weighted_hs / (1.0 * total_w)) : 0; } return result; } result.error = "Unknown engine: " + engine; return result; } function run_fuzzer_worker(engine, target, custom_url, rule_section, custom_file, mode, job_id) { if (job_id && job_id != "") { ensure_job_dir(job_id); } let target_url = resolve_target_url(target, custom_url); let state = get_fuzzer_state(); if (!state.running || (job_id && state.job_id != job_id)) { state = { running: true, job_id: job_id || sprintf("fuzz_%d", clock()[0]), engine, target, target_url, mode: as_string(mode || "presets"), rule_section: as_string(rule_section), custom_file: as_string(custom_file || ""), progress_pct: 0, current_index: 0, total_strategies: 0, current_strategy: { name: "Initializing DPI detection...", args: "" }, results: [], best_strategy: null, error: null, aborted: false, started_at: clock()[0], finished_at: 0, dpi_detection: null, phase: "detecting_dpi", stage: 1 }; save_fuzzer_state(state); } if (custom_url && custom_url != "" && !fuzzer_runner.is_valid_url(custom_url)) { state.running = false; state.error = "Invalid custom URL: malformed or forbidden characters"; state.finished_at = clock()[0]; save_fuzzer_state(state); cleanup_temp_daemons(state.job_id); return; } // ── Pre-fuzz DPI detection ──────────────────────────────────────────── let dpi_detection = detect_dpi_type(target, custom_url); state.dpi_detection = dpi_detection; state.phase = "exploration"; state.stage = 1; save_fuzzer_state(state); let strategies = null; if (custom_file && custom_file != "" && fs.stat(custom_file) != null) { strategies = common.read_json_file(custom_file); } if (!strategies || type(strategies) != "array" || length(strategies) == 0) { strategies = get_strategies_for_engine(engine, mode, target); } // Fail-closed re-validation of all candidate strategies before benchmarking let validated_strategies = []; for (let s in strategies) { if (s && s.args && fuzzer_runner.validate_strategy_args(s.engine || engine, s.args)) { push(validated_strategies, s); } } strategies = validated_strategies; if (length(strategies) == 0) { state.running = false; state.error = "No valid strategies found to benchmark"; state.finished_at = clock()[0]; save_fuzzer_state(state); cleanup_temp_daemons(state.job_id); return; } // Rerank strategies based on detected DPI type strategies = rerank_strategies_by_dpi(strategies, dpi_detection); let total = length(strategies); state.total_strategies = total; save_fuzzer_state(state); try { let highest_score = -1; let best = null; let working_count = 0; let consecutive_plateau = 0; // ── Stage 1: Exploration (Single-probe scan) ────────────────────── for (let i = 0; i < total; i++) { let strat = strategies[i]; state.current_index = i + 1; state.current_strategy = strat; state.progress_pct = int(((i) / (1.0 * total)) * 70.0); save_fuzzer_state(state); let probe = null; try { probe = run_probe(strat.engine || engine, strat.args, target, custom_url, state.job_id); } catch (err) { cleanup_temp_daemons(state.job_id); probe = { success: false, http_code: 0, handshake_ms: 0, ttfb_ms: 0, speed_kbps: 0, data_bytes: 0, data_verified: false, dpi_verdict: "failed", score: 0, error: sprintf("Probe error: %s", err), sub_probes: [] }; } let item_result = { id: strat.id || sprintf("strat_%d", i + 1), name: strat.name || sprintf("Strategy %d", i + 1), engine: strat.engine || engine, args: strat.args, description: strat.description || "", rationale: strat.rationale || "", success: probe.success, http_code: probe.http_code, handshake_ms: probe.handshake_ms, ttfb_ms: probe.ttfb_ms, speed_kbps: probe.speed_kbps, data_bytes: probe.data_bytes || 0, data_verified: probe.data_verified || false, dpi_verdict: probe.dpi_verdict || "unknown", score: probe.score, error: probe.error, sub_probes: probe.sub_probes || [], stability_pct: probe.success ? 100 : 0, reps: 1, jitter_ms: 0, confidence: probe.success ? "preliminary" : "none", badge: "" }; if (item_result.success) { working_count++; if (item_result.score > highest_score) { highest_score = item_result.score; best = item_result; consecutive_plateau = 0; } else { consecutive_plateau++; } } else if (working_count > 0) { consecutive_plateau++; } push(state.results, item_result); state.progress_pct = int(((i + 1) / (1.0 * total)) * 70.0); save_fuzzer_state(state); // Adaptive mode early plateau detection if (mode == "adaptive" && consecutive_plateau >= 8 && working_count >= 2) { break; } } // ── Stage 2: Verification (3 Repetitions on Top Candidates) ──────── let working_candidates = []; for (let r in state.results) { if (r && r.success === true) push(working_candidates, r); } sort(working_candidates, function(a, b) { return b.score - a.score; }); let avail_kb = fuzzer_runner.get_system_memory_kb(); let max_verify = (avail_kb < 32768) ? 3 : 5; let num_verify = length(working_candidates) < max_verify ? length(working_candidates) : max_verify; if (num_verify > 0) { state.phase = "verification"; state.stage = 2; save_fuzzer_state(state); for (let v_idx = 0; v_idx < num_verify; v_idx++) { let cand = working_candidates[v_idx]; state.current_strategy = { name: sprintf("[Stage 2 Verification %d/%d] %s", v_idx + 1, num_verify, cand.name), args: cand.args }; state.progress_pct = 70 + int(((v_idx) / (1.0 * num_verify)) * 30.0); save_fuzzer_state(state); let rep_ttfb = []; let rep_speed = []; let rep_handshake = []; let rep_bytes = []; let rep_success = 0; for (let rep = 0; rep < 3; rep++) { let p = null; try { p = run_probe(cand.engine || engine, cand.args, target, custom_url, state.job_id); } catch (e) { cleanup_temp_daemons(state.job_id); } if (p && p.success) { rep_success++; push(rep_ttfb, p.ttfb_ms); push(rep_speed, p.speed_kbps); push(rep_handshake, p.handshake_ms); push(rep_bytes, p.data_bytes || 0); } } let stability_pct = int((rep_success / 3.0) * 100); cand.verified = true; cand.reps = 3; cand.stability_pct = stability_pct; if (rep_success > 0) { let med_ttfb = fuzzer_runner.calculate_median(rep_ttfb); let jitter_ms = fuzzer_runner.calculate_jitter(rep_ttfb, med_ttfb); let p25_speed = fuzzer_runner.calculate_p25(rep_speed); let med_bytes = fuzzer_runner.calculate_median(rep_bytes); let data_verified = (med_bytes >= 32768); cand.ttfb_ms = med_ttfb; cand.jitter_ms = jitter_ms; cand.speed_kbps = fuzzer_runner.calculate_median(rep_speed); cand.p25_speed_kbps = p25_speed; cand.data_bytes = med_bytes; cand.data_verified = data_verified; let conf = "low"; if (stability_pct == 100 && jitter_ms <= 80) conf = "high"; else if (stability_pct >= 66 && jitter_ms <= 200) conf = "medium"; cand.confidence = conf; // Composite Stage 2 Score: Stability (0-400) + Latency (0-300) + Speed p25 (0-150) + Data (20-50) cand.score = int((stability_pct * 4.0) + (max(0, 1000 - med_ttfb) * 0.3) + (min(500, int(p25_speed / 10.0)) * 0.3) + (data_verified ? 50 : 20)); } else { cand.score = 0; cand.success = false; cand.confidence = "low"; cand.jitter_ms = 0; cand.p25_speed_kbps = 0; cand.error = "Failed all 3 verification repetitions (unstable connection)"; } for (let r_i = 0; r_i < length(state.results); r_i++) { if (state.results[r_i].id == cand.id) { state.results[r_i] = cand; break; } } save_fuzzer_state(state); } } // ── Assign Badges based on verified results ──────────────────────── let best_verified = null; let highest_vscore = -1; for (let r in state.results) { if (r.success && r.score > highest_vscore) { highest_vscore = r.score; best_verified = r; } } if (best_verified) { best_verified.badge = "🏆 Best Match"; state.best_strategy = best_verified; } let min_ttfb = 999999; let fastest = null; let lowest_jitter = 999999; let most_stable = null; for (let r in state.results) { if (r.success && r.stability_pct == 100) { if (r.ttfb_ms > 0 && r.ttfb_ms < min_ttfb) { min_ttfb = r.ttfb_ms; fastest = r; } if (r.jitter_ms !== null && r.jitter_ms < lowest_jitter) { lowest_jitter = r.jitter_ms; most_stable = r; } } } if (fastest && fastest.id != (best_verified ? best_verified.id : "")) { fastest.badge = "⚡ Ultra Fast"; } if (most_stable && most_stable.id != (best_verified ? best_verified.id : "") && (!fastest || most_stable.id != fastest.id)) { most_stable.badge = "🛡️ Bulletproof"; } state.running = false; state.stage = 2; state.phase = "finished"; state.current_strategy = null; state.progress_pct = 100; state.finished_at = clock()[0]; save_fuzzer_state(state); // ── Persist to history ──────────────────────────────────────────── let duration = state.finished_at - state.started_at; append_history({ timestamp: state.finished_at, engine: engine, target: target, mode: mode, best_strategy: state.best_strategy ? { id: state.best_strategy.id, name: state.best_strategy.name, engine: state.best_strategy.engine, args: state.best_strategy.args, score: state.best_strategy.score, ttfb_ms: state.best_strategy.ttfb_ms, speed_kbps: state.best_strategy.speed_kbps, stability_pct: state.best_strategy.stability_pct, confidence: state.best_strategy.confidence } : null, total_tested: total, working_count: working_count, dpi_detection: dpi_detection, duration_sec: int(duration) }); } catch (err) { state.running = false; state.phase = "finished"; state.current_strategy = null; state.error = as_string(err); state.finished_at = clock()[0]; if (!state.best_strategy && state.results) { let max_score = -1; let best_item = null; for (let r in state.results) { if (r.success && r.score > max_score) { max_score = r.score; best_item = r; } } if (best_item) { best_item.badge = "🏆 Best Match"; state.best_strategy = best_item; } } save_fuzzer_state(state); } cleanup_temp_daemons(state.job_id); } function stop_fuzzer() { let state = get_fuzzer_state(); let job_id = state ? state.job_id : null; let job_dir = get_job_dir(job_id); if (job_dir) { kill_pid_file(job_dir + "/worker.pid"); } kill_pid_file(PID_FILE); cleanup_temp_daemons(job_id); state.running = false; state.aborted = true; state.phase = "finished"; state.current_strategy = null; state.error = "Stopped by user"; state.finished_at = clock()[0]; if (!state.best_strategy && state.results) { let max_score = -1; let best_item = null; for (let r in state.results) { if (r.success && r.score > max_score) { max_score = r.score; best_item = r; } } if (best_item) { best_item.badge = "🏆 Best Match"; state.best_strategy = best_item; } } save_fuzzer_state(state); print(sprintf("%J\n", { success: true, message: "Fuzzer stopped" })); } function start_fuzzer(engine, target, custom_url, rule_section, custom_file, mode) { let current = get_fuzzer_state(); if (current.running) { stop_fuzzer(); system("sleep 0.25"); } if (custom_url && custom_url != "" && !fuzzer_runner.is_valid_url(custom_url)) { print(sprintf("%J\n", { success: false, error: "Invalid custom URL: malformed or forbidden characters" })); return; } ensure_state_dir(); let job_id = sprintf("fuzz_%d", clock()[0]); ensure_job_dir(job_id); cleanup_temp_daemons(job_id); // Immediately write starting state to prevent race conditions during frontend polling let state = { running: true, job_id: job_id, engine: engine || "zapret2", target: target || "youtube_suite", target_url: resolve_target_url(target, custom_url), mode: as_string(mode || "presets"), rule_section: as_string(rule_section), custom_file: as_string(custom_file || ""), progress_pct: 0, current_index: 0, total_strategies: 0, current_strategy: { name: "Initializing DPI detection...", args: "" }, results: [], best_strategy: null, error: null, aborted: false, started_at: clock()[0], finished_at: 0, dpi_detection: null, phase: "detecting_dpi", stage: 1 }; save_fuzzer_state(state); let fuzzer_bin = LIB_DIR + "/diagnostics/fuzzer.uc"; if (fs.stat(fuzzer_bin) == null) fuzzer_bin = "/usr/lib/tachyon/diagnostics/fuzzer.uc"; let cmd = sprintf( "ucode -L %s %s worker %s %s %s %s %s %s %s", shell_quote(LIB_DIR), shell_quote(fuzzer_bin), shell_quote(engine || "zapret2"), shell_quote(target || "youtube_suite"), shell_quote(custom_url || ""), shell_quote(rule_section || ""), shell_quote(custom_file || ""), shell_quote(mode || "presets"), shell_quote(job_id) ); let job_worker_pid = get_job_dir(job_id) + "/worker.pid"; system(common.background_command_with_pid(cmd, ">/dev/null", ">" + shell_quote(PID_FILE) + " && cp " + shell_quote(PID_FILE) + " " + shell_quote(job_worker_pid) + " 2>/dev/null")); print(sprintf("%J\n", { success: true, job_id, engine: engine || "zapret2", target: target || "youtube_suite", mode: mode || "presets" })); } function get_available_engines() { return { zapret2: get_zapret2_bin() != null, zapret: get_zapret_bin() != null, byedpi: get_byedpi_bin() != null }; } function normalize_strategy_for_uci(engine, args_val) { args_val = trim(as_string(args_val)); if (engine == "zapret2") { let blob_defs = resolve_zapret2_blobs(args_val); if (blob_defs != "") { args_val = trim(blob_defs) + " " + args_val; } } return args_val; } function apply_strategy(engine, args_val, target_rule) { engine = lc(as_string(engine)); args_val = trim(as_string(args_val)); target_rule = trim(as_string(target_rule)); if (args_val == "") { print(sprintf("%J\n", { success: false, error: "Empty strategy arguments" })); return; } if (!fuzzer_runner.validate_strategy_args(engine, args_val)) { print(sprintf("%J\n", { success: false, error: "Cannot apply invalid or insecure strategy arguments" })); return; } args_val = normalize_strategy_for_uci(engine, args_val); let uci = uci_core.cursor(); let applied = false; if (target_rule != "" && target_rule != "global") { uci.set(CONFIG_NAME, target_rule, "action", engine); if (engine == "zapret2") uci.set(CONFIG_NAME, target_rule, "nfqws2_opt", args_val); else if (engine == "zapret") uci.set(CONFIG_NAME, target_rule, "nfqws_opt", args_val); else if (engine == "byedpi") uci.set(CONFIG_NAME, target_rule, "byedpi_cmd_opts", args_val); applied = true; } else { let provider_sec = engine; let sec_obj = uci.get_all(CONFIG_NAME, provider_sec); if (sec_obj == null) { uci.set(CONFIG_NAME, provider_sec, "provider"); } uci.set(CONFIG_NAME, provider_sec, "enabled", "1"); if (engine == "zapret2") uci.set(CONFIG_NAME, provider_sec, "nfqws2_opt", args_val); else if (engine == "zapret") uci.set(CONFIG_NAME, provider_sec, "nfqws_opt", args_val); else if (engine == "byedpi") uci.set(CONFIG_NAME, provider_sec, "byedpi_cmd_opts", args_val); applied = true; } uci.commit(CONFIG_NAME); system(common.background_command("tachyon reload")); print(sprintf("%J\n", { success: true, engine, applied_to: target_rule != "" ? target_rule : "global", args: args_val })); } function auto_apply_best(target_rule) { let state = get_fuzzer_state(); if (state.aborted) { print(sprintf("%J\n", { success: false, error: "Cannot auto-apply: benchmark was stopped manually" })); return; } if (state.progress_pct < 100) { print(sprintf("%J\n", { success: false, error: "Cannot auto-apply: benchmark did not complete 100%" })); return; } if (!state.best_strategy || state.best_strategy.score <= 0) { print(sprintf("%J\n", { success: false, error: "No winning strategy found — run a benchmark first" })); return; } let best = state.best_strategy; apply_strategy(best.engine, best.args, target_rule); } function clear_history() { save_history({ entries: [] }); print(sprintf("%J\n", { success: true, message: "Fuzzer history cleared" })); } // CLI Dispatcher let op = ARGV[0] || "status"; if (op == "start") { start_fuzzer(ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6]); } else if (op == "worker") { run_fuzzer_worker(ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6], ARGV[7]); } else if (op == "status") { print(sprintf("%J\n", get_fuzzer_state())); } else if (op == "stop") { stop_fuzzer(); } else if (op == "apply") { apply_strategy(ARGV[1], ARGV[2], ARGV[3]); } else if (op == "get_patterns" || op == "patterns") { print(sprintf("%J\n", { success: true, patterns: get_patterns_config() })); } else if (op == "save_patterns") { let cfg = safe_json_parse(ARGV[1]); save_patterns_config(cfg); } else if (op == "reset_patterns") { reset_patterns_config(); } else if (op == "ai_synthesize" || op == "synthesize") { synthesize_ai_strategies(ARGV[1], ARGV[2], ARGV[3], ARGV[4]); } else if (op == "detect_dpi") { let detection = detect_dpi_type(ARGV[1], ARGV[2]); print(sprintf("%J\n", detection)); } else if (op == "auto_apply") { auto_apply_best(ARGV[1]); } else if (op == "history") { let entries = get_history(ARGV[1]); print(sprintf("%J\n", { success: true, entries: entries })); } else if (op == "clear_history") { clear_history(); } else if (op == "generate" || op == "strategies_generate") { print(sprintf("%J\n", get_strategies_for_engine(ARGV[1], ARGV[2] || "combinatorial"))); } else if (op == "strategies") { let strat_mode = ARGV[1] || "presets"; print(sprintf("%J\n", { available_engines: get_available_engines(), target_suites: TARGET_SUITES, patterns: get_patterns_config(), zapret2: get_strategies_for_engine("zapret2", strat_mode), zapret: get_strategies_for_engine("zapret", strat_mode), byedpi: get_strategies_for_engine("byedpi", strat_mode) })); } else if (op == "probe") { let r = run_probe(ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5]); print(sprintf("%J\n", r)); } else { warn("Usage: fuzzer.uc [start|status|stop|apply|strategies|generate|get_patterns|save_patterns|reset_patterns|ai_synthesize|detect_dpi|auto_apply|history|clear_history|worker|probe] ...\n"); exit(1); }