Files
kaskad_web_vpn/templates/index.html
Андрей Бобырев 43daf188c2 feat: first-run /setup password + PRO-style iptables
compat DNAT/INPUT/FORWARD/MASQUERADE; optional chain mode; auth_store hash; static absolute URLs; install skips env password by default; README.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 20:52:35 +03:00

127 lines
5.8 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">
<title>{{ ui_title }}</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<base href="/">
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;600;700&family=JetBrains+Mono:wght@400&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/styles.css">
</head>
<body>
<div class="shell shell-wide">
<div class="top-bar">
<h1 class="product-title">{{ ui_title }}</h1>
<button type="button" class="btn btn-ghost" id="btn-refresh" title="Обновить данные">Обновить</button>
</div>
<header class="site-header">
<div class="support-line">
<span class="support-title">Поддержка автора</span>
<span class="sep" aria-hidden="true">·</span>
<a href="https://github.com/andrey271192/kaskad_web_vpn" target="_blank" rel="noopener noreferrer">GitHub</a>
<span class="sep">·</span>
<a href="https://boosty.to/andrey27/donate" target="_blank" rel="noopener noreferrer">Boosty</a>
<span class="sep">·</span>
<a href="https://finance.ozon.ru/apps/sbp/ozonbankpay/019dc200-2a5d-7931-a619-782d285f6798" target="_blank" rel="noopener noreferrer">Ozon&nbsp;СБП</a>
<span class="sep">·</span>
<a href="https://t.me/lot_andrey" target="_blank" rel="noopener noreferrer">Telegram @lot_andrey</a>
</div>
{% if panel_url %}
<p class="support-blurb">Панель Amnezia / доп.: <a href="{{ panel_url }}">{{ panel_url }}</a></p>
{% else %}
<p class="support-blurb">Открытый исходный код, без сторонней рекламы на странице.</p>
{% endif %}
</header>
<section class="card" id="sec-system">
<h2 class="card-title">Система</h2>
<div class="sys-grid" id="system-grid"></div>
</section>
<section class="card" id="sec-services">
<h2 class="card-title">Сервисы</h2>
<div class="table-wrap">
<table class="data-table" id="tbl-services">
<thead>
<tr><th>UNIT</th><th>ACTIVE</th><th>ENABLED</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
</section>
<section class="card" id="sec-clients">
<div class="card-head">
<h2 class="card-title">Клиенты (правила NAT)</h2>
<button type="button" class="btn" id="btn-add-client">+ Добавить клиента</button>
</div>
<div class="table-wrap table-scroll">
<table class="data-table" id="tbl-clients">
<thead>
<tr>
<th>USER</th><th>PROTO</th><th>IN</th><th></th><th>TARGET</th><th>OUT</th>
<th>ЗАМЕТКА</th><th>ГДЕ</th><th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</section>
<details class="panel-fold card-inner" id="fold-iptables">
<summary class="fold-sum">
<span class="fold-arrow" aria-hidden="true"></span>
<span class="fold-h">Сырые iptables правила (kaskad)</span>
</summary>
<div class="fold-body">
<button type="button" class="btn btn-sm" id="btn-load-iptables">Показать</button>
<pre class="mono-block" id="iptables-out"></pre>
</div>
</details>
<section class="card">
<h2 class="card-title">Мониторы</h2>
<p class="muted pad-v">— нет ни одного —</p>
</section>
<footer class="site-footer">
{% if iptables_mode == 'chain' %}
Kaskad Web UI · <a href="https://github.com/andrey271192/kaskad_web_vpn">kaskad_web_vpn</a> · HTTP Basic Auth · DNAT в цепочке <span class="mono">KASKAD_WEB</span> (nat).
{% else %}
Kaskad Web UI · <a href="https://github.com/andrey271192/kaskad_web_vpn">kaskad_web_vpn</a> · HTTP Basic Auth · режим как у Kaskad PRO: DNAT в <span class="mono">PREROUTING</span>, метки <span class="mono">kaskad:PORT:proto</span> в INPUT/FORWARD, <span class="mono">MASQUERADE</span> на исходящем интерфейсе (<span class="mono">KASKAD_IPTABLES_MODE=compat</span>).
{% endif %}
</footer>
</div>
<div class="modal-overlay" id="modal-overlay" hidden>
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title">
<h3 id="modal-title">Клиент</h3>
<form id="form-client" class="form-grid">
<input type="hidden" name="id" id="f-id">
<label>USER <input name="user" id="f-user" required maxlength="64" autocomplete="off"></label>
<label>PROTO
<select name="proto" id="f-proto">
<option value="udp">udp</option>
<option value="tcp">tcp</option>
</select>
</label>
<label>IN (порт) <input name="in_port" id="f-in" type="number" required min="1" max="65535"></label>
<label>TARGET (IPv4) <input name="target" id="f-target" required autocomplete="off" placeholder="10.0.0.5"></label>
<label>OUT (порт) <input name="out_port" id="f-out" type="number" required min="1" max="65535"></label>
<label class="span-2">ЗАМЕТКА <input name="note" id="f-note" maxlength="256" autocomplete="off"></label>
<label class="span-2">ГДЕ <input name="where" id="f-where" maxlength="256" autocomplete="off" placeholder="Netherlands · узел …"></label>
<div class="modal-actions span-2">
<button type="submit" class="btn">Сохранить</button>
<button type="button" class="btn btn-ghost" id="modal-cancel">Отмена</button>
</div>
</form>
</div>
</div>
<script src="/static/dashboard.js" defer></script>
</body>
</html>