Files
NeoTachyon/fe-app-tachyon/src/tachyon/tabs/diagnostic/partials/renderStrategyFuzzerModal.ts
T
Dushnilin 603c0df91b feat(security,ci,ui): harden CI/CD, LuCI ACL, low-space updates and mobile layout
- ci: make frontend CI read-only with strict diff check and deterministic calls.json
- ci: pin external GitHub Actions in workflows to immutable commit SHAs
- ci: add openwrt-e2e blocking gate job running docker_e2e_test.sh
- fix(diagnostic): fix contstants.ts typo and update all 13 import sites
- fix(acl): remove unused /bin/busybox exec from rpcd ACL and add regression test
- feat(updates): add low-space update fallback when creating sing-box.old is impossible
- fix(routes): preserve dedicated Discord gateway subnets (162.159.128.0/21)
- feat(ui): implement responsive auto-fit grid and mobile modal viewport bounds
- test: add viewport regression test suite in vitest
2026-09-14 23:00:18 +03:00

2059 lines
65 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { TachyonShellMethods } from '../../../methods';
import { renderButton } from '../../../../partials';
import { showToast } from '../../../../helpers/showToast';
import { Tachyon } from '../../../types';
export function renderStrategyFuzzerModal(ruleNames: string[] = []) {
let pollingInterval: ReturnType<typeof setInterval> | null = null;
let isPolling = false;
// Modal State
let activeTab: 'benchmark' | 'patterns' | 'custom' | 'ai' | 'history' =
'benchmark';
let selectedEngine: Tachyon.FuzzerEngine = 'zapret2';
let selectedTarget: Tachyon.FuzzerTarget = 'youtube_suite';
let customUrl = '';
let selectedRuleSection = '';
let selectedMode: Tachyon.FuzzerMode = 'presets';
let isRunning = false;
let currentState: Tachyon.FuzzerState | null = null;
let resultFilter: 'all' | 'success' | 'fast' = 'all';
let autoApplyEnabled = false;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let currentDpiDetection: Tachyon.FuzzerDpiDetection | null = null;
// Patterns Config State
let patternsConfig: Tachyon.FuzzerPatternsConfig = {
zapret2: {
splits: ['1', '2', '3', 'midsld', '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'],
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: [],
};
const modalContainer = E('div', {
class: 'tachyon_fuzzer_modal',
style:
'display: flex; flex-direction: column; gap: 14px; width: 100%; box-sizing: border-box;',
});
// ── Tab Bar Navigation ────────────────────────────────────────────────────
const tabButtons: Record<string, HTMLElement> = {};
const createTabButton = (
id: 'benchmark' | 'patterns' | 'custom' | 'ai' | 'history',
icon: string,
label: string,
) => {
const btn = E(
'button',
{
type: 'button',
class: `cbi-button ${activeTab === id ? 'cbi-button-action' : 'cbi-button-neutral'}`,
style:
'display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; font-size: 12px; font-weight: 500; border-radius: 6px; cursor: pointer;',
},
[E('span', {}, icon), E('span', {}, label)],
);
btn.addEventListener('click', () => {
activeTab = id;
updateTabVisibility();
});
tabButtons[id] = btn;
return btn;
};
const tabBar = E(
'div',
{
style:
'display: flex; gap: 8px; border-bottom: 1px solid var(--border-color, rgba(255,255,255,0.12)); padding-bottom: 10px; flex-wrap: wrap;',
},
[
createTabButton('benchmark', '⚡', _('Benchmark & Test')),
createTabButton('patterns', '🛠️', _('Pattern Builder')),
createTabButton('custom', '➕', _('My Strategies')),
createTabButton('ai', '🧠', _('AI Doctor RAG')),
createTabButton('history', '📋', _('History')),
],
);
const tabContentBenchmark = E('div', {
style: 'display: flex; flex-direction: column; gap: 14px;',
});
const tabContentPatterns = E('div', {
style: 'display: none; flex-direction: column; gap: 14px;',
});
const tabContentCustom = E('div', {
style: 'display: none; flex-direction: column; gap: 14px;',
});
const tabContentAi = E('div', {
style: 'display: none; flex-direction: column; gap: 14px;',
});
const tabContentHistory = E('div', {
style: 'display: none; flex-direction: column; gap: 14px;',
});
const updateTabVisibility = () => {
for (const key in tabButtons) {
tabButtons[key].className =
`cbi-button ${activeTab === key ? 'cbi-button-action' : 'cbi-button-neutral'}`;
}
tabContentBenchmark.style.display =
activeTab === 'benchmark' ? 'flex' : 'none';
tabContentPatterns.style.display =
activeTab === 'patterns' ? 'flex' : 'none';
tabContentCustom.style.display = activeTab === 'custom' ? 'flex' : 'none';
tabContentAi.style.display = activeTab === 'ai' ? 'flex' : 'none';
tabContentHistory.style.display = activeTab === 'history' ? 'flex' : 'none';
if (activeTab === 'patterns') renderPatternsTab();
if (activeTab === 'custom') renderCustomTab();
if (activeTab === 'history') renderHistoryTab();
};
// ═════════════════════════════════════════════════════════════════════════════
// TAB 1: BENCHMARK & RUN
// ═════════════════════════════════════════════════════════════════════════════
const controlsGrid = E('div', {
style:
'display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)); gap: 10px; align-items: end;',
});
// 1. Engine Select
const engineSelect = E(
'select',
{ class: 'cbi-input-select', style: 'width: 100%;' },
[
E('option', { value: 'zapret2' }, _('Zapret v2 (nfqws2)')),
E('option', { value: 'zapret' }, _('Zapret v1 (nfqws)')),
E('option', { value: 'byedpi' }, _('ByeDPI (ciadpi)')),
E('option', { value: 'all' }, _('All Engines (Full Matrix)')),
],
);
engineSelect.addEventListener('change', () => {
selectedEngine = (engineSelect as HTMLSelectElement)
.value as Tachyon.FuzzerEngine;
});
const engineGroup = E(
'div',
{ style: 'display: flex; flex-direction: column; gap: 4px;' },
[
E(
'label',
{ style: 'font-size: 11px; font-weight: 600; opacity: 0.85;' },
_('DPI Engine'),
),
engineSelect,
],
);
// 2. Target Preset Select
const targetSelect = E(
'select',
{ class: 'cbi-input-select', style: 'width: 100%;' },
[
E(
'option',
{ value: 'youtube_suite', selected: true },
_('🎬 YouTube Full Suite (Web + 4K Stream + CDN)'),
),
E(
'option',
{ value: 'discord_suite' },
_('💬 Discord Suite (Gateway + Voice + CDN)'),
),
E(
'option',
{ value: 'twitch_suite' },
_('🟣 Twitch Suite (Live Stream + HLS CDN)'),
),
E(
'option',
{ value: 'twitter_suite' },
_('🐦 X / Twitter Suite (API + Media CDN)'),
),
E('option', { value: 'chatgpt_suite' }, _('🤖 ChatGPT / OpenAI Suite')),
E(
'option',
{ value: 'instagram_suite' },
_('📸 Instagram / Meta (Web + CDN)'),
),
E(
'option',
{ value: 'telegram_suite' },
_('✈️ Telegram Suite (Web + Bot API)'),
),
E('option', { value: 'rutracker_suite' }, _('🏴‍☠️ RuTracker Suite')),
E('option', { value: 'quic_http3' }, _('⚡ QUIC / HTTP/3 (UDP 443)')),
E('option', { value: 'custom' }, _('🌐 Custom Target URL...')),
],
);
const customUrlInput = E('input', {
type: 'text',
class: 'cbi-input-text',
placeholder: 'https://example.com',
style: 'width: 100%; display: none; margin-top: 4px;',
});
targetSelect.addEventListener('change', () => {
selectedTarget = (targetSelect as HTMLSelectElement)
.value as Tachyon.FuzzerTarget;
(customUrlInput as HTMLElement).style.display =
selectedTarget === 'custom' ? 'block' : 'none';
});
customUrlInput.addEventListener('input', () => {
customUrl = (customUrlInput as HTMLInputElement).value.trim();
});
const targetGroup = E(
'div',
{ style: 'display: flex; flex-direction: column; gap: 4px;' },
[
E(
'label',
{ style: 'font-size: 11px; font-weight: 600; opacity: 0.85;' },
_('Target Service / Suite'),
),
targetSelect,
customUrlInput,
],
);
// 3. Search Mode Select
const modeSelect = E(
'select',
{ class: 'cbi-input-select', style: 'width: 100%;' },
[
E(
'option',
{ value: 'presets', selected: true },
_('⚡ Quick Benchmark (Presets ~30+)'),
),
E(
'option',
{ value: 'combinatorial' },
_('🔍 Combinatorial Deep Fuzzing (~150-300+)'),
),
E('option', { value: 'custom' }, _('🛠️ My Custom Strategies Only')),
],
);
modeSelect.addEventListener('change', () => {
selectedMode = (modeSelect as HTMLSelectElement)
.value as Tachyon.FuzzerMode;
});
const modeGroup = E(
'div',
{ style: 'display: flex; flex-direction: column; gap: 4px;' },
[
E(
'label',
{ style: 'font-size: 11px; font-weight: 600; opacity: 0.85;' },
_('Search Mode'),
),
modeSelect,
],
);
// 4. Rule Apply Target Select
const ruleSelect = E(
'select',
{ class: 'cbi-input-select', style: 'width: 100%;' },
[
E('option', { value: '', selected: true }, _('Provider Global Default')),
...ruleNames.map((r) => E('option', { value: r }, `${_('Rule:')} ${r}`)),
],
);
ruleSelect.addEventListener('change', () => {
selectedRuleSection = (ruleSelect as HTMLSelectElement).value;
});
const ruleGroup = E(
'div',
{ style: 'display: flex; flex-direction: column; gap: 4px;' },
[
E(
'label',
{ style: 'font-size: 11px; font-weight: 600; opacity: 0.85;' },
_('Apply Strategy To'),
),
ruleSelect,
],
);
controlsGrid.append(engineGroup, targetGroup, modeGroup, ruleGroup);
// Auto-Apply Toggle
const autoApplyCheckbox = E('input', {
type: 'checkbox',
id: 'tachyon-fuzzer-auto-apply',
style: 'margin: 0;',
});
autoApplyCheckbox.addEventListener('change', () => {
autoApplyEnabled = (autoApplyCheckbox as HTMLInputElement).checked;
});
const autoApplyGroup = E(
'div',
{
style:
'display: flex; align-items: end; padding: 4px 0; grid-column: 1 / -1;',
},
[
E(
'div',
{
style:
'font-size: 11px; cursor: pointer; display: flex; align-items: center; gap: 4px;',
},
[autoApplyCheckbox, E('span', {}, _('Auto-apply best strategy'))],
),
],
);
controlsGrid.append(autoApplyGroup);
// DPI Detection Banner
const dpiDetectionBanner = E('div', {
id: 'tachyon-fuzzer-dpi-banner',
style:
'display: none; padding: 10px 14px; border-radius: 6px; font-size: 12px; line-height: 1.4;',
});
// Progress Bar
const progressContainer = E(
'div',
{
style:
'display: none; flex-direction: column; gap: 6px; padding: 10px 14px; background: var(--background-color-secondary, rgba(0,0,0,0.18)); border-radius: 6px; border: 1px solid var(--border-color, rgba(255,255,255,0.08));',
},
[
E(
'div',
{
style:
'display: flex; justify-content: space-between; font-size: 12px; font-weight: 600;',
},
[
E(
'span',
{ id: 'tachyon-fuzzer-status-text' },
_('Benchmarking in progress...'),
),
E('span', { id: 'tachyon-fuzzer-progress-pct' }, '0%'),
],
),
E(
'div',
{
style:
'width: 100%; height: 6px; background: rgba(255,255,255,0.1); border-radius: 3px; overflow: hidden;',
},
[
E('div', {
id: 'tachyon-fuzzer-progress-bar',
style:
'height: 100%; width: 0%; background: #007bff; transition: width 0.3s ease;',
}),
],
),
E(
'div',
{
id: 'tachyon-fuzzer-current-strategy',
style: 'font-size: 11px; opacity: 0.75; font-family: monospace;',
},
'',
),
],
);
const applyBestBtn = renderButton({
text: _('🏆 Apply Best Match'),
classNames: ['cbi-button-save'],
disabled: true,
onClick: () => handleApplyBest(),
});
// Results Filter Toolbar
const filterToolbar = E(
'div',
{
style:
'display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;',
},
[
E('div', { style: 'display: flex; gap: 6px; align-items: center;' }, [
E(
'span',
{ style: 'font-size: 11px; opacity: 0.7; margin-right: 4px;' },
_('Filter:'),
),
(() => {
const bAll = E(
'button',
{
type: 'button',
class: 'cbi-button cbi-button-action',
style: 'padding: 2px 10px; font-size: 11px;',
},
_('All'),
);
const bOk = E(
'button',
{
type: 'button',
class: 'cbi-button cbi-button-neutral',
style: 'padding: 2px 10px; font-size: 11px;',
},
_('✅ Working only'),
);
const bFast = E(
'button',
{
type: 'button',
class: 'cbi-button cbi-button-neutral',
style: 'padding: 2px 10px; font-size: 11px;',
},
_('⚡ Fast (>1MB/s)'),
);
const setFilter = (
f: 'all' | 'success' | 'fast',
btn: HTMLElement,
) => {
resultFilter = f;
[bAll, bOk, bFast].forEach(
(b) => (b.className = 'cbi-button cbi-button-neutral'),
);
btn.className = 'cbi-button cbi-button-action';
if (currentState) renderResults(currentState);
};
bAll.addEventListener('click', () => setFilter('all', bAll));
bOk.addEventListener('click', () => setFilter('success', bOk));
bFast.addEventListener('click', () => setFilter('fast', bFast));
return E('div', { style: 'display: flex; gap: 4px;' }, [
bAll,
bOk,
bFast,
]);
})(),
]),
E('div', { style: 'display: flex; gap: 8px;' }, [applyBestBtn]),
],
);
// Results Table
const resultsContainer = E('div', {
style:
'max-height: 380px; overflow-y: auto; overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid var(--border-color, rgba(255,255,255,0.1)); border-radius: 6px; width: 100%; box-sizing: border-box;',
});
const tableEl = E(
'table',
{
class: 'table cbi-section-table',
style:
'width: 100%; min-width: 620px; margin: 0; font-size: 12px; text-align: left; border-collapse: collapse;',
},
[
E(
'thead',
{
class: 'cbi-section-table-titles',
style:
'background: var(--background-color-secondary, rgba(0,0,0,0.25)); position: sticky; top: 0; z-index: 2;',
},
[
E('tr', { class: 'cbi-section-table-titles' }, [
E(
'th',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px 10px; width: 35px;',
},
'#',
),
E(
'th',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px 10px; width: 75px;',
},
_('Engine'),
),
E(
'th',
{ class: 'cbi-section-table-cell', style: 'padding: 8px 10px;' },
_('Strategy & Parameters'),
),
E(
'th',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px 10px; width: 95px;',
},
_('Status / Suite'),
),
E(
'th',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px 10px; width: 65px;',
},
_('TTFB'),
),
E(
'th',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px 10px; width: 75px;',
},
_('Speed'),
),
E(
'th',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px 10px; width: 80px;',
},
_('Score'),
),
E(
'th',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px 10px; width: 85px; text-align: center;',
},
_('Actions'),
),
]),
],
),
E('tbody', { id: 'tachyon-fuzzer-results-tbody' }, [
E(
'tr',
{},
E(
'td',
{
colSpan: 8,
style: 'padding: 24px; text-align: center; opacity: 0.6;',
},
_(
'No benchmark results yet. Configure options and click "Start Benchmark".',
),
),
),
]),
],
);
resultsContainer.appendChild(tableEl);
// Footer Actions for Benchmark
const startBtn = renderButton({
text: _('🚀 Start Benchmark'),
classNames: ['cbi-button-action'],
onClick: () => handleToggleRun(),
});
const footerActions = E(
'div',
{
style:
'display: flex; justify-content: space-between; align-items: center; padding-top: 6px;',
},
[
startBtn,
renderButton({
text: _('Close'),
classNames: ['cbi-button-neutral'],
onClick: () => {
stopPolling();
ui.hideModal();
},
}),
],
);
tabContentBenchmark.append(
controlsGrid,
dpiDetectionBanner,
progressContainer,
filterToolbar,
resultsContainer,
footerActions,
);
// ═════════════════════════════════════════════════════════════════════════════
// TAB 2: PATTERN BUILDER & MATRIX CONFIG
// ═════════════════════════════════════════════════════════════════════════════
const renderChipGroup = (
title: string,
items: (string | number)[],
onAdd: (val: string) => void,
onRemove: (idx: number) => void,
) => {
const input = E('input', {
type: 'text',
class: 'cbi-input-text',
placeholder: _('+ add'),
style: 'width: 80px; padding: 2px 6px; font-size: 11px;',
});
input.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'Enter') {
const v = (input as HTMLInputElement).value.trim();
if (v) {
onAdd(v);
(input as HTMLInputElement).value = '';
renderPatternsTab();
}
}
});
const chips = items.map((item, idx) => {
const chip = E(
'span',
{
style:
'display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; background: var(--background-color-secondary, rgba(255,255,255,0.08)); border: 1px solid var(--border-color, rgba(255,255,255,0.12)); border-radius: 4px; font-size: 11px; font-family: monospace;',
},
[
E('span', {}, String(item)),
(() => {
const del = E(
'span',
{
style:
'cursor: pointer; opacity: 0.6; font-size: 12px; margin-left: 2px;',
},
'×',
);
del.addEventListener('click', () => {
onRemove(idx);
renderPatternsTab();
});
return del;
})(),
],
);
return chip;
});
return E(
'div',
{ style: 'display: flex; flex-direction: column; gap: 4px;' },
[
E(
'span',
{ style: 'font-size: 11px; font-weight: 600; opacity: 0.8;' },
title,
),
E(
'div',
{
style:
'display: flex; flex-wrap: wrap; gap: 6px; align-items: center;',
},
[...chips, input],
),
],
);
};
const renderPatternsTab = () => {
tabContentPatterns.replaceChildren();
const z2 = patternsConfig.zapret2;
const z1 = patternsConfig.zapret;
const bd = patternsConfig.byedpi;
const z2Card = E(
'div',
{
style:
'padding: 12px; background: var(--background-color-secondary, rgba(0,0,0,0.15)); border-radius: 6px; border: 1px solid var(--border-color, rgba(255,255,255,0.1)); display: flex; flex-direction: column; gap: 10px;',
},
[
E(
'div',
{ style: 'font-size: 13px; font-weight: bold;' },
'⚡ Zapret v2 (nfqws2) Matrix Patterns',
),
renderChipGroup(
_('Split Positions (pos)'),
z2.splits,
(v) => z2.splits.push(v),
(i) => z2.splits.splice(i, 1),
),
renderChipGroup(
_('Fooling Methods (fooling)'),
z2.foolings,
(v) => z2.foolings.push(v),
(i) => z2.foolings.splice(i, 1),
),
renderChipGroup(
_('TTL Values (ttl)'),
z2.ttls,
(v) => z2.ttls.push(Number(v) || 4),
(i) => z2.ttls.splice(i, 1),
),
renderChipGroup(
_('Sequence Overlaps (seqovl)'),
z2.seqovls,
(v) => z2.seqovls.push(v),
(i) => z2.seqovls.splice(i, 1),
),
renderChipGroup(
_('TCP Window Sizes (wsize)'),
z2.wsizes,
(v) => z2.wsizes.push(v),
(i) => z2.wsizes.splice(i, 1),
),
],
);
const z1Card = E(
'div',
{
style:
'padding: 12px; background: var(--background-color-secondary, rgba(0,0,0,0.15)); border-radius: 6px; border: 1px solid var(--border-color, rgba(255,255,255,0.1)); display: flex; flex-direction: column; gap: 10px;',
},
[
E(
'div',
{ style: 'font-size: 13px; font-weight: bold;' },
'⚡ Zapret v1 (nfqws) Matrix Patterns',
),
renderChipGroup(
_('Split Modes (dpi-desync)'),
z1.split_modes,
(v) => z1.split_modes.push(v),
(i) => z1.split_modes.splice(i, 1),
),
renderChipGroup(
_('Split Positions (dpi-desync-split-pos)'),
z1.splits,
(v) => z1.splits.push(v),
(i) => z1.splits.splice(i, 1),
),
renderChipGroup(
_('Fooling Methods (dpi-desync-fooling)'),
z1.foolings,
(v) => z1.foolings.push(v),
(i) => z1.foolings.splice(i, 1),
),
renderChipGroup(
_('TTL Values (dpi-desync-ttl)'),
z1.ttls,
(v) => z1.ttls.push(Number(v) || 4),
(i) => z1.ttls.splice(i, 1),
),
],
);
const bdCard = E(
'div',
{
style:
'padding: 12px; background: var(--background-color-secondary, rgba(0,0,0,0.15)); border-radius: 6px; border: 1px solid var(--border-color, rgba(255,255,255,0.1)); display: flex; flex-direction: column; gap: 10px;',
},
[
E(
'div',
{ style: 'font-size: 13px; font-weight: bold;' },
'⚡ ByeDPI (ciadpi) Matrix Patterns',
),
renderChipGroup(
_('Split Values (-s)'),
bd.splits,
(v) => bd.splits.push(v),
(i) => bd.splits.splice(i, 1),
),
renderChipGroup(
_('Disorder Values (-d)'),
bd.disorders,
(v) => bd.disorders.push(v),
(i) => bd.disorders.splice(i, 1),
),
renderChipGroup(
_('OOB Values (-o)'),
bd.oobs,
(v) => bd.oobs.push(v),
(i) => bd.oobs.splice(i, 1),
),
renderChipGroup(
_('Auto Modes (--auto)'),
bd.autos,
(v) => bd.autos.push(v),
(i) => bd.autos.splice(i, 1),
),
renderChipGroup(
_('TLS-Rec Bounds (--tlsrec)'),
bd.tlsrecs,
(v) => bd.tlsrecs.push(v),
(i) => bd.tlsrecs.splice(i, 1),
),
renderChipGroup(
_('IP Frag Bounds (--ip-frag)'),
bd.ipfrags,
(v) => bd.ipfrags.push(v),
(i) => bd.ipfrags.splice(i, 1),
),
],
);
const patternsFooter = E(
'div',
{
style:
'display: flex; justify-content: space-between; align-items: center; padding-top: 6px;',
},
[
renderButton({
text: _('💾 Save Custom Patterns'),
classNames: ['cbi-button-save'],
onClick: async () => {
const res =
await TachyonShellMethods.saveFuzzerPatterns(patternsConfig);
if (res.success) {
showToast(_('Patterns saved successfully!'), 'success');
} else {
showToast(_('Failed to save patterns'), 'error');
}
},
}),
renderButton({
text: _('🔄 Reset to Factory Defaults'),
classNames: ['cbi-button-neutral'],
onClick: async () => {
const res = await TachyonShellMethods.resetFuzzerPatterns();
if (res.success && res.data?.patterns) {
patternsConfig = res.data.patterns;
renderPatternsTab();
showToast(_('Patterns reset to defaults!'), 'success');
}
},
}),
],
);
tabContentPatterns.append(z2Card, z1Card, bdCard, patternsFooter);
};
// ═════════════════════════════════════════════════════════════════════════════
// TAB 3: CUSTOM STRATEGIES
// ═════════════════════════════════════════════════════════════════════════════
const renderCustomTab = () => {
tabContentCustom.replaceChildren();
const nameInput = E('input', {
type: 'text',
class: 'cbi-input-text',
placeholder: _('Strategy Name'),
style: 'flex: 1 1 180px; min-width: 140px;',
});
const engineSel = E(
'select',
{
class: 'cbi-input-select',
style: 'flex: 0 1 140px; min-width: 120px;',
},
[
E('option', { value: 'zapret2' }, _('Zapret v2')),
E('option', { value: 'zapret' }, _('Zapret v1')),
E('option', { value: 'byedpi' }, _('ByeDPI')),
],
);
const argsInput = E('input', {
type: 'text',
class: 'cbi-input-text',
placeholder: _('Command-line arguments string...'),
style: 'flex: 2 1 240px; min-width: 180px; font-family: monospace;',
});
const addBtn = renderButton({
text: _('+ Add Strategy'),
classNames: ['cbi-button-action'],
onClick: async () => {
const name = (nameInput as HTMLInputElement).value.trim();
const eng = (engineSel as HTMLSelectElement)
.value as Tachyon.FuzzerEngine;
const args = (argsInput as HTMLInputElement).value.trim();
if (!name || !args) {
showToast(_('Please specify strategy name and arguments'), 'error');
return;
}
patternsConfig.custom_strategies =
patternsConfig.custom_strategies || [];
patternsConfig.custom_strategies.push({
id: `custom_${Date.now()}`,
name,
engine: eng as 'zapret2' | 'zapret' | 'byedpi',
args,
description: _('User custom strategy'),
});
await TachyonShellMethods.saveFuzzerPatterns(patternsConfig);
showToast(_('Custom strategy added!'), 'success');
(nameInput as HTMLInputElement).value = '';
(argsInput as HTMLInputElement).value = '';
renderCustomTab();
},
});
const addCard = E(
'div',
{
style:
'padding: 12px; background: var(--background-color-secondary, rgba(0,0,0,0.15)); border-radius: 6px; border: 1px solid var(--border-color, rgba(255,255,255,0.1)); display: flex; flex-direction: column; gap: 8px;',
},
[
E(
'div',
{ style: 'font-size: 12px; font-weight: 600;' },
_('Add Custom DPI Strategy'),
),
E(
'div',
{
style:
'display: flex; gap: 8px; flex-wrap: wrap; align-items: center;',
},
[nameInput, engineSel, argsInput, addBtn],
),
],
);
const customList = patternsConfig.custom_strategies || [];
const listCard = E(
'div',
{
style:
'border: 1px solid var(--border-color, rgba(255,255,255,0.1)); border-radius: 6px; overflow: hidden;',
},
[
E(
'table',
{ class: 'table', style: 'width: 100%; margin: 0; font-size: 12px;' },
[
E('thead', {}, [
E('tr', {}, [
E('th', { style: 'padding: 8px;' }, _('Name')),
E('th', { style: 'padding: 8px; width: 90px;' }, _('Engine')),
E('th', { style: 'padding: 8px;' }, _('Arguments')),
E(
'th',
{
style: 'padding: 8px; width: 80px; text-align: center;',
},
_('Actions'),
),
]),
]),
E(
'tbody',
{},
customList.length === 0
? [
E(
'tr',
{},
E(
'td',
{
colSpan: 4,
style:
'padding: 20px; text-align: center; opacity: 0.6;',
},
_('No custom strategies added yet.'),
),
),
]
: customList.map((cs, idx) => {
return E('tr', {}, [
E(
'td',
{ style: 'padding: 8px; font-weight: 600;' },
cs.name,
),
E(
'td',
{
style:
'padding: 8px; font-family: monospace; font-size: 11px;',
},
cs.engine,
),
E(
'td',
{
style:
'padding: 8px; font-family: monospace; font-size: 11px; word-break: break-all;',
},
cs.args,
),
E(
'td',
{
style: 'padding: 8px; text-align: center;',
},
[
(() => {
const delBtn = E(
'button',
{
type: 'button',
class: 'cbi-button cbi-button-reset',
style: 'padding: 2px 8px; font-size: 11px;',
},
_('Delete'),
);
delBtn.addEventListener('click', async () => {
patternsConfig.custom_strategies.splice(idx, 1);
await TachyonShellMethods.saveFuzzerPatterns(
patternsConfig,
);
showToast(_('Strategy deleted'), 'success');
renderCustomTab();
});
return delBtn;
})(),
],
),
]);
}),
),
],
),
],
);
tabContentCustom.append(addCard, listCard);
};
// ═════════════════════════════════════════════════════════════════════════════
// TAB 4: AI DOCTOR RAG
// ═════════════════════════════════════════════════════════════════════════════
const aiPromptInput = E('input', {
type: 'text',
class: 'cbi-input-text',
placeholder: _(
'Optional context (e.g. "Rostelecom, YouTube 4K buffering is slow")...',
),
style: 'flex: 1 1 240px; min-width: 180px; font-size: 12px;',
});
const aiSynthesizeBtn = renderButton({
text: _('🧠 Synthesize with AI'),
classNames: ['cbi-button-action'],
onClick: () => handleAiSynthesize(),
});
const aiAnalysisContainer = E(
'div',
{
id: 'tachyon-fuzzer-ai-analysis',
style:
'display: none; padding: 12px; background: rgba(0, 123, 255, 0.08); border-left: 3px solid #007bff; border-radius: 4px; font-size: 12px; line-height: 1.4;',
},
[
E(
'div',
{
style:
'font-weight: bold; margin-bottom: 6px; display: flex; align-items: center; gap: 6px;',
},
[
E('span', {}, '🧠'),
E('span', {}, _('AI Diagnostics & Strategy Rationale')),
],
),
E(
'div',
{ id: 'tachyon-fuzzer-ai-analysis-text', style: 'opacity: 0.9;' },
'',
),
],
);
const aiSynthesizerCard = E(
'div',
{
style:
'padding: 14px; background: var(--background-color-secondary, rgba(0,0,0,0.15)); border-radius: 6px; border: 1px solid var(--border-color, rgba(255,255,255,0.1)); display: flex; flex-direction: column; gap: 12px;',
},
[
E(
'div',
{
style:
'font-size: 13px; font-weight: bold; display: flex; align-items: center; justify-content: space-between;',
},
[
E('span', {}, '🧠 ' + _('AI DPI Engineer & Strategy Synthesizer')),
E(
'span',
{ style: 'font-size: 11px; opacity: 0.6; font-weight: normal;' },
_('RAG Knowledge Base + Live ISP Probe Context'),
),
],
),
E(
'div',
{ style: 'font-size: 12px; opacity: 0.8;' },
_(
'Automatically runs a diagnostic probe against the target service, queries the built-in DPI Knowledge Base, and synthesizes 3-5 custom bypass strategies tailored to your ISP.',
),
),
E('div', { style: 'display: flex; gap: 8px; align-items: center;' }, [
aiPromptInput,
aiSynthesizeBtn,
]),
aiAnalysisContainer,
],
);
tabContentAi.append(aiSynthesizerCard);
// ═════════════════════════════════════════════════════════════════════════════
// TAB 5: HISTORY
// ═════════════════════════════════════════════════════════════════════════════
const renderHistoryTab = async () => {
tabContentHistory.replaceChildren();
const historyHeader = E(
'div',
{
style:
'display: flex; justify-content: space-between; align-items: center;',
},
[
E(
'div',
{ style: 'font-size: 13px; font-weight: bold;' },
'📋 ' + _('Benchmark History'),
),
E('div', { style: 'display: flex; gap: 8px;' }, [
renderButton({
text: _('🔄 Refresh'),
classNames: ['cbi-button-neutral'],
onClick: () => renderHistoryTab(),
}),
renderButton({
text: _('🗑️ Clear History'),
classNames: ['cbi-button-reset'],
onClick: async () => {
await TachyonShellMethods.clearFuzzerHistory();
showToast(_('History cleared'), 'success');
renderHistoryTab();
},
}),
]),
],
);
const historyContainer = E('div', {
style:
'border: 1px solid var(--border-color, rgba(255,255,255,0.1)); border-radius: 6px; overflow: hidden;',
});
try {
const res = await TachyonShellMethods.getFuzzerHistory(20);
const entries = res.data?.entries || [];
if (entries.length === 0) {
historyContainer.appendChild(
E(
'div',
{
style:
'padding: 24px; text-align: center; opacity: 0.6; font-size: 12px;',
},
_('No benchmark history yet. Run a benchmark to see results here.'),
),
);
} else {
const table = E(
'table',
{
class: 'table cbi-section-table',
style: 'width: 100%; margin: 0; font-size: 12px;',
},
[
E('thead', { class: 'cbi-section-table-titles' }, [
E('tr', { class: 'cbi-section-table-titles' }, [
E(
'th',
{ class: 'cbi-section-table-cell', style: 'padding: 8px;' },
_('Date'),
),
E(
'th',
{ class: 'cbi-section-table-cell', style: 'padding: 8px;' },
_('Engine'),
),
E(
'th',
{ class: 'cbi-section-table-cell', style: 'padding: 8px;' },
_('Target'),
),
E(
'th',
{ class: 'cbi-section-table-cell', style: 'padding: 8px;' },
_('DPI Type'),
),
E(
'th',
{ class: 'cbi-section-table-cell', style: 'padding: 8px;' },
_('Best Strategy'),
),
E(
'th',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px; width: 60px;',
},
_('Score'),
),
E(
'th',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px; width: 70px;',
},
_('Working'),
),
]),
]),
E(
'tbody',
{},
entries.reverse().map((entry) => {
const date = new Date(entry.timestamp * 1000);
const dateStr = `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;
const dpiType = entry.dpi_detection
? `${entry.dpi_detection.type} (${entry.dpi_detection.confidence}%)`
: '—';
const bestName = entry.best_strategy
? entry.best_strategy.name
: '—';
const bestScore = entry.best_strategy
? String(entry.best_strategy.score)
: '0';
const working = `${entry.working_count}/${entry.total_tested}`;
return E('tr', { class: 'cbi-section-table-row' }, [
E(
'td',
{ class: 'cbi-section-table-cell', style: 'padding: 8px;' },
dateStr,
),
E(
'td',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px; font-family: monospace;',
},
entry.engine,
),
E(
'td',
{ class: 'cbi-section-table-cell', style: 'padding: 8px;' },
entry.target,
),
E(
'td',
{ class: 'cbi-section-table-cell', style: 'padding: 8px;' },
dpiType,
),
E(
'td',
{
class: 'cbi-section-table-cell',
style:
'padding: 8px; font-size: 11px; max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;',
},
bestName,
),
E(
'td',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px; font-weight: bold;',
},
bestScore,
),
E(
'td',
{ class: 'cbi-section-table-cell', style: 'padding: 8px;' },
working,
),
]);
}),
),
],
);
historyContainer.appendChild(table);
}
} catch {
historyContainer.appendChild(
E(
'div',
{
style:
'padding: 24px; text-align: center; opacity: 0.6; font-size: 12px;',
},
_('Failed to load history'),
),
);
}
tabContentHistory.append(historyHeader, historyContainer);
};
// ── Results Rendering ─────────────────────────────────────────────────────
const renderResults = (state: Tachyon.FuzzerState) => {
const tbody = document.getElementById('tachyon-fuzzer-results-tbody');
if (!tbody) return;
tbody.replaceChildren();
let list = state.results || [];
if (resultFilter === 'success') {
list = list.filter((r) => r.success);
} else if (resultFilter === 'fast') {
list = list.filter((r) => r.success && r.speed_kbps > 1024);
}
if (list.length === 0) {
tbody.appendChild(
E(
'tr',
{},
E(
'td',
{
colSpan: 8,
style: 'padding: 24px; text-align: center; opacity: 0.6;',
},
state.running
? _('Running benchmarks...')
: _('No strategies match the active filter.'),
),
),
);
return;
}
list.forEach((item, idx) => {
const isBest = state.best_strategy && state.best_strategy.id === item.id;
const nameChildren: (HTMLElement | string)[] = [E('span', {}, item.name)];
if (item.badge) {
nameChildren.push(
E(
'span',
{
style: `font-size: 10px; margin-left: 6px; font-weight: bold; color: ${
isBest ? '#28a745' : '#17a2b8'
};`,
},
item.badge,
),
);
}
const statusChildren: (HTMLElement | string)[] = [
E(
'span',
{
class: `badge ${item.success ? 'badge-success' : 'badge-danger'}`,
style: 'font-size: 10px; padding: 2px 6px; display: inline-block;',
},
item.success ? `HTTP ${item.http_code}` : 'DROP',
),
];
if (item.data_verified) {
statusChildren.push(
E(
'span',
{
class: 'badge badge-success',
style:
'font-size: 9px; padding: 2px 5px; margin-left: 4px; display: inline-block; font-weight: 500;',
title: _(
'Data transfer verified: streamed >= 32KB without throttling or disconnect',
),
},
_('✓ 32KB Streamed'),
),
);
} else if (item.dpi_verdict === 'throttled_16k') {
statusChildren.push(
E(
'span',
{
class: 'badge badge-danger',
style:
'font-size: 9px; padding: 2px 5px; margin-left: 4px; display: inline-block; font-weight: 500;',
title: _(
'DPI throttling: stream cut off after ~16KB payload transfer',
),
},
_('✗ Throttled at 16KB'),
),
);
} else if (item.dpi_verdict === 'server_fakes') {
statusChildren.push(
E(
'span',
{
class: 'badge badge-warning',
style:
'font-size: 9px; padding: 2px 5px; margin-left: 4px; display: inline-block; font-weight: 500;',
title: _(
'Fake packets reached remote server (HTTP 400 Bad Request)',
),
},
_('⚠️ Server received fakes'),
),
);
}
if (item.sub_probes && item.sub_probes.length > 1) {
const passedSub = item.sub_probes.filter((p) => p.success).length;
const totalSub = item.sub_probes.length;
statusChildren.push(
E(
'div',
{ style: 'font-size: 10px; opacity: 0.75; margin-top: 2px;' },
`${passedSub}/${totalSub} ` + _('endpoints OK'),
),
);
}
if (!item.success && item.error) {
statusChildren.push(
E(
'div',
{
style:
'font-size: 10px; color: var(--error-color-medium, #dc3545); opacity: 0.85; margin-top: 2px; max-width: 220px; word-break: break-word;',
title: item.error,
},
item.error,
),
);
}
const tr = E(
'tr',
{
class: `cbi-section-table-row ${isBest ? 'cbi-rowstyle-1' : 'cbi-rowstyle-2'}`,
style: `border-bottom: 1px solid var(--border-color, rgba(255,255,255,0.06)); ${
isBest
? 'background: var(--background-color-high, rgba(40, 167, 69, 0.08));'
: ''
}`,
},
[
E(
'td',
{ class: 'cbi-section-table-cell', style: 'padding: 8px 10px;' },
String(idx + 1),
),
E(
'td',
{
class: 'cbi-section-table-cell',
style:
'padding: 8px 10px; font-family: monospace; font-size: 11px;',
},
item.engine,
),
E(
'td',
{ class: 'cbi-section-table-cell', style: 'padding: 8px 10px;' },
[
E('div', { style: 'font-weight: 600;' }, nameChildren),
E(
'div',
{
style:
'font-size: 10px; opacity: 0.7; font-family: monospace; word-break: break-all; margin-top: 2px;',
},
item.args,
),
],
),
E(
'td',
{ class: 'cbi-section-table-cell', style: 'padding: 8px 10px;' },
E('div', {}, statusChildren),
),
E(
'td',
{ class: 'cbi-section-table-cell', style: 'padding: 8px 10px;' },
item.success ? `${item.ttfb_ms}ms` : '—',
),
E(
'td',
{ class: 'cbi-section-table-cell', style: 'padding: 8px 10px;' },
item.success
? [
E('div', {}, `${(item.speed_kbps / 1024).toFixed(1)}MB/s`),
item.data_bytes && item.data_bytes > 0
? E(
'div',
{ style: 'font-size: 10px; opacity: 0.65;' },
`${(item.data_bytes / 1024).toFixed(1)} KB`,
)
: '',
]
: '—',
),
E(
'td',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px 10px; font-weight: bold;',
},
item.success ? String(item.score) : '0',
),
E(
'td',
{
class: 'cbi-section-table-cell',
style: 'padding: 8px 10px; text-align: center;',
},
E(
'div',
{ style: 'display: flex; gap: 4px; justify-content: center;' },
[
renderButton({
text: _('Apply'),
classNames: ['cbi-button-action'],
disabled: !item.success,
onClick: () => handleApplySingle(item),
}),
],
),
),
],
);
tbody.appendChild(tr);
});
};
const updateProgressUI = (state: Tachyon.FuzzerState) => {
const statusText = document.getElementById('tachyon-fuzzer-status-text');
const pctText = document.getElementById('tachyon-fuzzer-progress-pct');
const progressBar = document.getElementById('tachyon-fuzzer-progress-bar');
const currentStratEl = document.getElementById(
'tachyon-fuzzer-current-strategy',
);
const applyBestBtn = document.getElementById(
'tachyon-fuzzer-apply-best-btn',
);
if (progressContainer) {
progressContainer.style.display =
state.running || state.results?.length ? 'flex' : 'none';
}
if (pctText) pctText.innerText = `${state.progress_pct}%`;
if (progressBar) progressBar.style.width = `${state.progress_pct}%`;
const workingResults = state.results?.filter((r) => r.success) || [];
const bestStrategy = state.best_strategy || workingResults[0] || null;
if (statusText) {
if (state.running) {
statusText.innerText = `${_('Testing strategy')} ${state.current_index} / ${state.total_strategies}...`;
} else if (state.finished_at > 0 || state.results?.length) {
if (bestStrategy || workingResults.length > 0) {
if (state.error) {
statusText.innerText = `${_('🛑 Benchmark stopped')}. ${_('Found')} ${workingResults.length} ${_('working strategies')}.`;
} else {
statusText.innerText = _(
'✅ Benchmark completed! Optimal strategy identified.',
);
}
} else {
statusText.innerText = state.error
? `${_('⚠️ Benchmark stopped')}: ${state.error}`
: _(
'⚠️ Benchmark completed. No working bypass found for this target.',
);
}
}
}
if (currentStratEl) {
if (state.running && state.current_strategy) {
currentStratEl.innerText = `${_('Testing:')} [${state.current_strategy.name}] -> ${state.current_strategy.args}`;
} else {
currentStratEl.innerText = '';
}
}
if (applyBestBtn) {
(applyBestBtn as HTMLButtonElement).disabled = !bestStrategy;
}
};
// ── Polling & Execution Logic ─────────────────────────────────────────────
let lastRenderedCount = 0;
let lastRenderedFinishedAt = 0;
const pollStatus = async () => {
if (isPolling) return;
isPolling = true;
try {
const res = await TachyonShellMethods.getFuzzerStatus();
if (res.success && res.data) {
currentState = res.data;
isRunning = res.data.running;
if (isRunning) {
startBtn.innerText = _('🛑 Stop Benchmark');
(startBtn as HTMLButtonElement).disabled = false;
startPolling();
} else {
stopPolling();
startBtn.innerText = _('🚀 Start Benchmark');
(startBtn as HTMLButtonElement).disabled = false;
}
updateProgressUI(res.data);
if (res.data.dpi_detection) {
currentDpiDetection = res.data.dpi_detection;
updateDpiBanner(res.data.dpi_detection);
}
// Only re-render results when new results arrive or benchmark finishes
const resultCount = res.data.results?.length || 0;
const finishedAt = res.data.finished_at || 0;
if (
resultCount !== lastRenderedCount ||
finishedAt !== lastRenderedFinishedAt
) {
renderResults(res.data);
lastRenderedCount = resultCount;
lastRenderedFinishedAt = finishedAt;
}
if (!isRunning) {
// Auto-apply best strategy if enabled
if (autoApplyEnabled && currentState?.best_strategy) {
try {
const applyRes =
await TachyonShellMethods.autoApplyFuzzerStrategy(
selectedRuleSection || undefined,
);
if (applyRes.success) {
showToast(
`${_('✅ Auto-applied best strategy')}: ${currentState.best_strategy.name}`,
'success',
);
} else {
showToast(
`${_('Auto-apply failed')}: ${applyRes.error || _('Unknown error')}`,
'error',
);
}
} catch {
showToast(_('Auto-apply failed'), 'error');
}
}
}
}
} catch {
// transient error ignore
} finally {
isPolling = false;
}
};
const startPolling = () => {
stopPolling();
pollingInterval = setInterval(pollStatus, 1200);
pollStatus();
};
const stopPolling = () => {
if (pollingInterval) {
clearInterval(pollingInterval);
pollingInterval = null;
}
};
const updateDpiBanner = (detection: Tachyon.FuzzerDpiDetection | null) => {
const banner = document.getElementById('tachyon-fuzzer-dpi-banner');
if (!banner) return;
if (!detection) {
banner.style.display = 'none';
return;
}
const typeMeta: Record<string, { alertClass: string; icon: string }> = {
rst: { alertClass: 'danger', icon: '🔴' },
throttle: { alertClass: 'warning', icon: '🟡' },
dns_block: { alertClass: 'info', icon: '🔵' },
ip_block: { alertClass: 'danger', icon: '🚫' },
unknown: { alertClass: 'notice', icon: '⚪' },
none: { alertClass: 'success', icon: '🟢' },
};
const typeLabels: Record<string, string> = {
rst: _('TCP Reset Injection'),
throttle: _('Throttling / Deep Inspection'),
dns_block: _('DNS Blocking'),
ip_block: _('IP Block (TCP SYN Timeout)'),
unknown: _('Unknown DPI Pattern'),
none: _('No Blocking Detected'),
};
const getLocalizedDpiDetails = (
det: Tachyon.FuzzerDpiDetection | null | undefined,
) => {
if (!det) return '';
switch (det.type) {
case 'ip_block':
return _(
'TCP connect timed out before TLS handshake — host is blocked at the IP layer. DPI bypass cannot unblock this; route via Sing-box VPN/Proxy outbound instead.',
);
case 'rst':
return _(
'TCP RST received from DPI — active TCP reset injection detected.',
);
case 'dns_block':
return _(
'DNS resolution failed — likely DNS-level blocking or hijacking.',
);
case 'throttle':
return _(
'DPI bandwidth throttling or delay detected — connection throttled during data transfer.',
);
case 'none':
return _('Target accessible — no DPI blocking detected.');
default:
return det.details || _('Analysis inconclusive.');
}
};
const meta = typeMeta[detection.type] || typeMeta.unknown;
const label = typeLabels[detection.type] || detection.type;
const ipBlockNotice =
detection.type === 'ip_block'
? `<div class="alert-message danger" style="margin-top: 8px;">
⚠️ ${_('IP-level blocking detected! The resource is blocked at the network level (no TCP SYN response). DPI bypass methods (Zapret / ByeDPI) cannot bypass this address — configure proxy/VPN routing (Sing-box) for this domain!')}
</div>`
: '';
banner.className = `alert-message ${meta.alertClass}`;
banner.style.display = 'block';
banner.innerHTML = `
<div style="display: flex; justify-content: space-between; align-items: start; flex-wrap: wrap; gap: 6px;">
<div>
<span style="font-weight: bold;">${meta.icon} ${_('DPI Detected')}: ${label}</span>
<span style="opacity: 0.7; margin-left: 8px;">${detection.confidence}% ${_('confidence')}</span>
</div>
${detection.recommended_engines.length > 0 ? `<div style="font-size: 11px; opacity: 0.8;">${_('Recommended')}: ${detection.recommended_engines.join(', ')}</div>` : ''}
</div>
<div style="margin-top: 4px; opacity: 0.9; font-size: 11px;">${getLocalizedDpiDetails(detection)}</div>
${ipBlockNotice}
`;
};
const handleToggleRun = async () => {
if (isRunning) {
(startBtn as HTMLButtonElement).disabled = true;
startBtn.innerText = _('⏳ Stopping...');
await TachyonShellMethods.stopFuzzer();
showToast(_('Benchmark stopped'), 'success');
isRunning = false;
stopPolling();
await pollStatus();
return;
}
(startBtn as HTMLButtonElement).disabled = true;
startBtn.innerText = _('🛑 Stop Benchmark');
// Immediate visual feedback
progressContainer.style.display = 'flex';
const statusTextEl = document.getElementById('tachyon-fuzzer-status-text');
const progressBarEl = document.getElementById(
'tachyon-fuzzer-progress-bar',
);
const currentStratEl = document.getElementById(
'tachyon-fuzzer-current-strategy',
);
if (statusTextEl)
statusTextEl.innerText = _('🚀 Initializing benchmark in sandbox...');
if (progressBarEl) progressBarEl.style.width = '3%';
if (currentStratEl)
currentStratEl.innerText = _(
'Preparing strategies and isolated nftables queue...',
);
// Run DPI detection before starting benchmark
try {
const dpiRes = await TachyonShellMethods.detectFuzzerDpi(
selectedTarget,
selectedTarget === 'custom' ? customUrl : undefined,
);
if (dpiRes.success && dpiRes.data) {
currentDpiDetection = dpiRes.data;
updateDpiBanner(dpiRes.data);
}
} catch {
// DPI detection is non-critical, continue with benchmark
}
const tbody = document.getElementById('tachyon-fuzzer-results-tbody');
if (tbody) {
tbody.replaceChildren(
E(
'tr',
{},
E(
'td',
{
colSpan: 8,
style: 'padding: 24px; text-align: center; opacity: 0.85;',
},
[
E('span', { style: 'margin-right: 8px;' }, '⏳'),
E(
'span',
{},
_('Testing bypass strategies in isolated sandbox...'),
),
],
),
),
);
}
const res = await TachyonShellMethods.startFuzzer(
selectedEngine,
selectedTarget,
customUrl,
selectedRuleSection,
'',
selectedMode,
);
if (res.success) {
showToast(_('Strategy benchmark started'), 'success');
(startBtn as HTMLButtonElement).disabled = false;
isRunning = true;
lastRenderedCount = 0;
lastRenderedFinishedAt = 0;
startPolling();
} else {
const errMsg = !res.success ? res.error : _('Unknown error');
showToast(`${_('Failed to start benchmark')}: ${errMsg}`, 'error');
(startBtn as HTMLButtonElement).disabled = false;
startBtn.innerText = _('🚀 Start Benchmark');
progressContainer.style.display = 'none';
}
};
const handleAiSynthesize = async () => {
const userPrompt = (aiPromptInput as HTMLInputElement).value.trim();
(aiSynthesizeBtn as HTMLButtonElement).disabled = true;
aiSynthesizeBtn.innerText = _('🧠 Synthesizing...');
const analysisBox = document.getElementById('tachyon-fuzzer-ai-analysis');
const analysisText = document.getElementById(
'tachyon-fuzzer-ai-analysis-text',
);
if (analysisBox) analysisBox.style.display = 'none';
try {
showToast(_('Consulting DPI Knowledge Base & AI...'), 'success');
const res = await TachyonShellMethods.fuzzerAiSynthesize(
selectedEngine,
selectedTarget,
customUrl,
userPrompt,
);
if (res.success && res.data) {
showToast(
_('AI successfully synthesized custom strategies!'),
'success',
);
if (analysisBox && analysisText && res.data.analysis) {
analysisText.innerText = res.data.analysis;
analysisBox.style.display = 'block';
}
// Switch to benchmark tab and start running
activeTab = 'benchmark';
updateTabVisibility();
(startBtn as HTMLButtonElement).disabled = true;
startBtn.innerText = _('🛑 Stop Benchmark');
const startRes = await TachyonShellMethods.startFuzzer(
selectedEngine,
selectedTarget,
customUrl,
selectedRuleSection,
);
if (startRes.success) {
isRunning = true;
startPolling();
}
} else {
const errMsg = !res.success ? res.error : _('AI synthesis failed');
showToast(`${_('AI Synthesis Error')}: ${errMsg}`, 'error');
}
} catch {
showToast(_('Failed to communicate with AI provider'), 'error');
} finally {
(aiSynthesizeBtn as HTMLButtonElement).disabled = false;
aiSynthesizeBtn.innerText = _('🧠 Synthesize with AI');
}
};
const handleApplySingle = async (item: Tachyon.FuzzerStrategyResult) => {
const res = await TachyonShellMethods.applyFuzzerStrategy(
item.engine,
item.args,
selectedRuleSection,
);
if (res.success) {
if (typeof ui?.addNotification === 'function') {
ui.addNotification(
_('Tachyon'),
E(
'p',
{},
`${_('Strategy applied successfully and service reloaded!')} (${item.name} -> ${selectedRuleSection || _('Global Default')})`,
),
'info',
);
} else {
showToast(
`${_('Applied')} "${item.name}" -> ${selectedRuleSection || _('Global Default')}`,
'success',
);
}
if (typeof ui?.hideModal === 'function') ui.hideModal();
if (
typeof window !== 'undefined' &&
typeof window.location?.reload === 'function'
) {
window.location.reload();
}
} else {
showToast(_('Failed to apply strategy'), 'error');
}
};
const handleApplyBest = async () => {
const best =
currentState?.best_strategy ||
currentState?.results?.find((r) => r.success);
if (!best) {
showToast(_('No working strategy to apply'), 'error');
return;
}
await handleApplySingle(best);
};
// Initial Data Fetch: available engines & custom patterns
TachyonShellMethods.getFuzzerStrategies()
.then((res) => {
if (res.success && res.data?.available_engines) {
const av = res.data.available_engines;
const opts = (engineSelect as HTMLSelectElement).options;
for (let i = 0; i < opts.length; i++) {
const opt = opts[i];
if (opt.value === 'zapret2') {
opt.text = av.zapret2
? _('Zapret v2 (nfqws2)') + ' — ' + _('Installed')
: _('Zapret v2 (nfqws2)') + ' — ' + _('Not installed');
if (!av.zapret2) opt.disabled = true;
} else if (opt.value === 'zapret') {
opt.text = av.zapret
? _('Zapret v1 (nfqws)') + ' — ' + _('Installed')
: _('Zapret v1 (nfqws)') + ' — ' + _('Not installed');
if (!av.zapret) opt.disabled = true;
} else if (opt.value === 'byedpi') {
opt.text = av.byedpi
? _('ByeDPI (ciadpi)') + ' — ' + _('Installed')
: _('ByeDPI (ciadpi)') + ' — ' + _('Not installed');
if (!av.byedpi) opt.disabled = true;
}
}
}
})
.catch(() => {});
TachyonShellMethods.getFuzzerPatterns()
.then((res) => {
if (res.success && res.data?.patterns) {
patternsConfig = res.data.patterns;
}
})
.catch(() => {});
// Build Modal Tree
modalContainer.append(
tabBar,
tabContentBenchmark,
tabContentPatterns,
tabContentCustom,
tabContentAi,
tabContentHistory,
);
// Check initial state
pollStatus();
ui.showModal(_('⚡ Strategy Fuzzer & Auto-Tuner'), modalContainer);
}