Files
alpine-router/public/proxy.html
2026-04-15 11:38:26 +03:00

1783 lines
74 KiB
HTML
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.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NanoRouter — Прокси</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<div class="header-left">
<svg class="logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
<path d="M2 17l10 5 10-5"/>
<path d="M2 12l10 5 10-5"/>
</svg>
<h1>NanoRouter</h1>
</div>
<div class="header-right">
<span id="statusBadge" class="svc-badge stopped">Остановлен</span>
</div>
</header>
<nav class="tab-nav">
<a href="/home.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
<polyline points="9 22 9 12 15 12 15 22"/>
</svg>
Главная
</a>
<a href="/ifaces.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
<path d="M2 17l10 5 10-5"/>
<path d="M2 12l10 5 10-5"/>
</svg>
Интерфейсы
</a>
<a href="/dhcp.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
DHCP сервер
</a>
<a href="/clients.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<circle cx="9" cy="7" r="4"/><path d="M3 21v-2a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v2"/>
<path d="M16 3.13a4 4 0 0 1 0 7.75M21 21v-2a4 4 0 0 0-3-3.87"/>
</svg>
Клиенты
</a>
<a href="/firewall.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
<path d="M9 12l2 2 4-4"/>
</svg>
Файрвол
</a>
<a href="/proxy.html" class="tab-link active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<circle cx="12" cy="12" r="3"/>
<path d="M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83"/>
</svg>
Прокси
</a>
<a href="/profile.html" class="tab-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
<circle cx="12" cy="7" r="4"/>
</svg>
Профиль
</a>
</nav>
<main class="proxy-main">
<div id="loading" class="loading">
<div class="spinner"></div>
<span>Загрузка...</span>
</div>
<div id="statusBar" class="dhcp-status-bar hidden">
<div class="status-info">
<span class="status-label">Mihomo</span>
<span id="statusText" class="svc-badge stopped">Остановлен</span>
</div>
<div class="status-actions">
<label class="toggle-label" id="serviceToggleWrap" title="Запустить / Остановить">
<input type="checkbox" id="serviceActive">
<span class="toggle-slider"></span>
<span id="serviceToggleText">Остановлен</span>
</label>
<button class="btn-icon" id="restartBtn" disabled title="Перезапустить">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/>
<path d="M3 3v5h5"/>
</svg>
</button>
</div>
</div>
<div id="coreInfo" class="alert alert-error hidden" style="margin-top:16px">
<span id="coreInfoMsg">Ядро Mihomo не найдено. Загрузите бинарный файл в раздел «Ядро».</span>
</div>
<div class="proxy-tabs">
<button class="ptab active" data-tab="dashboard">Дашборд</button>
<button class="ptab" data-tab="proxies">Прокси</button>
<button class="ptab" data-tab="groups">Группы</button>
<button class="ptab" data-tab="rules">Правила</button>
<button class="ptab" data-tab="providers">Провайдеры</button>
<button class="ptab" data-tab="settings">Настройки</button>
<button class="ptab" data-tab="logs">Логи</button>
<button class="ptab" data-tab="core">Ядро</button>
</div>
<!-- Dashboard Tab -->
<div id="tab-dashboard" class="ptab-content">
<div id="dashOffline" class="alert alert-error" style="margin-bottom:16px">
Mihomo не запущен — дашборд недоступен. Запустите ядро для просмотра статуса прокси в реальном времени.
</div>
<div id="dashOnline" class="hidden">
<div class="dash-grid">
<div class="dash-card dash-traffic-card">
<h3 class="dash-card-title">Трафик</h3>
<div class="dash-traffic-row">
<div class="dash-traffic-item">
<span class="dash-traffic-label">↓ Загрузка</span>
<span class="dash-traffic-val" id="dashDown">0 B/s</span>
</div>
<div class="dash-traffic-item">
<span class="dash-traffic-label">↑ Отдача</span>
<span class="dash-traffic-val" id="dashUp">0 B/s</span>
</div>
</div>
<div class="dash-traffic-row">
<div class="dash-traffic-item">
<span class="dash-traffic-label">Всего</span>
<span class="dash-traffic-val dash-traffic-total" id="dashDownTotal">0 B</span>
</div>
<div class="dash-traffic-item">
<span class="dash-traffic-label">Всего</span>
<span class="dash-traffic-val dash-traffic-total" id="dashUpTotal">0 B</span>
</div>
</div>
<div class="dash-mem-row">
<span class="dash-traffic-label">Память</span>
<span class="dash-traffic-val" id="dashMem">0 B</span>
</div>
</div>
<div class="dash-card">
<h3 class="dash-card-title">Режим</h3>
<div class="dash-mode-switch" id="dashModeSwitch">
<button class="seg-btn" data-mode="rule">Правила</button>
<button class="seg-btn" data-mode="global">Глобальный</button>
<button class="seg-btn" data-mode="direct">Прямой</button>
</div>
<div class="dash-info-row" style="margin-top:12px">
<span class="info-label">Версия</span>
<span class="info-val mono" id="dashVersion"></span>
</div>
</div>
</div>
<div class="dash-section">
<div class="dash-section-header">
<h3>Группы прокси</h3>
<button class="btn btn-ghost btn-sm" id="dashPingAllBtn">Пинг всех</button>
</div>
<div id="dashGroupList" class="dash-group-list"></div>
</div>
<div class="dash-section">
<div class="dash-section-header">
<h3>Активные соединения</h3>
<span class="dash-conn-count" id="dashConnCount">0</span>
<button class="btn btn-danger btn-sm" id="dashCloseAllConnsBtn" style="margin-left:auto">Закрыть все</button>
</div>
<div class="dash-conn-table-wrap">
<table class="dash-conn-table">
<thead>
<tr>
<th>Хост</th>
<th>Тип</th>
<th>Цепочка</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody id="dashConnBody"></tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Proxies Tab -->
<div id="tab-proxies" class="ptab-content hidden">
<div class="section-header" style="margin-bottom:16px">
<div style="display:flex;align-items:center;justify-content:space-between">
<div>
<h2>Прокси-ноды</h2>
<div class="section-desc">Добавьте прокси-серверы для маршрутизации трафика</div>
</div>
<button class="btn btn-primary btn-sm" id="addProxyBtn">+ Добавить</button>
</div>
</div>
<div id="proxyList" class="proxy-list"></div>
<div id="proxyEmpty" class="empty-state hidden">Нет прокси-нод. Нажмите «Добавить» для создания.</div>
</div>
<!-- Groups Tab -->
<div id="tab-groups" class="ptab-content hidden">
<div class="section-header" style="margin-bottom:16px">
<div style="display:flex;align-items:center;justify-content:space-between">
<div>
<h2>Группы прокси</h2>
<div class="section-desc">Балансировщики, селекторы и URL-тесты</div>
</div>
<button class="btn btn-primary btn-sm" id="addGroupBtn">+ Добавить группу</button>
</div>
</div>
<div id="groupList" class="proxy-list"></div>
<div id="groupEmpty" class="empty-state hidden">Нет групп. Нажмите «Добавить группу» для создания.</div>
</div>
<!-- Rules Tab -->
<div id="tab-rules" class="ptab-content hidden">
<div class="rules-toolbar">
<div class="rules-toolbar-left">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="15" height="15" style="color:var(--accent);flex-shrink:0">
<path d="M4 6h16M4 12h16M4 18h7"/>
</svg>
<div>
<div class="rules-toolbar-title">Правила маршрутизации</div>
<div class="rules-toolbar-hint">Применяются сверху вниз</div>
</div>
</div>
<div class="rules-toolbar-right">
<button class="btn btn-ghost btn-sm" id="addBlockBtn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="13" height="13"><circle cx="12" cy="12" r="10"/><path d="M4.93 4.93l14.14 14.14"/></svg>
Блокировка домена
</button>
<button class="btn btn-primary btn-sm" id="addRuleBtn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="13" height="13"><path d="M12 5v14M5 12h14"/></svg>
Добавить правило
</button>
</div>
</div>
<div id="rulesList" class="rules-list"></div>
</div>
<!-- Providers Tab -->
<div id="tab-providers" class="ptab-content hidden">
<div class="section-header" style="margin-bottom:16px">
<div style="display:flex;align-items:center;justify-content:space-between">
<div>
<h2>Провайдеры прокси</h2>
<div class="section-desc">Внешние источники прокси-нод (proxy-providers)</div>
</div>
<button class="btn btn-primary btn-sm" id="addProxyProviderBtn">+ Добавить</button>
</div>
</div>
<div id="proxyProviderList" class="proxy-list"></div>
<div id="proxyProviderEmpty" class="empty-state">Нет провайдеров прокси.</div>
<div class="form-divider" style="margin:24px 0"></div>
<div class="section-header" style="margin-bottom:16px">
<div style="display:flex;align-items:center;justify-content:space-between">
<div>
<h2>Провайдеры правил</h2>
<div class="section-desc">Внешние наборы правил маршрутизации (rule-providers)</div>
</div>
<button class="btn btn-primary btn-sm" id="addRuleProviderBtn">+ Добавить</button>
</div>
</div>
<div id="ruleProviderList" class="proxy-list"></div>
<div id="ruleProviderEmpty" class="empty-state">Нет провайдеров правил.</div>
</div>
<!-- Settings Tab -->
<div id="tab-settings" class="ptab-content hidden">
<div class="section-header" style="margin-bottom:16px">
<h2>Настройки Mihomo</h2>
</div>
<form id="settingsForm" class="proxy-form">
<h3 class="settings-section-title">Основные</h3>
<div class="form-row">
<label>Режим</label>
<div class="segmented" id="modeSwitch">
<button type="button" class="seg-btn active" data-mode="rule">Правила</button>
<button type="button" class="seg-btn" data-mode="global">Глобальный</button>
<button type="button" class="seg-btn" data-mode="direct">Прямой</button>
</div>
</div>
<div class="form-row">
<label>Уровень логов</label>
<div class="segmented" id="logLevelSwitch">
<button type="button" class="seg-btn" data-mode="silent">silent</button>
<button type="button" class="seg-btn" data-mode="error">error</button>
<button type="button" class="seg-btn" data-mode="warning">warning</button>
<button type="button" class="seg-btn active" data-mode="info">info</button>
<button type="button" class="seg-btn" data-mode="debug">debug</button>
</div>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="allowLan" checked>
<span>Разрешить LAN</span>
</label>
</div>
<div class="form-row">
<label for="bindAddress">Адрес привязки</label>
<input type="text" id="bindAddress" value="*" placeholder="* или конкретный IP">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="ipv6" checked>
<span>IPv6</span>
</label>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="tcpConcurrent" checked>
<span>TCP Concurrency</span>
</label>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="unifiedDelay">
<span>Unified Delay</span>
</label>
</div>
<div class="form-row">
<label>Поиск процессов</label>
<div class="segmented" id="findProcessSwitch">
<button type="button" class="seg-btn" data-mode="always">always</button>
<button type="button" class="seg-btn" data-mode="strict">strict</button>
<button type="button" class="seg-btn active" data-mode="off">off</button>
</div>
</div>
<div class="form-row">
<label for="globalUA">Global UA</label>
<input type="text" id="globalUA" placeholder="clash.meta">
</div>
<div class="form-row">
<label for="keepAliveInterval">Keep-Alive Interval (сек)</label>
<input type="number" id="keepAliveInterval" placeholder="15">
</div>
<div class="form-row">
<label for="keepAliveIdle">Keep-Alive Idle (сек)</label>
<input type="number" id="keepAliveIdle" placeholder="15">
</div>
<div class="form-divider"></div>
<h3 class="settings-section-title">Порты</h3>
<div class="form-row">
<label for="mixedPort">Mixed Port (HTTP+SOCKS)</label>
<input type="number" id="mixedPort" value="7890">
</div>
<div class="form-row">
<label for="httpPort">HTTP Port</label>
<input type="number" id="httpPort" placeholder="0 (отключён)">
</div>
<div class="form-row">
<label for="socksPort">SOCKS5 Port</label>
<input type="number" id="socksPort" placeholder="0 (отключён)">
</div>
<div class="form-row">
<label for="redirPort">Redir Port</label>
<input type="number" id="redirPort" placeholder="0 (отключён)">
</div>
<div class="form-divider"></div>
<h3 class="settings-section-title">TProxy (прозрачный прокси)</h3>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="tproxyEnabled">
<span>Включить TProxy</span>
</label>
</div>
<div class="form-row">
<label for="tproxyPort">TProxy порт</label>
<input type="number" id="tproxyPort" value="7894">
</div>
<div class="form-divider"></div>
<h3 class="settings-section-title">DNS</h3>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="dnsEnabled" checked>
<span>DNS сервер</span>
</label>
</div>
<div class="form-row">
<label for="dnsListen">DNS адрес</label>
<input type="text" id="dnsListen" value="0.0.0.0:1053">
</div>
<div class="form-row">
<label>DNS режим</label>
<div class="segmented" id="dnsModeSwitch">
<button type="button" class="seg-btn active" data-mode="redir-host">redir-host</button>
<button type="button" class="seg-btn" data-mode="fake-ip">fake-ip</button>
</div>
</div>
<div class="form-row">
<label for="dnsNameserver">DNS серверы (по строке)</label>
<textarea id="dnsNameserver" rows="3" class="mono-ta">https://doh.pub/dns-query
https://dns.alidns.com/dns-query</textarea>
</div>
<div class="form-row">
<label for="dnsFallback">Fallback DNS (по строке)</label>
<textarea id="dnsFallback" rows="2" class="mono-ta">tls://8.8.8.8:853
tls://1.1.1.1:853</textarea>
</div>
<div class="form-row">
<label for="dnsDefaultNS">Default Nameserver (по строке)</label>
<textarea id="dnsDefaultNS" rows="2" class="mono-ta">223.5.5.5
119.29.29.29</textarea>
</div>
<div class="form-row">
<label for="dnsProxyNS">Proxy Server Nameserver (по строке)</label>
<textarea id="dnsProxyNS" rows="2" class="mono-ta"></textarea>
</div>
<div class="form-row">
<label for="dnsFakeIPRange">Fake-IP Range</label>
<input type="text" id="dnsFakeIPRange" value="198.18.0.1/16">
</div>
<div class="form-row">
<label for="dnsFakeIPFilter">Fake-IP Filter (по строке)</label>
<textarea id="dnsFakeIPFilter" rows="3" class="mono-ta">*.lan
*.local
+.market.xiaomi.com</textarea>
</div>
<div class="form-row">
<label for="dnsNameserverPolicy">Nameserver Policy (YAML)</label>
<textarea id="dnsNameserverPolicy" rows="3" class="mono-ta" placeholder="geosite:cn: https://doh.pub/dns-query"></textarea>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="dnsUseHosts" checked>
<span>Использовать hosts</span>
</label>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="dnsUseSystemHosts" checked>
<span>Использовать системные hosts</span>
</label>
</div>
<div class="form-divider"></div>
<h3 class="settings-section-title">GEO данные</h3>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="geodataMode">
<span>Geodata Mode (dat)</span>
</label>
</div>
<div class="form-row">
<label>Geodata Loader</label>
<div class="segmented" id="geodataLoaderSwitch">
<button type="button" class="seg-btn active" data-mode="memconservative">memconservative</button>
<button type="button" class="seg-btn" data-mode="standard">standard</button>
</div>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="geoAutoUpdate">
<span>Авто-обновление GEO</span>
</label>
</div>
<div class="form-row">
<label for="geoUpdateInterval">Интервал обновления GEO (часы)</label>
<input type="number" id="geoUpdateInterval" value="24">
</div>
<div class="form-row">
<label for="geoxGeoIP">GeoIP URL</label>
<input type="text" id="geoxGeoIP" placeholder="https://...geoip.dat">
</div>
<div class="form-row">
<label for="geoxGeoSite">GeoSite URL</label>
<input type="text" id="geoxGeoSite" placeholder="https://...geosite.dat">
</div>
<div class="form-row">
<label for="geoxMMDB">MMDB URL</label>
<input type="text" id="geoxMMDB" placeholder="https://...country.mmdb">
</div>
<div class="form-row">
<label for="geoxASN">ASN URL</label>
<input type="text" id="geoxASN" placeholder="https://...GeoLite2-ASN.mmdb">
</div>
<div class="form-divider"></div>
<h3 class="settings-section-title">External Controller</h3>
<div class="form-row">
<label for="externalController">External Controller</label>
<input type="text" id="externalController" value="0.0.0.0:9090">
</div>
<div class="form-row">
<label for="secret">Secret (API ключ)</label>
<input type="text" id="secret" placeholder="опционально">
</div>
<div class="form-row">
<label for="externalUI">External UI путь</label>
<input type="text" id="externalUI" placeholder="/path/to/ui">
</div>
<div class="form-row">
<label for="externalUIName">External UI Name</label>
<input type="text" id="externalUIName" placeholder="xd">
</div>
<div class="form-row">
<label for="externalUIURL">External UI URL (для скачивания)</label>
<input type="text" id="externalUIURL" placeholder="https://...">
</div>
<div class="form-divider"></div>
<h3 class="settings-section-title">Профиль</h3>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="profileStoreSelected" checked>
<span>Сохранять выбор группы (store-selected)</span>
</label>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="profileStoreFakeIP" checked>
<span>Сохранять fake-ip таблицу (store-fake-ip)</span>
</label>
</div>
<div style="margin-top:16px;display:flex;gap:8px">
<button type="submit" class="btn btn-primary">Сохранить настройки</button>
<button type="button" class="btn btn-ghost" id="saveAndRestartBtn">Сохранить и перезапустить</button>
</div>
</form>
<div class="form-divider" style="margin:20px 0"></div>
<h3 style="color:var(--text);font-size:.95rem;margin-bottom:8px">config.yaml (только чтение)</h3>
<div class="section-desc" style="margin-bottom:8px">Текущий конфиг mihomo. Обновляется автоматически после сохранения настроек.</div>
<div class="form-row">
<textarea id="yamlPreview" rows="18" readonly class="mono-ta" style="opacity:.85"></textarea>
</div>
</div>
<!-- Logs Tab -->
<div id="tab-logs" class="ptab-content hidden">
<div class="section-header" style="margin-bottom:16px">
<div style="display:flex;align-items:center;justify-content:space-between">
<div>
<h2>Логи ядра</h2>
<div class="section-desc">Вывод процесса mihomo (обновление каждые 500мс)</div>
</div>
<button class="btn btn-ghost btn-sm" id="clearLogsBtn">Очистить</button>
</div>
</div>
<div id="logOutput" style="background:var(--bg-deep);border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px;font-family:'JetBrains Mono','Fira Code',monospace;font-size:.78rem;color:var(--text-muted);min-height:200px;max-height:calc(100vh - 300px);overflow-y:auto;white-space:pre-wrap;word-break:break-all"></div>
</div>
<!-- Core Tab -->
<div id="tab-core" class="ptab-content hidden">
<div class="section-header" style="margin-bottom:16px">
<h2>Ядро Mihomo</h2>
<div class="section-desc">Управление бинарным файлом ядра</div>
</div>
<div id="coreStatus" class="proxy-card" style="margin-bottom:16px">
<div class="card-info">
<div class="info-row"><span class="info-label">Путь</span><span class="info-val" id="corePath"></span></div>
<div class="info-row"><span class="info-label">Наличие</span><span class="info-val" id="coreExists"></span></div>
<div class="info-row"><span class="info-label">PID</span><span class="info-val" id="corePid"></span></div>
</div>
</div>
<div class="form-divider" style="margin-bottom:16px"></div>
<h3 style="color:var(--text);font-size:.95rem;margin-bottom:12px">Загрузить ядро</h3>
<div class="section-desc" style="margin-bottom:12px">Загрузите бинарный файл mihomo (например, mihomo-linux-amd64). Файл автоматически определит архитектуру по имени.</div>
<form id="uploadCoreForm">
<div class="form-row">
<input type="file" id="coreFile" accept=".gz,.zip,application/octet-stream" style="color:var(--text)">
</div>
<button type="submit" class="btn btn-primary btn-sm" style="margin-top:8px">Загрузить</button>
</form>
<div class="form-divider" style="margin:20px 0"></div>
<h3 style="color:var(--text);font-size:.95rem;margin-bottom:12px">Ручная конфигурация (config.yaml)</h3>
<div class="section-desc" style="margin-bottom:8px">Редактировать конфигурационный файл напрямую</div>
<div class="form-row">
<textarea id="yamlEditor" rows="20" class="mono-ta"></textarea>
</div>
<div style="margin-top:8px;display:flex;gap:8px">
<button class="btn btn-primary btn-sm" id="yamlLoadBtn">Загрузить</button>
<button class="btn btn-success btn-sm" id="yamlSaveBtn">Сохранить</button>
</div>
</div>
</div>
<!-- ===================== PROXY MODAL ===================== -->
<div id="proxyModal" class="modal hidden" role="dialog" aria-modal="true">
<div class="modal-backdrop" id="proxyModalBackdrop"></div>
<div class="modal-box" style="width:min(640px,calc(100vw - 40px))">
<div class="modal-header">
<h2 id="proxyModalTitle">Добавить прокси</h2>
<button class="btn-icon" id="closeProxyModal" title="Закрыть"></button>
</div>
<form id="proxyForm" autocomplete="off" style="max-height:52vh;overflow-y:auto;padding-right:4px">
<!-- Type -->
<div class="form-row">
<label for="proxyType">Тип</label>
<select id="proxyType" class="field-select">
<option value="ss">Shadowsocks</option>
<option value="ssr">ShadowsocksR</option>
<option value="vmess">VMess</option>
<option value="vless">VLESS</option>
<option value="trojan">Trojan</option>
<option value="hysteria">Hysteria v1</option>
<option value="hysteria2">Hysteria2</option>
<option value="tuic">TUIC</option>
<option value="wireguard">WireGuard</option>
<option value="snell">Snell</option>
<option value="ssh">SSH</option>
<option value="anytls">AnyTLS</option>
<option value="mieru">Mieru</option>
<option value="http">HTTP</option>
<option value="socks5">SOCKS5</option>
<option value="direct">DIRECT</option>
</select>
</div>
<!-- Name -->
<div class="form-row">
<label for="proxyName">Имя</label>
<input type="text" id="proxyName" placeholder="my-proxy">
</div>
<!-- Server / Port (hidden for direct) -->
<div id="pf-server-section">
<div class="form-row">
<label for="proxyServer">Сервер</label>
<input type="text" id="proxyServer" placeholder="example.com">
</div>
<div class="form-row">
<label for="proxyPort">Порт</label>
<input type="number" id="proxyPort" placeholder="443">
</div>
</div>
<!-- ===== SS ===== -->
<div id="pf-ss" class="hidden">
<div class="form-row">
<label>Шифр (cipher)</label>
<select id="ssCipher" class="field-select">
<option value="auto">auto</option>
<optgroup label="AES-GCM">
<option value="aes-128-gcm">aes-128-gcm</option>
<option value="aes-192-gcm">aes-192-gcm</option>
<option value="aes-256-gcm">aes-256-gcm</option>
<option value="aes-128-gcm-siv">aes-128-gcm-siv</option>
<option value="aes-256-gcm-siv">aes-256-gcm-siv</option>
</optgroup>
<optgroup label="AES-CTR">
<option value="aes-128-ctr">aes-128-ctr</option>
<option value="aes-192-ctr">aes-192-ctr</option>
<option value="aes-256-ctr">aes-256-ctr</option>
</optgroup>
<optgroup label="AES-CFB">
<option value="aes-128-cfb">aes-128-cfb</option>
<option value="aes-192-cfb">aes-192-cfb</option>
<option value="aes-256-cfb">aes-256-cfb</option>
</optgroup>
<optgroup label="ChaCha20">
<option value="chacha20-ietf-poly1305">chacha20-ietf-poly1305</option>
<option value="xchacha20-ietf-poly1305">xchacha20-ietf-poly1305</option>
<option value="chacha20-ietf">chacha20-ietf</option>
<option value="chacha20">chacha20</option>
</optgroup>
<optgroup label="2022-Blake3">
<option value="2022-blake3-aes-128-gcm">2022-blake3-aes-128-gcm</option>
<option value="2022-blake3-aes-256-gcm">2022-blake3-aes-256-gcm</option>
<option value="2022-blake3-chacha20-poly1305">2022-blake3-chacha20-poly1305</option>
</optgroup>
<optgroup label="Прочие">
<option value="none">none</option>
<option value="rc4-md5">rc4-md5</option>
<option value="aegis-128l">aegis-128l</option>
<option value="aegis-256">aegis-256</option>
</optgroup>
</select>
</div>
<div class="form-row">
<label>Пароль</label>
<input type="text" id="ssPassword" placeholder="password">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="ssUOT">
<span>UDP over TCP</span>
</label>
</div>
<div class="form-row" id="pf-ss-uot-ver">
<label>UDP over TCP версия</label>
<div class="segmented" id="ssUOTVersionSwitch">
<button type="button" class="seg-btn active" data-mode="1">1</button>
<button type="button" class="seg-btn" data-mode="2">2</button>
</div>
</div>
<div class="form-row">
<label>Plugin</label>
<select id="ssPlugin" class="field-select">
<option value="">Нет</option>
<option value="obfs">obfs</option>
<option value="v2ray-plugin">v2ray-plugin</option>
<option value="gost-plugin">gost-plugin</option>
<option value="shadow-tls">shadow-tls</option>
<option value="restls">restls</option>
<option value="kcptun">kcptun</option>
</select>
</div>
<div id="pf-ss-obfs" class="hidden">
<div class="form-row">
<label>Obfs Mode</label>
<select id="ssObfsMode" class="field-select">
<option value="tls">tls</option>
<option value="http">http</option>
</select>
</div>
<div class="form-row">
<label>Obfs Host</label>
<input type="text" id="ssObfsHost" placeholder="bing.com">
</div>
</div>
<div id="pf-ss-plugin-opts" class="hidden">
<div class="form-row">
<label>Plugin-Opts (YAML)</label>
<textarea id="ssPluginOpts" rows="4" class="mono-ta" placeholder="mode: websocket&#10;tls: true&#10;host: example.com&#10;path: /"></textarea>
</div>
</div>
</div>
<!-- ===== SSR ===== -->
<div id="pf-ssr" class="hidden">
<div class="form-row">
<label>Шифр (cipher)</label>
<select id="ssrCipher" class="field-select">
<option value="none">none</option>
<option value="aes-128-cfb">aes-128-cfb</option>
<option value="aes-192-cfb">aes-192-cfb</option>
<option value="aes-256-cfb">aes-256-cfb</option>
<option value="aes-128-ctr">aes-128-ctr</option>
<option value="aes-192-ctr">aes-192-ctr</option>
<option value="aes-256-ctr">aes-256-ctr</option>
<option value="chacha20-ietf">chacha20-ietf</option>
<option value="chacha20">chacha20</option>
<option value="rc4-md5">rc4-md5</option>
</select>
</div>
<div class="form-row">
<label>Пароль</label>
<input type="text" id="ssrPassword" placeholder="password">
</div>
<div class="form-row">
<label>Protocol</label>
<select id="ssrProtocol" class="field-select">
<option value="origin">origin</option>
<option value="auth_sha1_v4">auth_sha1_v4</option>
<option value="auth_aes128_md5">auth_aes128_md5</option>
<option value="auth_aes128_sha1">auth_aes128_sha1</option>
<option value="auth_chain_a">auth_chain_a</option>
<option value="auth_chain_b">auth_chain_b</option>
</select>
</div>
<div class="form-row">
<label>Protocol Param</label>
<input type="text" id="ssrProtocolParam" placeholder="#">
</div>
<div class="form-row">
<label>Obfs</label>
<select id="ssrObfs" class="field-select">
<option value="plain">plain</option>
<option value="http_simple">http_simple</option>
<option value="http_post">http_post</option>
<option value="random_head">random_head</option>
<option value="tls1.2_ticket_auth">tls1.2_ticket_auth</option>
<option value="tls1.2_ticket_fastauth">tls1.2_ticket_fastauth</option>
</select>
</div>
<div class="form-row">
<label>Obfs Param</label>
<input type="text" id="ssrObfsParam" placeholder="domain.tld">
</div>
</div>
<!-- ===== VMess ===== -->
<div id="pf-vmess" class="hidden">
<div class="form-row">
<label>UUID</label>
<input type="text" id="vmessUUID" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
</div>
<div class="form-row">
<label>Alter ID</label>
<input type="number" id="vmessAlterID" value="0" min="0">
</div>
<div class="form-row">
<label>Cipher</label>
<select id="vmessCipher" class="field-select">
<option value="auto">auto</option>
<option value="none">none</option>
<option value="zero">zero</option>
<option value="aes-128-gcm">aes-128-gcm</option>
<option value="chacha20-poly1305">chacha20-poly1305</option>
</select>
</div>
</div>
<!-- ===== VLESS ===== -->
<div id="pf-vless" class="hidden">
<div class="form-row">
<label>UUID</label>
<input type="text" id="vlessUUID" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
</div>
<div class="form-row">
<label>Flow</label>
<select id="vlessFlow" class="field-select">
<option value="">Нет</option>
<option value="xtls-rprx-vision">xtls-rprx-vision</option>
<option value="xtls-rprx-vision-udp443">xtls-rprx-vision-udp443</option>
</select>
</div>
<div class="form-row">
<label>Encryption</label>
<select id="vlessEncryption" class="field-select">
<option value="none">none</option>
</select>
</div>
</div>
<!-- ===== Trojan ===== -->
<div id="pf-trojan" class="hidden">
<div class="form-row">
<label>Пароль</label>
<input type="text" id="trojanPassword" placeholder="password">
</div>
</div>
<!-- ===== Hysteria v1 ===== -->
<div id="pf-hysteria" class="hidden">
<div class="form-row">
<label>Auth (строка)</label>
<input type="text" id="hyAuthStr" placeholder="yourpassword">
</div>
<div class="form-row">
<label>Protocol</label>
<select id="hyProtocol" class="field-select">
<option value="udp">udp</option>
<option value="wechat-video">wechat-video</option>
<option value="faketcp">faketcp</option>
</select>
</div>
<div class="form-row">
<label>Up (напр. 30 Mbps)</label>
<input type="text" id="hyUp" placeholder="30 Mbps">
</div>
<div class="form-row">
<label>Down (напр. 200 Mbps)</label>
<input type="text" id="hyDown" placeholder="200 Mbps">
</div>
<div class="form-row">
<label>Obfs</label>
<input type="text" id="hyObfs" placeholder="obfs строка (опционально)">
</div>
<div class="form-row">
<label>Ports (port hopping)</label>
<input type="text" id="hyPorts" placeholder="1000,2000-3000,4000">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="hyFastOpen">
<span>Fast Open</span>
</label>
</div>
</div>
<!-- ===== Hysteria2 ===== -->
<div id="pf-hysteria2" class="hidden">
<div class="form-row">
<label>Пароль</label>
<input type="text" id="hy2Password" placeholder="yourpassword">
</div>
<div class="form-row">
<label>Up (напр. 30 Mbps)</label>
<input type="text" id="hy2Up" placeholder="30 Mbps">
</div>
<div class="form-row">
<label>Down (напр. 200 Mbps)</label>
<input type="text" id="hy2Down" placeholder="200 Mbps">
</div>
<div class="form-row">
<label>Obfs тип</label>
<select id="hy2ObfsType" class="field-select">
<option value="">Нет</option>
<option value="salamander">salamander</option>
</select>
</div>
<div class="form-row">
<label>Obfs пароль</label>
<input type="text" id="hy2ObfsPassword" placeholder="obfs password">
</div>
<div class="form-row">
<label>Ports (port hopping)</label>
<input type="text" id="hy2Ports" placeholder="443-8443">
</div>
<div class="form-row">
<label>Hop Interval (сек)</label>
<input type="number" id="hy2HopInterval" placeholder="30">
</div>
</div>
<!-- ===== TUIC ===== -->
<div id="pf-tuic" class="hidden">
<div class="form-row">
<label>Версия</label>
<div class="segmented" id="tuicVersionSwitch">
<button type="button" class="seg-btn" data-mode="4">v4</button>
<button type="button" class="seg-btn active" data-mode="5">v5</button>
</div>
</div>
<div class="form-row" id="pf-tuic-token">
<label>Token (v4)</label>
<input type="text" id="tuicToken" placeholder="TOKEN">
</div>
<div id="pf-tuic-v5-auth">
<div class="form-row">
<label>UUID (v5)</label>
<input type="text" id="tuicUUID" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
</div>
<div class="form-row">
<label>Пароль (v5)</label>
<input type="text" id="tuicPassword" placeholder="PASSWORD">
</div>
</div>
<div class="form-row">
<label>IP (переопределить DNS)</label>
<input type="text" id="tuicIP" placeholder="127.0.0.1 (опционально)">
</div>
<div class="form-row">
<label>Heartbeat Interval (мс)</label>
<input type="number" id="tuicHeartbeat" placeholder="10000">
</div>
<div class="form-row">
<label>UDP Relay Mode</label>
<select id="tuicUDPMode" class="field-select">
<option value="native">native</option>
<option value="quic">quic</option>
</select>
</div>
<div class="form-row">
<label>Congestion Controller</label>
<select id="tuicCongestion" class="field-select">
<option value="">по умолчанию</option>
<option value="cubic">cubic</option>
<option value="new_reno">new_reno</option>
<option value="bbr">bbr</option>
</select>
</div>
<div class="form-row">
<label>Max UDP Relay Packet Size</label>
<input type="number" id="tuicMaxUDP" placeholder="1500">
</div>
<div class="form-row">
<label>Request Timeout (мс)</label>
<input type="number" id="tuicReqTimeout" placeholder="8000">
</div>
<div class="form-row">
<label>Max Open Streams</label>
<input type="number" id="tuicMaxStreams" placeholder="20">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="tuicDisableSNI">
<span>Disable SNI</span>
</label>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="tuicReduceRTT">
<span>Reduce RTT (0-RTT)</span>
</label>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="tuicFastOpen">
<span>Fast Open</span>
</label>
</div>
</div>
<!-- ===== WireGuard ===== -->
<div id="pf-wireguard" class="hidden">
<div class="form-row">
<label>Private Key (base64)</label>
<input type="text" id="wgPrivateKey" placeholder="eCtXsJZ27+4PbhDk...">
</div>
<div class="form-row">
<label>Local IP (IPv4)</label>
<input type="text" id="wgIP" placeholder="172.16.0.2">
</div>
<div class="form-row">
<label>Local IPv6 (опционально)</label>
<input type="text" id="wgIPv6" placeholder="fd01:5ca1:ab1e::1">
</div>
<div class="form-row">
<label>Public Key (сервер)</label>
<input type="text" id="wgPublicKey" placeholder="Cr8hWlKvtDt7nrvf...">
</div>
<div class="form-row">
<label>Allowed IPs</label>
<input type="text" id="wgAllowedIPs" value="0.0.0.0/0" placeholder="0.0.0.0/0, ::/0">
</div>
<div class="form-row">
<label>Pre-Shared Key (опционально)</label>
<input type="text" id="wgPreSharedKey" placeholder="">
</div>
<div class="form-row">
<label>Reserved (опционально)</label>
<input type="text" id="wgReserved" placeholder="209,98,59 или U4An">
</div>
<div class="form-row">
<label>MTU (опционально)</label>
<input type="number" id="wgMTU" placeholder="1408">
</div>
<div class="form-row">
<label>Persistent Keepalive (сек)</label>
<input type="number" id="wgKeepalive" placeholder="0">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="wgRemoteDNS">
<span>Remote DNS Resolve</span>
</label>
</div>
<div class="form-row">
<label>DNS (через запятую)</label>
<input type="text" id="wgDNS" placeholder="1.1.1.1, 8.8.8.8">
</div>
<div class="form-row">
<label>Dialer Proxy</label>
<input type="text" id="wgDialerProxy" placeholder="имя прокси (опционально)">
</div>
</div>
<!-- ===== Snell ===== -->
<div id="pf-snell" class="hidden">
<div class="form-row">
<label>PSK (pre-shared key)</label>
<input type="text" id="snellPSK" placeholder="yourpsk">
</div>
<div class="form-row">
<label>Версия</label>
<select id="snellVersion" class="field-select">
<option value="1">1</option>
<option value="2">2</option>
<option value="3" selected>3</option>
<option value="4">4</option>
</select>
</div>
<div class="form-row">
<label>Obfs Mode</label>
<select id="snellObfsMode" class="field-select">
<option value="">Нет</option>
<option value="http">http</option>
<option value="tls">tls</option>
</select>
</div>
<div class="form-row" id="pf-snell-obfs-host">
<label>Obfs Host</label>
<input type="text" id="snellObfsHost" placeholder="bing.com">
</div>
</div>
<!-- ===== SSH ===== -->
<div id="pf-ssh" class="hidden">
<div class="form-row">
<label>Username</label>
<input type="text" id="sshUsername" placeholder="root">
</div>
<div class="form-row">
<label>Пароль</label>
<input type="text" id="sshPassword" placeholder="password (опционально)">
</div>
<div class="form-row">
<label>Private Key (PEM или путь)</label>
<textarea id="sshPrivateKey" rows="3" class="mono-ta" placeholder="-----BEGIN OPENSSH PRIVATE KEY-----&#10;...&#10;или путь к файлу"></textarea>
</div>
<div class="form-row">
<label>Private Key Passphrase</label>
<input type="text" id="sshPrivateKeyPass" placeholder="passphrase (опционально)">
</div>
<div class="form-row">
<label>Host Key (по строке)</label>
<textarea id="sshHostKey" rows="2" class="mono-ta" placeholder="ssh-rsa AAAAB3NzaC1yc2EAA... (пусто = принимать все)"></textarea>
</div>
<div class="form-row">
<label>Host Key Algorithms (по строке)</label>
<textarea id="sshHostKeyAlgos" rows="2" class="mono-ta" placeholder="rsa&#10;ecdsa"></textarea>
</div>
</div>
<!-- ===== AnyTLS ===== -->
<div id="pf-anytls" class="hidden">
<div class="form-row">
<label>Пароль</label>
<input type="text" id="anytlsPassword" placeholder="password">
</div>
</div>
<!-- ===== Mieru ===== -->
<div id="pf-mieru" class="hidden">
<div class="form-row">
<label>Username</label>
<input type="text" id="mieruUsername" placeholder="username">
</div>
<div class="form-row">
<label>Пароль</label>
<input type="text" id="mieruPassword" placeholder="password">
</div>
<div class="form-row">
<label>Transport</label>
<select id="mieruTransport" class="field-select">
<option value="TCP">TCP</option>
<option value="UDP">UDP</option>
</select>
</div>
</div>
<!-- ===== HTTP / SOCKS5 ===== -->
<div id="pf-http-auth" class="hidden">
<div class="form-row">
<label>Username (опционально)</label>
<input type="text" id="httpUsername" placeholder="username">
</div>
<div class="form-row">
<label>Пароль (опционально)</label>
<input type="text" id="httpPassword" placeholder="password">
</div>
<div class="form-row" id="pf-http-headers-row">
<label>Headers (key: value, по строке)</label>
<textarea id="httpHeaders" rows="2" class="mono-ta" placeholder="X-Custom: value"></textarea>
</div>
</div>
<!-- ===== TRANSPORT SECTION ===== -->
<div id="pf-transport-section" class="hidden">
<div class="form-divider"></div>
<div class="pf-section-title">Транспорт</div>
<div class="form-row">
<label>Network</label>
<select id="proxyNetwork" class="field-select">
<option value="">tcp (по умолчанию)</option>
<option value="ws">WebSocket (ws)</option>
<option value="h2">HTTP/2 (h2)</option>
<option value="grpc">gRPC</option>
<option value="http">HTTP</option>
<option value="xhttp">XHTTP (только VLESS)</option>
</select>
</div>
<!-- WS opts -->
<div id="pf-ws-opts" class="hidden">
<div class="form-row">
<label>WS Path</label>
<input type="text" id="wsPath" placeholder="/path">
</div>
<div class="form-row">
<label>WS Host (заголовок)</label>
<input type="text" id="wsHost" placeholder="example.com">
</div>
<div class="form-row">
<label>Max Early Data</label>
<input type="number" id="wsMaxEarlyData" placeholder="0">
</div>
<div class="form-row">
<label>Early Data Header Name</label>
<input type="text" id="wsEarlyDataHeader" placeholder="">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="wsV2rayUpgrade">
<span>v2ray-http-upgrade</span>
</label>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="wsV2rayUpgradeFO">
<span>v2ray-http-upgrade-fast-open</span>
</label>
</div>
</div>
<!-- H2 opts -->
<div id="pf-h2-opts" class="hidden">
<div class="form-row">
<label>H2 Host (по строке)</label>
<textarea id="h2Host" rows="2" class="mono-ta" placeholder="example.com"></textarea>
</div>
<div class="form-row">
<label>H2 Path</label>
<input type="text" id="h2Path" placeholder="/">
</div>
</div>
<!-- gRPC opts -->
<div id="pf-grpc-opts" class="hidden">
<div class="form-row">
<label>gRPC Service Name</label>
<input type="text" id="grpcServiceName" placeholder="example">
</div>
<div class="form-row">
<label>gRPC User-Agent</label>
<input type="text" id="grpcUserAgent" placeholder="">
</div>
</div>
<!-- HTTP transport opts -->
<div id="pf-http-transport-opts" class="hidden">
<div class="form-row">
<label>HTTP Method</label>
<select id="httpTransportMethod" class="field-select">
<option value="GET">GET</option>
<option value="POST">POST</option>
<option value="PUT">PUT</option>
</select>
</div>
<div class="form-row">
<label>HTTP Path (по строке)</label>
<textarea id="httpTransportPath" rows="2" class="mono-ta" placeholder="/&#10;/video"></textarea>
</div>
</div>
<!-- XHTTP opts -->
<div id="pf-xhttp-opts" class="hidden">
<div class="form-row">
<label>XHTTP Path</label>
<input type="text" id="xhttpPath" placeholder="/">
</div>
<div class="form-row">
<label>XHTTP Host</label>
<input type="text" id="xhttpHost" placeholder="example.com">
</div>
<div class="form-row">
<label>XHTTP Mode</label>
<select id="xhttpMode" class="field-select">
<option value="">auto</option>
<option value="stream-one">stream-one</option>
<option value="stream-up">stream-up</option>
<option value="packet-up">packet-up</option>
</select>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="xhttpNoGRPC">
<span>No gRPC Header</span>
</label>
</div>
<div class="form-row">
<label>X-Padding-Bytes</label>
<input type="text" id="xhttpPaddingBytes" placeholder="100-1000">
</div>
</div>
</div>
<!-- ===== TLS SECTION ===== -->
<div id="pf-tls-section" class="hidden">
<div class="form-divider"></div>
<div class="pf-section-title">TLS</div>
<div class="form-row" id="pf-tls-toggle-row">
<label class="checkbox-label">
<input type="checkbox" id="proxyTLS">
<span>Включить TLS</span>
</label>
</div>
<div id="pf-tls-fields" class="hidden">
<div class="form-row">
<label>SNI / Servername</label>
<input type="text" id="proxySNI" placeholder="example.com">
</div>
<div class="form-row">
<label>Fingerprint (SHA256)</label>
<input type="text" id="proxyFingerprint" placeholder="xx:xx:xx:... (опционально)">
</div>
<div class="form-row">
<label>ALPN (по строке)</label>
<textarea id="proxyALPN" rows="2" class="mono-ta" placeholder="h2&#10;http/1.1"></textarea>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="proxySkipCertVerify">
<span>Skip Cert Verify</span>
</label>
</div>
<div class="form-row" id="pf-client-fp-row">
<label>Client Fingerprint</label>
<select id="proxyClientFP" class="field-select">
<option value="">Нет</option>
<option value="chrome">chrome</option>
<option value="firefox">firefox</option>
<option value="safari">safari</option>
<option value="ios">ios</option>
<option value="android">android</option>
<option value="edge">edge</option>
<option value="360">360</option>
<option value="qq">qq</option>
<option value="random">random</option>
</select>
</div>
<!-- Reality -->
<div id="pf-reality-section">
<div class="form-divider" style="margin:10px 0"></div>
<div class="pf-subsection-title">Reality (опционально)</div>
<div class="form-row">
<label>Public Key</label>
<input type="text" id="realityPublicKey" placeholder="base64 публичный ключ">
</div>
<div class="form-row">
<label>Short ID</label>
<input type="text" id="realityShortID" placeholder="short_id">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="realityX25519mlkem">
<span>Support X25519-MLKEM768</span>
</label>
</div>
</div>
<!-- ECH -->
<div id="pf-ech-section">
<div class="form-divider" style="margin:10px 0"></div>
<div class="pf-subsection-title">ECH (опционально)</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="echEnable">
<span>Включить ECH</span>
</label>
</div>
<div class="form-row">
<label>ECH Config (base64)</label>
<textarea id="echConfig" rows="2" class="mono-ta" placeholder="AEn+DQBFKwAgACA..."></textarea>
</div>
<div class="form-row">
<label>ECH Query Server Name</label>
<input type="text" id="echQuerySNI" placeholder="опционально">
</div>
</div>
</div>
</div>
<!-- ===== ADVANCED / COMMON ===== -->
<div class="form-divider"></div>
<div class="pf-section-title">Дополнительно</div>
<div class="form-row" id="pf-udp-row">
<label class="checkbox-label">
<input type="checkbox" id="proxyUDP" checked>
<span>UDP</span>
</label>
</div>
<div class="form-row">
<label>IP Version</label>
<select id="proxyIPVersion" class="field-select">
<option value="">dual (по умолчанию)</option>
<option value="ipv4">ipv4</option>
<option value="ipv6">ipv6</option>
<option value="ipv4-prefer">ipv4-prefer</option>
<option value="ipv6-prefer">ipv6-prefer</option>
</select>
</div>
<div class="form-row">
<label>Interface Name</label>
<input type="text" id="proxyInterface" placeholder="eth0 (опционально)">
</div>
<div class="form-row">
<label>Routing Mark</label>
<input type="number" id="proxyRoutingMark" placeholder="опционально">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="proxyTFO">
<span>TCP Fast Open (TFO)</span>
</label>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="proxyMPTCP">
<span>MPTCP</span>
</label>
</div>
<div class="form-row" id="pf-dialer-proxy-row">
<label>Dialer Proxy</label>
<input type="text" id="proxyDialerProxy" placeholder="имя прокси или группы">
</div>
<input type="hidden" id="proxyEditName" value="">
</form>
<div class="modal-footer">
<button class="btn btn-ghost" id="cancelProxyBtn">Отмена</button>
<button class="btn btn-primary" id="saveProxyBtn">Сохранить</button>
</div>
</div>
</div>
<!-- ===================== GROUP MODAL ===================== -->
<div id="groupModal" class="modal hidden" role="dialog" aria-modal="true">
<div class="modal-backdrop" id="groupModalBackdrop"></div>
<div class="modal-box" style="width:min(580px,calc(100vw - 40px))">
<div class="modal-header">
<h2 id="groupModalTitle">Добавить группу</h2>
<button class="btn-icon" id="closeGroupModal" title="Закрыть"></button>
</div>
<form id="groupForm" autocomplete="off" style="max-height:52vh;overflow-y:auto;padding-right:4px">
<div class="form-row">
<label for="groupName">Имя группы</label>
<input type="text" id="groupName" placeholder="proxy">
</div>
<div class="form-row">
<label for="groupType">Тип</label>
<select id="groupType" class="field-select">
<option value="select">Select (ручной выбор)</option>
<option value="url-test">URL-test (автовыбор по задержке)</option>
<option value="fallback">Fallback (резервный)</option>
<option value="load-balance">Load Balance (балансировка)</option>
<option value="relay">Relay (цепочка)</option>
</select>
</div>
<div id="groupURLField" class="hidden">
<div class="form-row">
<label for="groupURL">URL тестирования</label>
<input type="text" id="groupURL" value="https://www.gstatic.com/generate_204">
</div>
<div class="form-row">
<label for="groupInterval">Интервал тестирования (сек)</label>
<input type="number" id="groupInterval" value="300">
</div>
<div class="form-row">
<label for="groupTimeout">Timeout (мс)</label>
<input type="number" id="groupTimeout" value="5000" placeholder="5000">
</div>
<div class="form-row">
<label for="groupTolerance">Допуск (мс, для url-test)</label>
<input type="number" id="groupTolerance" value="50" placeholder="50">
</div>
<div class="form-row">
<label for="groupMaxFailed">Max Failed Times</label>
<input type="number" id="groupMaxFailed" value="5" placeholder="5">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="groupLazy" checked>
<span>Lazy (не тестировать без использования)</span>
</label>
</div>
</div>
<div id="groupLBStrategyDiv" class="hidden">
<div class="form-row">
<label>Стратегия балансировки</label>
<select id="groupLBStrategy" class="field-select">
<option value="round-robin">Round Robin</option>
<option value="consistent-hashing">Consistent Hashing</option>
<option value="sticky-sessions">Sticky Sessions</option>
</select>
</div>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="groupDisableUDP">
<span>Disable UDP</span>
</label>
</div>
<div class="form-row">
<label>Прокси-ноды в группе</label>
<div id="groupProxyCheckboxes" style="max-height:180px;overflow-y:auto;background:var(--bg-deep);border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px"></div>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="groupIncludeAll">
<span>Включить все прокси автоматически (include-all)</span>
</label>
</div>
<div class="form-row">
<label for="groupFilter">Фильтр (regex)</label>
<input type="text" id="groupFilter" placeholder="(?i)hk|hongkong">
</div>
<div class="form-row">
<label for="groupExcludeFilter">Exclude Filter (regex)</label>
<input type="text" id="groupExcludeFilter" placeholder="">
</div>
<div class="form-row">
<label for="groupExcludeType">Exclude Type (через |)</label>
<input type="text" id="groupExcludeType" placeholder="ss|vmess">
</div>
<div class="form-row">
<label for="groupExpectedStatus">Expected Status</label>
<input type="text" id="groupExpectedStatus" placeholder="204 или 200/204">
</div>
<input type="hidden" id="groupEditName" value="">
</form>
<div class="modal-footer">
<button class="btn btn-ghost" id="cancelGroupBtn">Отмена</button>
<button class="btn btn-primary" id="saveGroupBtn">Сохранить</button>
</div>
</div>
</div>
<!-- ===================== RULE MODAL ===================== -->
<div id="ruleModal" class="modal hidden" role="dialog" aria-modal="true">
<div class="modal-backdrop" id="ruleModalBackdrop"></div>
<div class="modal-box" style="width:min(520px,calc(100vw - 40px))">
<div class="modal-header">
<h2 id="ruleModalTitle">Добавить правило</h2>
<button class="btn-icon" id="closeRuleModal" title="Закрыть"></button>
</div>
<form id="ruleForm" autocomplete="off">
<div class="form-row">
<label for="ruleType">Тип правила</label>
<select id="ruleType" class="field-select">
<optgroup label="Домен">
<option value="DOMAIN">DOMAIN</option>
<option value="DOMAIN-SUFFIX">DOMAIN-SUFFIX</option>
<option value="DOMAIN-KEYWORD">DOMAIN-KEYWORD</option>
<option value="DOMAIN-WILDCARD">DOMAIN-WILDCARD</option>
<option value="DOMAIN-REGEX">DOMAIN-REGEX</option>
<option value="GEOSITE">GEOSITE</option>
</optgroup>
<optgroup label="IP">
<option value="IP-CIDR">IP-CIDR</option>
<option value="IP-CIDR6">IP-CIDR6</option>
<option value="IP-SUFFIX">IP-SUFFIX</option>
<option value="IP-ASN">IP-ASN</option>
<option value="GEOIP">GEOIP</option>
</optgroup>
<optgroup label="Источник">
<option value="SRC-IP-CIDR">SRC-IP-CIDR</option>
<option value="SRC-IP-SUFFIX">SRC-IP-SUFFIX</option>
<option value="SRC-IP-ASN">SRC-IP-ASN</option>
<option value="SRC-GEOIP">SRC-GEOIP</option>
<option value="SRC-PORT">SRC-PORT</option>
</optgroup>
<optgroup label="Порт / Сеть">
<option value="DST-PORT">DST-PORT</option>
<option value="IN-PORT">IN-PORT</option>
<option value="NETWORK">NETWORK</option>
<option value="DSCP">DSCP</option>
</optgroup>
<optgroup label="Процесс">
<option value="PROCESS-NAME">PROCESS-NAME</option>
<option value="PROCESS-PATH">PROCESS-PATH</option>
</optgroup>
<optgroup label="Входящее соединение">
<option value="IN-TYPE">IN-TYPE</option>
</optgroup>
<optgroup label="Наборы правил">
<option value="RULE-SET">RULE-SET</option>
</optgroup>
<optgroup label="Прочие">
<option value="MATCH">MATCH (всё)</option>
</optgroup>
</select>
</div>
<div id="ruleValueField" class="form-row">
<label for="ruleValue">Значение</label>
<input type="text" id="ruleValue" placeholder="напр. google.com или 192.168.0.0/16">
</div>
<div class="form-row">
<label for="ruleProxy">Прокси / Группа</label>
<select id="ruleProxy" class="field-select">
<option value="DIRECT">DIRECT</option>
<option value="REJECT">REJECT</option>
<option value="REJECT-DROP">REJECT-DROP</option>
</select>
</div>
<div id="ruleNoResolveDiv" class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="ruleNoResolve" checked>
<span>no-resolve</span>
</label>
</div>
</form>
<div class="modal-footer">
<button class="btn btn-ghost" id="cancelRuleBtn">Отмена</button>
<button class="btn btn-primary" id="saveRuleBtn">Добавить</button>
</div>
</div>
</div>
<!-- ===================== PROXY PROVIDER MODAL ===================== -->
<div id="proxyProviderModal" class="modal hidden" role="dialog" aria-modal="true">
<div class="modal-backdrop" id="ppModalBackdrop"></div>
<div class="modal-box" style="width:min(580px,calc(100vw - 40px))">
<div class="modal-header">
<h2 id="ppModalTitle">Добавить провайдер прокси</h2>
<button class="btn-icon" id="closePPModal"></button>
</div>
<form id="ppForm" autocomplete="off" style="max-height:52vh;overflow-y:auto;padding-right:4px">
<div class="form-row">
<label>Имя</label>
<input type="text" id="ppName" placeholder="provider1">
</div>
<div class="form-row">
<label>Тип</label>
<select id="ppType" class="field-select">
<option value="http">http (по URL)</option>
<option value="file">file (локальный файл)</option>
<option value="inline">inline (встроенный)</option>
</select>
</div>
<div class="form-row" id="pp-url-row">
<label>URL</label>
<input type="text" id="ppURL" placeholder="http://example.com/proxies.yaml">
</div>
<div class="form-row">
<label>Path (локальный путь)</label>
<input type="text" id="ppPath" placeholder="./proxy_providers/provider1.yaml">
</div>
<div class="form-row" id="pp-interval-row">
<label>Интервал обновления (сек)</label>
<input type="number" id="ppInterval" value="3600">
</div>
<div class="form-row">
<label>Proxy для скачивания</label>
<input type="text" id="ppProxy" placeholder="DIRECT">
</div>
<div class="form-divider"></div>
<div class="pf-subsection-title">Health Check</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="ppHCEnable" checked>
<span>Включить Health Check</span>
</label>
</div>
<div class="form-row">
<label>Health Check URL</label>
<input type="text" id="ppHCURL" value="https://www.gstatic.com/generate_204">
</div>
<div class="form-row">
<label>HC Интервал (сек)</label>
<input type="number" id="ppHCInterval" value="300">
</div>
<div class="form-row">
<label>HC Timeout (мс)</label>
<input type="number" id="ppHCTimeout" value="5000">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="ppHCLazy" checked>
<span>Lazy (не проверять без использования)</span>
</label>
</div>
<div class="form-divider"></div>
<div class="pf-subsection-title">Фильтрация</div>
<div class="form-row">
<label>Filter (regex)</label>
<input type="text" id="ppFilter" placeholder="(?i)hk|hongkong">
</div>
<div class="form-row">
<label>Exclude Filter (regex)</label>
<input type="text" id="ppExcludeFilter" placeholder="">
</div>
<div class="form-row">
<label>Exclude Type (через |)</label>
<input type="text" id="ppExcludeType" placeholder="ss|vmess">
</div>
<div class="form-divider"></div>
<div class="pf-subsection-title">Override (переопределение полей нод)</div>
<div class="form-row">
<label>Additional Prefix</label>
<input type="text" id="ppOverridePrefix" placeholder="">
</div>
<div class="form-row">
<label>Additional Suffix</label>
<input type="text" id="ppOverrideSuffix" placeholder="">
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="ppOverrideSkipCert">
<span>skip-cert-verify</span>
</label>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="ppOverrideUDP">
<span>udp: true</span>
</label>
</div>
<div class="form-row">
<label>IP Version override</label>
<select id="ppOverrideIPVersion" class="field-select">
<option value="">Не переопределять</option>
<option value="ipv4">ipv4</option>
<option value="ipv6">ipv6</option>
<option value="ipv4-prefer">ipv4-prefer</option>
<option value="ipv6-prefer">ipv6-prefer</option>
</select>
</div>
<input type="hidden" id="ppEditName" value="">
</form>
<div class="modal-footer">
<button class="btn btn-ghost" id="cancelPPBtn">Отмена</button>
<button class="btn btn-primary" id="savePPBtn">Сохранить</button>
</div>
</div>
</div>
<!-- ===================== RULE PROVIDER MODAL ===================== -->
<div id="ruleProviderModal" class="modal hidden" role="dialog" aria-modal="true">
<div class="modal-backdrop" id="rpModalBackdrop"></div>
<div class="modal-box" style="width:min(540px,calc(100vw - 40px))">
<div class="modal-header">
<h2 id="rpModalTitle">Добавить провайдер правил</h2>
<button class="btn-icon" id="closeRPModal"></button>
</div>
<form id="rpForm" autocomplete="off">
<div class="form-row">
<label>Имя</label>
<input type="text" id="rpName" placeholder="google">
</div>
<div class="form-row">
<label>Тип</label>
<select id="rpType" class="field-select">
<option value="http">http (по URL)</option>
<option value="file">file (локальный файл)</option>
<option value="inline">inline (встроенный)</option>
</select>
</div>
<div class="form-row">
<label>Behavior</label>
<select id="rpBehavior" class="field-select">
<option value="domain">domain</option>
<option value="ipcidr">ipcidr</option>
<option value="classical">classical</option>
</select>
</div>
<div class="form-row">
<label>Format</label>
<select id="rpFormat" class="field-select">
<option value="yaml">yaml</option>
<option value="text">text</option>
<option value="mrs">mrs</option>
</select>
</div>
<div class="form-row" id="rp-url-row">
<label>URL</label>
<input type="text" id="rpURL" placeholder="https://raw.githubusercontent.com/.../Google.yaml">
</div>
<div class="form-row">
<label>Path (локальный путь)</label>
<input type="text" id="rpPath" placeholder="./rule1.yaml">
</div>
<div class="form-row" id="rp-interval-row">
<label>Интервал обновления (сек)</label>
<input type="number" id="rpInterval" value="600">
</div>
<div class="form-row">
<label>Proxy для скачивания</label>
<input type="text" id="rpProxy" placeholder="DIRECT">
</div>
<input type="hidden" id="rpEditName" value="">
</form>
<div class="modal-footer">
<button class="btn btn-ghost" id="cancelRPBtn">Отмена</button>
<button class="btn btn-primary" id="saveRPBtn">Сохранить</button>
</div>
</div>
</div>
<div id="toast" class="toast hidden"></div>
<script src="proxy.js"></script>
</body>
</html>