Files
kaskad_web_vpn/templates/index.html
Андрей Бобырев 23f5649651 feat: kaskad memo site with Basic Auth
Flask + Docker, header support links, install/uninstall curl scripts, password file or ADMIN_PASSWORD.

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

145 lines
7.5 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>Каскад AmneziaWG — памятка</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<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="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="shell">
<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>
<p class="support-blurb">Звезда репозиторию и донат помогают развивать утилиты. На этой странице нет сторонней рекламы.</p>
</header>
<p class="eyebrow">VPN · каскад</p>
<h1>Каскад для AmneziaWG</h1>
<p class="lead">
Краткая памятка: клиент подключается сначала к вашему <strong>промежуточному узлу</strong> (Endpoint),
а ключ и peer создаются на основном сервере AmneziaWG. Эта страница только объясняет шаги и может собрать текст-памятку;
генерация <span class="inline-code">.conf</span> выполняется в вашей <strong>админ-панели</strong> или вручную.
</p>
{% if panel_url %}
<p class="muted">Ваша панель: <a href="{{ panel_url }}">{{ panel_url }}</a></p>
{% endif %}
<details class="panel-fold" open>
<summary>
<span class="fold-arrow" aria-hidden="true"></span>
<span class="fold-h">Что такое каскад</span>
</summary>
<div class="fold-body">
<p class="muted">
В конфиге клиента поле <span class="inline-code">Endpoint</span> указывает на IP или DNS узла «перед» VPS
(домашний роутер с пробросом UDP, другой VPS и т.д.). На этом узле нужен проброс порта на ваш основной сервер WireGuard/AWG.
Сервер AmneziaWG добавляет peer и выдаёт готовый <span class="inline-code">.conf</span>.
</p>
</div>
</details>
<details class="panel-fold" open>
<summary>
<span class="fold-arrow" aria-hidden="true"></span>
<span class="fold-h">Через панель Amnezia Admin</span>
</summary>
<div class="fold-body">
<p class="muted">
Если установлена <strong>Amnezia Admin WebUI</strong>, откройте блок <strong>«Новый клиент под каскад»</strong>:
укажите Endpoint (ваш публичный IP/DNS узла и при необходимости порт), затем скачайте <span class="inline-code">.conf</span>.
</p>
<p class="muted">
Репозиторий панели:
<a href="https://github.com/andrey271192/Amnezia_web" target="_blank" rel="noopener noreferrer">github.com/andrey271192/Amnezia_web</a>
</p>
</div>
</details>
<details class="panel-fold">
<summary>
<span class="fold-arrow" aria-hidden="true"></span>
<span class="fold-h">Собрать памятку (локально в браузере)</span>
</summary>
<div class="fold-body">
<p class="muted">Данные не отправляются на сервер — только текст для копирования.</p>
<div class="grid-form">
<label for="ep-host">Endpoint (хост для клиента)</label>
<input id="ep-host" type="text" placeholder="203.0.113.50 или ddns.example.com" autocomplete="off">
<label for="ep-port">Порт Endpoint (если пусто — как у сервера)</label>
<input id="ep-port" type="number" min="1" max="65535" placeholder="51820" autocomplete="off">
<label for="memo-name">Имя клиента (произвольно)</label>
<input id="memo-name" type="text" placeholder="Телефон через узел X" autocomplete="off">
<div class="btn-row">
<button type="button" class="btn" id="btn-build">Собрать текст</button>
<button type="button" class="btn" id="btn-copy">Копировать</button>
</div>
</div>
<pre class="out-box" id="out-memo" aria-live="polite"></pre>
</div>
</details>
<details class="panel-fold">
<summary>
<span class="fold-arrow" aria-hidden="true"></span>
<span class="fold-h">Проброс UDP</span>
</summary>
<div class="fold-body">
<p class="muted">
На промежуточном узле пробросьте UDP с выбранного порта на IP VPS и порт, где слушает ваш инстанс AmneziaWG.
Убедитесь, что фаервол не режет входящий UDP.
</p>
</div>
</details>
<footer class="site-footer">
Сервис: HTTP Basic Auth (realm «kaskad»). Установка одной ссылкой — см. README репозитория kaskad_web_vpn.
</footer>
</div>
<script>
(function () {
function buildText() {
var host = (document.getElementById("ep-host").value || "").trim();
var port = (document.getElementById("ep-port").value || "").trim();
var name = (document.getElementById("memo-name").value || "").trim() || "клиент";
var epLine = host ? (host + (port ? ":" + port : "")) : "(укажите Endpoint)";
return (
"Памятка по каскаду\n" +
"— Имя: " + name + "\n" +
"— Endpoint для клиента: " + epLine + "\n" +
"— На промежуточном узле: проброс UDP на VPS и порт WG/AWG.\n" +
"— На основном сервере: создать peer (панель Amnezia Admin → «Новый клиент под каскад») и выдать .conf.\n"
);
}
document.getElementById("btn-build").addEventListener("click", function () {
document.getElementById("out-memo").textContent = buildText();
});
document.getElementById("btn-copy").addEventListener("click", async function () {
var t = document.getElementById("out-memo").textContent || buildText();
try {
await navigator.clipboard.writeText(t);
} catch (e) {
alert("Не удалось скопировать — выделите текст вручную.");
}
});
})();
</script>
</body>
</html>