mirror of
https://github.com/andrey271192/keenetic_ssh-web.git
synced 2026-09-20 14:42:01 +00:00
Compare commits
19 Commits
claude/tru
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b23ac29e87 | ||
|
|
23212a8b01 | ||
|
|
48d20a08b7 | ||
|
|
8beee2f067 | ||
|
|
6624b8127e | ||
|
|
9792bbccb6 | ||
|
|
156a02fa32 | ||
|
|
8fe0a09684 | ||
|
|
aae52e86ef | ||
|
|
ee031b09dd | ||
|
|
bf504f4b28 | ||
|
|
a671c1556f | ||
|
|
c6db82bd2e | ||
|
|
90006b6149 | ||
|
|
10852b61b3 | ||
|
|
4e9f413521 | ||
|
|
858ff8b6ef | ||
|
|
7dbd2b43d0 | ||
|
|
7866cc22d5 |
@@ -24,7 +24,7 @@ PORT=2001
|
|||||||
CMD_TIMEOUT=300
|
CMD_TIMEOUT=300
|
||||||
|
|
||||||
# Подпись и Telegram внизу страницы (без @)
|
# Подпись и Telegram внизу страницы (без @)
|
||||||
AUTHOR_TELEGRAM_USERNAME=Iot_andrey
|
AUTHOR_TELEGRAM_USERNAME=PCAdministration
|
||||||
|
|
||||||
# Ограничение по IP клиента (через запятую, без масок). Пусто = все IP.
|
# Ограничение по IP клиента (через запятую, без масок). Пусто = все IP.
|
||||||
# Пример: ALLOWED_IPS=192.168.1.100,10.0.0.5
|
# Пример: ALLOWED_IPS=192.168.1.100,10.0.0.5
|
||||||
|
|||||||
482
README.md
482
README.md
@@ -1,329 +1,279 @@
|
|||||||
# keenetic_ssh-web
|
# keenetic_ssh-web
|
||||||
|
|
||||||
> Локальная веб-панель для **Keenetic + Entware**: shell-команды на роутере, расписание, ручной запуск, просмотр stdout/stderr. Слушает порт **2001**. Авторизация — логин/пароль от веб-админки роутера.
|
Веб‑панель, которая **выполняет команды прямо на роутере Keenetic** (Entware) и показывает вывод. Подходит для обновления пакетов, перезапусков сервисов, диагностики, и т. п.
|
||||||
>
|
|
||||||
> + опциональный модуль **`tunnel/`** — WireGuard VPS↔роутер, чтобы дотянуться до панели и SSH с **серого IP**, без проброса портов.
|
|
||||||
|
|
||||||
Репозиторий: [github.com/andrey271192/keenetic_ssh-web](https://github.com/andrey271192/keenetic_ssh-web)
|
- **Порт панели:** `2001`
|
||||||
|
- **Где работает:** на самом роутере (Entware)
|
||||||
|
- **Вход:** логин/пароль **от веб‑админки Keenetic** (NDM `/auth`)
|
||||||
|
(есть запасной «мастер‑пароль» `WEB_PASSWORD`, если нужно)
|
||||||
|
- **Опционально:** модуль `tunnel/` — **WireGuard‑туннель VPS ↔ роутер**, чтобы открыть доступ к панели и SSH, даже если у роутера **серый IP** (без проброса портов).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## В репозитории два независимых пакета
|
## Самое главное (чтобы было безопасно)
|
||||||
|
|
||||||
| Пакет | Куда ставится | Зачем | Обязателен |
|
- Эта панель запускает **любые команды** в Linux на роутере. Это мощно, но опасно.
|
||||||
|---|---|---|---|
|
- **Не открывайте порт 2001 в интернет для всех.** Минимум — включите `ALLOWED_IPS` или используйте туннель (вариант 2).
|
||||||
| **A. keenetic_ssh-web** | роутер (Entware) | веб-панель команд на 2001 | да |
|
|
||||||
| **B. tunnel** | VPS (Ubuntu) + роутер | WG-туннель для серого IP | нет, по желанию |
|
|
||||||
|
|
||||||
**Ставятся и удаляются отдельно**. Пакет B нужен только если у роутера серый IP и вы хотите управлять им из интернета через свой VPS. Если у вас белый IP / KeenDNS Cloud / достаточно LAN — ставьте только A.
|
|
||||||
|
|
||||||
> ⚠️ **Скрипты установки/удаления НЕ трогают** `hrneo`/`hrweb` (HydraRoute Neo), XKeen, Domain Hydra и любые ваши кастомные пакеты Entware. Не правят `/opt/etc/opkg.conf`, не сбрасывают чужие правила iptables, не ставят/удаляют пакеты, не относящиеся к данным двум пакетам.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Сценарии и что ставить
|
## Быстрый старт
|
||||||
|
|
||||||
| Сценарий | Доступ | Что ставить |
|
1. **Entware** на роутере — блок «📦 Установка Entware» ниже.
|
||||||
|---|---|---|
|
2. **Панель** — вариант 1, если хватает доступа из домашней сети.
|
||||||
| Управляю только из дома (LAN) | `http://192.168.X.1:2001` | только **A** |
|
3. **Серый IP** и нужен доступ откуда угодно — вариант 2 с туннелем через VPS.
|
||||||
| Серый IP, нужен доступ из любой точки | `https://имя.домен` через ваш VPS | **A** + **B** + reverse-proxy на VPS |
|
|
||||||
| Белый IP / KeenDNS Cloud | проброс портов или KeenDNS на 2001 | только **A** (B не нужен) |
|
Рядом с [Keenetic Unified](https://github.com/andrey271192/keenetic-unified) этот проект **не мешает**: другой порт (`2001`), всё крутится на самом роутере.
|
||||||
|
|
||||||
|
### Ещё скриншоты
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| Список файлов на роутере |  |
|
||||||
|
| Проверка DNS-маршрутов |  |
|
||||||
|
|
||||||
|
### 📦 Установка Entware на Keenetic
|
||||||
|
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
⚠️ Определи свою архитектуру
|
||||||
|
- Mipsel — роутеры на чипе MT7628/MT7621
|
||||||
|
- Aarch64 — роутеры на чипе MT7622/MT7981/MT7988 (ARM)
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
💡 Совет
|
||||||
|
Начиная с KeeneticOS 4.2 Entware можно установить прямо через браузер — просто открой `192.168.1.1/a` и следуй инструкции.
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
🚀 Установка онлайн — одной командой
|
||||||
|
|
||||||
|
🔵 Mipsel (MT7628/MT7621)
|
||||||
|
```sh
|
||||||
|
opkg disk storage:/ https://bin.entware.net/mipselsf-k3.4/installer/mipsel-installer.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
🟢 Aarch64 (MT7622/MT7981/MT7988)
|
||||||
|
```sh
|
||||||
|
opkg disk storage:/ https://bin.entware.net/aarch64-k3.10/installer/aarch64-installer.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
⏳ Дождись окончания установки — это займёт пару минут. После этого Entware готов к работе.
|
||||||
|
|
||||||
|
🔌 Подключение по SSH
|
||||||
|
📋 Данные для входа
|
||||||
|
- Логин: `root`
|
||||||
|
- Пароль: `keenetic`
|
||||||
|
- Порт: `22` (если вы не меняли порт SSH вручную)
|
||||||
|
|
||||||
|
### Вариант 1. Панель нужна только дома (LAN)
|
||||||
|
|
||||||
|
На роутере (в Entware shell по SSH):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/setup-router.sh | sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Откройте в браузере:
|
||||||
|
|
||||||
|
- `http://IP_РОУТЕРА:2001`
|
||||||
|
|
||||||
|
Вход — **как в веб‑админку Keenetic**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# A. keenetic_ssh-web — установка
|
### Вариант 2. Серый IP, нужен доступ из любой точки (через VPS)
|
||||||
|
|
||||||
## A.1. Требования
|
#### 2 команды “с нуля” (самый простой путь)
|
||||||
|
|
||||||
- Keenetic с **Entware** (`opkg` доступен)
|

|
||||||
- `python3` — установится автоматически из `bin.entware.net`
|
|
||||||
- Свободный порт **2001** (можно переопределить в `.env`)
|
|
||||||
|
|
||||||
## A.2. Установка одной командой (на роутере)
|
**Команда 1 — на VPS (Ubuntu):** поставить туннель и сразу добавить роутер.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/bootstrap.sh | sh
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/setup-vps.sh | sudo bash -s -- add my-router
|
||||||
```
|
```
|
||||||
|
|
||||||
Что делает:
|
Где `my-router` — **имя этого роутера на VPS** (можете назвать `home`, `dacha`, `office1`).
|
||||||
- скачивает архив ветки `main`, кладёт в `/opt/share/keenetic_ssh-web`
|
|
||||||
- ставит **только** `python3`, `python3-pip`, `python3-venv` (если их нет)
|
|
||||||
- кладёт init-скрипт `/opt/etc/init.d/S99keenetic-ssh-web` и rc.d-симлинк
|
|
||||||
- стартует сервис на порту 2001
|
|
||||||
- создаёт `.env` из примера и подставляет в `ROUTER_HOST` LAN-IP роутера
|
|
||||||
|
|
||||||
В конце выведет адрес панели: `http://<LAN-IP>:2001`. Логин/пароль — от веб-админки роутера.
|
Если у конкретного роутера «прокси/админка» сидит на другом порту (например `777`), задайте порт **для этого роутера**:
|
||||||
|
|
||||||
> Другая ветка/форк: `KSSH_BRANCH=dev KSSH_REPO=user/repo curl … | sh`.
|
|
||||||
|
|
||||||
## A.3. Конфиг — `/opt/share/keenetic_ssh-web/.env`
|
|
||||||
|
|
||||||
| Переменная | Описание | По умолчанию |
|
|
||||||
|---|---|---|
|
|
||||||
| `ROUTER_HOST` | HTTP-адреса админки Keenetic для проверки логина (через запятую — пробуем по очереди). Установщик сам подставит LAN-IP. | `http://127.0.0.1` |
|
|
||||||
| `ROUTER_LOGIN` | Логин по умолчанию в форме входа | `admin` |
|
|
||||||
| `ROUTER_TIMEOUT` | Таймаут запроса к `/auth`, сек | `5` |
|
|
||||||
| `WEB_PASSWORD` | Запасной мастер-пароль (если админка недоступна) | пусто |
|
|
||||||
| `PORT` | HTTP-порт панели | `2001` |
|
|
||||||
| `CMD_TIMEOUT` | Таймаут одной shell-команды, сек | `300` |
|
|
||||||
| `ALLOWED_IPS` | Белый список IP клиентов (через запятую). Пусто = всех. | пусто |
|
|
||||||
| `AUTHOR_TELEGRAM_USERNAME` | username для ссылки в шапке | `Iot_andrey` |
|
|
||||||
|
|
||||||
После правки:
|
|
||||||
```sh
|
|
||||||
/opt/etc/init.d/S99keenetic-ssh-web restart
|
|
||||||
tail -f /opt/var/log/keenetic-ssh-web.log
|
|
||||||
```
|
|
||||||
|
|
||||||
> ⚠️ **Безопасность.** Панель выполняет произвольные shell-команды с правами процесса (на Entware часто root). Не открывайте порт 2001 в интернет напрямую. Используйте `ALLOWED_IPS` или туннель + reverse-proxy с HTTPS (см. пакет B).
|
|
||||||
|
|
||||||
## A.4. Управление сервисом
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
/opt/etc/init.d/S99keenetic-ssh-web start
|
sudo kssh-tun add my-router --dnat 777
|
||||||
/opt/etc/init.d/S99keenetic-ssh-web stop
|
|
||||||
/opt/etc/init.d/S99keenetic-ssh-web restart
|
|
||||||
tail -f /opt/var/log/keenetic-ssh-web.log
|
|
||||||
vi /opt/share/keenetic_ssh-web/.env
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## A.5. Удаление keenetic_ssh-web
|
Что делает `--dnat`: туннель на роутере автоматически прокидывает вход на `wg0:<порт>` → `LAN_IP:<порт>`.
|
||||||
|
Это нужно, потому что некоторые сервисы Keenetic слушают **только на LAN‑IP**, и через `wg0` иначе будет `Connection refused`.
|
||||||
|
|
||||||
|
Команда на VPS выведет **готовый блок** (несколько строк `export ...` + `curl ... | sh`).
|
||||||
|
|
||||||
|
**Команда 2 — на роутере (Entware shell):** вставьте выданный блок **как есть**.
|
||||||
|
|
||||||
|
Он поднимет `wg0`, а затем установит панель на `2001`.
|
||||||
|
|
||||||
|
Проверка с VPS:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl http://10.99.0.X:2001
|
||||||
|
ssh root@10.99.0.X
|
||||||
|
```
|
||||||
|
|
||||||
|
Можно **вообще без домена и без Caddy/Nginx**: просто открывайте панель по IP из туннеля:
|
||||||
|
|
||||||
|
- `http://10.99.0.X:2001`
|
||||||
|
|
||||||
|
Reverse‑proxy нужен только если вы хотите **красивый адрес** `https://router-домен` и HTTPS.
|
||||||
|
|
||||||
|
**Caddy (3 строки):**
|
||||||
|
|
||||||
|
```caddy
|
||||||
|
router.example.com {
|
||||||
|
reverse_proxy 10.99.0.X:2001
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nginx (минимальный server block):**
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
server_name router.example.com;
|
||||||
|
location / { proxy_pass http://10.99.0.X:2001; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Рекомендация: в `.env` панели выставить **`ALLOWED_IPS=10.99.0.1`**, чтобы к роутеру мог обращаться **только VPS**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Вариант 3. Белый IP — без туннеля
|
||||||
|
|
||||||
|
Ставьте как в варианте 1 (LAN), а доступ снаружи делайте как вам удобно: проброс порта/файрвол/домен.
|
||||||
|
Важно: **не открывайте 2001 в интернет без ограничений** (см. безопасность ниже).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Как пользоваться панелью
|
||||||
|
|
||||||
|
### 1) Добавьте команду
|
||||||
|
|
||||||
|
- **Название** — как вам удобно (например: `opkg update`)
|
||||||
|
- **Команда** — обычная shell‑команда (например: `opkg update`)
|
||||||
|
- **Примечание** — необязательно
|
||||||
|
|
||||||
|
### 2) Запуск
|
||||||
|
|
||||||
|
- **Выполнить** — запускает одну команду и показывает результат
|
||||||
|
- **Выполнить все команды** — запускает все строки с галочкой **«ВКЛ»**
|
||||||
|
|
||||||
|
### 3) Расписание
|
||||||
|
|
||||||
|
- Поставьте интервал (в минутах) и нажмите **Сохранить**
|
||||||
|
- У нужных строк включите **«Распис.»**
|
||||||
|
|
||||||
|
По расписанию выполняются только строки: **ВКЛ + Распис.**
|
||||||
|
|
||||||
|
### 4) Просмотр вывода
|
||||||
|
|
||||||
|
Кнопка **«Вывод»** раскрывает полный лог последнего запуска (stdout + stderr).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Примеры полезных команд (можно копировать)
|
||||||
|
|
||||||
|
- Обновить пакеты: `opkg update && opkg list-upgradable | head`
|
||||||
|
- Обновить всё: `opkg update && opkg upgrade`
|
||||||
|
- Проверить место: `df -h`
|
||||||
|
- Процессы: `top -b -n 1 | head -60`
|
||||||
|
- WireGuard: `wg show`
|
||||||
|
- Логи: `logread | tail -200`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Безопасность (важно)
|
||||||
|
|
||||||
|
Это **не песочница**: команда выполняется с правами процесса (на Entware часто **root**).
|
||||||
|
|
||||||
|
- Не публикуйте порт **2001** в интернет «как есть».
|
||||||
|
- Используйте минимум: **туннель + reverse‑proxy** или **`ALLOWED_IPS`**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Удаление (одной командой)
|
||||||
|
|
||||||
|
### удаления (под ключ, без поломок)
|
||||||
|
|
||||||
|
Скрипты **удаляют только то, что сами ставили** и **не трогают**:
|
||||||
|
|
||||||
|
- HydraRoute Neo (`hrneo` / `hrweb`)
|
||||||
|
- другие Entware‑пакеты и ваши сервисы
|
||||||
|
- ваши конфиги (кроме своих файлов)
|
||||||
|
- чужие правила firewall/iptables (удаляются только наши вставки, связанные с wg0)
|
||||||
|
|
||||||
|
Если хотите сохранить настройки панели (`.env`) и список команд (`data/store.json`) — скажите, добавлю отдельную “удалить, но оставить данные” команду в `setup-router.sh` (сейчас это есть для панели через `KEEP_DATA=1`, но не вынесено в быстрый блок).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Панель (на роутере):
|
||||||
|
|
||||||
С GitHub:
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/uninstall.sh | sh
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/uninstall.sh | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Сохранить `data/store.json` и `.env`:
|
Панель (на роутере), **сохранить команды и настройки**:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/uninstall.sh | env KEEP_DATA=1 sh
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/uninstall.sh | env KEEP_DATA=1 sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Удаляет ровно: `/opt/share/keenetic_ssh-web/`, `/opt/etc/init.d/S99keenetic-ssh-web`, `/opt/etc/rc.d/S99keenetic-ssh-web`, pid-файл.
|
Туннель‑клиент (на роутере, если ставили):
|
||||||
**Не удаляет:** `python3`, `wireguard-tools`, `hrneo`, `hrweb`, любые другие пакеты Entware, лог `/opt/var/log/keenetic-ssh-web.log`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# B. tunnel — установка (опционально, для серых IP)
|
|
||||||
|
|
||||||
```
|
|
||||||
[твой ПК] → https://router.домен (VPS, белый IP)
|
|
||||||
│ Caddy/Nginx reverse-proxy
|
|
||||||
▼
|
|
||||||
wg0 10.99.0.1 (VPS)
|
|
||||||
⇅ WireGuard, UDP/51820
|
|
||||||
wg0 10.99.0.X (роутер за NAT провайдера)
|
|
||||||
▼
|
|
||||||
127.0.0.1:2001 keenetic_ssh-web
|
|
||||||
127.0.0.1:22 SSH
|
|
||||||
```
|
|
||||||
|
|
||||||
Туннель **инициирует роутер** наружу — серый IP / NAT провайдера не мешает.
|
|
||||||
|
|
||||||
## B.1. На VPS (Ubuntu) — один раз
|
|
||||||
|
|
||||||
```sh
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/server-install.sh | sudo sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Что делает:
|
|
||||||
- `apt install wireguard wireguard-tools curl`
|
|
||||||
- генерит серверные ключи (`/etc/wireguard/server_{private,public}.key`)
|
|
||||||
- создаёт `/etc/wireguard/wg0.conf` (UDP 51820, IP `10.99.0.1/24`)
|
|
||||||
- ставит утилиту `kssh-tun` в `/usr/local/bin/`
|
|
||||||
- открывает `51820/udp` и `wg0` в `ufw`/`iptables`, если активны
|
|
||||||
- запускает `wg-quick@wg0` и ставит на автозапуск
|
|
||||||
|
|
||||||
В конце печатает Endpoint и серверный PublicKey.
|
|
||||||
|
|
||||||
## B.2. На VPS — добавить роутер (peer)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo kssh-tun add router-name
|
|
||||||
```
|
|
||||||
|
|
||||||
Утилита:
|
|
||||||
- генерит ключи клиента, выделяет IP `10.99.0.X`
|
|
||||||
- сохраняет `/etc/wireguard/peers/<name>.peer`
|
|
||||||
- регенерирует `wg0.conf` и применяет (`systemctl restart wg-quick@wg0`)
|
|
||||||
- **выводит готовую команду для роутера** — четыре `export` + `curl … | sh`
|
|
||||||
|
|
||||||
Прочие команды:
|
|
||||||
```sh
|
|
||||||
sudo kssh-tun list # список peer-ов
|
|
||||||
sudo kssh-tun show <name> # повторно вывести ENV-блок
|
|
||||||
sudo kssh-tun remove <name> # удалить peer
|
|
||||||
sudo kssh-tun status # wg show wg0
|
|
||||||
```
|
|
||||||
|
|
||||||
## B.3. На роутере — поднять клиент
|
|
||||||
|
|
||||||
Скопируйте блок из `kssh-tun add` и выполните на роутере (через SSH/Entware shell):
|
|
||||||
|
|
||||||
```sh
|
|
||||||
export VPS_ENDPOINT=SERVER_IP:51820
|
|
||||||
export VPS_PUBKEY='...'
|
|
||||||
export CLIENT_IP=10.99.0.X
|
|
||||||
export CLIENT_PRIVKEY='...'
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/tunnel-install.sh | sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Что делает:
|
|
||||||
- `opkg install wireguard-tools` (если нет)
|
|
||||||
- пишет `/opt/etc/wireguard/wg0.conf`
|
|
||||||
- поднимает интерфейс `wg0` с адресом `CLIENT_IP/24`
|
|
||||||
- ставит init-скрипт `/opt/etc/init.d/S50kssh-tunnel` + rc.d-симлинк
|
|
||||||
- **разрешает входящий трафик с туннеля** (`iptables -I INPUT -i wg0 -j ACCEPT` + `rp_filter=2`) — без этого Keenetic режет ответы из VPS, handshake пройдёт, а ping/HTTP — нет
|
|
||||||
- пингует `10.99.0.1` для проверки
|
|
||||||
|
|
||||||
После этого с VPS:
|
|
||||||
```sh
|
|
||||||
ping -c 3 10.99.0.X
|
|
||||||
ssh root@10.99.0.X # если на роутере включён SSH
|
|
||||||
curl http://10.99.0.X:2001 # панель keenetic_ssh-web (если установлена)
|
|
||||||
```
|
|
||||||
|
|
||||||
## B.4. Reverse-proxy на VPS (доступ снаружи)
|
|
||||||
|
|
||||||
Caddyfile:
|
|
||||||
```
|
|
||||||
router.example.com {
|
|
||||||
reverse_proxy 10.99.0.X:2001
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Caddy выдаст HTTPS, и `https://router.example.com` отдаёт панель роутера. В `.env` keenetic_ssh-web укажите `ALLOWED_IPS=10.99.0.1` — только VPS будет иметь право заходить.
|
|
||||||
|
|
||||||
## B.5. Параметры (ENV)
|
|
||||||
|
|
||||||
`server-install.sh` (VPS):
|
|
||||||
|
|
||||||
| Переменная | По умолчанию | Описание |
|
|
||||||
|---|---|---|
|
|
||||||
| `WG_PORT` | `51820` | UDP-порт сервера |
|
|
||||||
| `WG_SUBNET_PREFIX` | `10.99.0` | Первые три октета `/24` |
|
|
||||||
| `WG_SERVER_LAST_OCTET` | `1` | Адрес сервера в туннеле |
|
|
||||||
| `KSSH_REPO`/`KSSH_BRANCH` | `andrey271192/keenetic_ssh-web` / `main` | Источник `kssh-tun` и `tunnel-install.sh` |
|
|
||||||
|
|
||||||
`tunnel-install.sh` (роутер):
|
|
||||||
|
|
||||||
| Переменная | Обязательная | Описание |
|
|
||||||
|---|---|---|
|
|
||||||
| `VPS_ENDPOINT` | да | `<публичный IP>:<порт>` |
|
|
||||||
| `VPS_PUBKEY` | да | PublicKey сервера |
|
|
||||||
| `CLIENT_IP` | да | IP роутера в туннеле |
|
|
||||||
| `CLIENT_PRIVKEY` | да | PrivateKey роутера (выдаёт `kssh-tun add`) |
|
|
||||||
| `WG_IF` | `wg0` | Имя интерфейса |
|
|
||||||
| `WG_SUBNET` | `10.99.0.1/32` | AllowedIPs клиента. По умолчанию только VPS, чтобы не ломать существующие WG-маршруты Keenetic. Поставьте `10.99.0.0/24` для peer-to-peer. |
|
|
||||||
| `WG_KEEPALIVE` | `25` | `PersistentKeepalive`, сек (нужен из-за NAT провайдера) |
|
|
||||||
|
|
||||||
## B.6. Удаление tunnel
|
|
||||||
|
|
||||||
### B.6.1. На роутере (только клиент)
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/tunnel-uninstall.sh | sh
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/tunnel-uninstall.sh | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Удаляет: интерфейс `wg0`, `/opt/etc/wireguard/wg0.conf`, init-скрипт `S50kssh-tunnel`, rc.d-симлинк, наши правила `iptables ACCEPT для wg0`.
|
Туннель‑сервер (на VPS, если ставили):
|
||||||
**Не удаляет:** `wireguard-tools`, общие правила iptables, чужие WG-конфиги, `keenetic_ssh-web`, HydraRoute Neo и др.
|
|
||||||
|
|
||||||
### B.6.2. На VPS (сервер)
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/server-uninstall.sh | sudo sh
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/server-uninstall.sh | sudo sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Удаляет: `wg-quick@wg0` (stop+disable), `/etc/wireguard/{wg0.conf,server_*.key,peers/,.kssh-tun.env}`, `/usr/local/bin/kssh-tun`, наши правила ufw/iptables.
|
---
|
||||||
**Не удаляет:** apt-пакеты `wireguard`/`wireguard-tools`, чужие правила ufw/iptables, ваши приложения и Docker.
|
|
||||||
|
|
||||||
Если потом захотите снести и сами apt-пакеты — вручную:
|
## Туннель как отдельный сервис (по желанию)
|
||||||
```sh
|
|
||||||
sudo apt remove --purge wireguard wireguard-tools
|
Туннель — это **дополнительный сервис для всей вашей экосистемы** (keenetic‑unified, domen_hydra и т. д.). Он просто делает так, что VPS «видит» роутер по адресу `10.99.0.X`.
|
||||||
```
|
|
||||||
|
Полная документация (для тех, кому нужно больше деталей): `tunnel/README.md`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Полный «с нуля» — пример
|
## Частые ошибки (и решения)
|
||||||
|
|
||||||
Допустим, на роутере уже стоит HydraRoute Neo, и его трогать **нельзя**. Хотим чистую установку обоих пакетов.
|
### `Connection refused` через туннель (RCI/админка/порт)
|
||||||
|
|
||||||
|
Некоторые сервисы Keenetic слушают **только LAN‑IP**, и если вы ходите на `wg0`, будет `Connection refused`.
|
||||||
|
|
||||||
|
- **Решение**: включить авто‑DNAT на нужный порт:
|
||||||
|
|
||||||
**1. На VPS:**
|
|
||||||
```sh
|
```sh
|
||||||
# (если что-то стояло раньше)
|
sudo kssh-tun add my-router --dnat 81
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/server-uninstall.sh | sudo sh
|
|
||||||
|
|
||||||
# свежая установка сервера туннеля
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/server-install.sh | sudo sh
|
|
||||||
|
|
||||||
# завести роутер
|
|
||||||
sudo kssh-tun add my-router
|
|
||||||
# → скопировать выданный 5-строчный блок
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**2. На роутере:**
|
или задать несколько портов: `--dnat 81,79`.
|
||||||
```sh
|
|
||||||
# (если что-то стояло раньше — оба пакета по отдельности)
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/tunnel-uninstall.sh | sh
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/uninstall.sh | sh
|
|
||||||
|
|
||||||
# панель
|
### Нельзя открывать панель в интернет
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/bootstrap.sh | sh
|
|
||||||
|
|
||||||
# туннель — вставить выданный с VPS блок (4 export + curl)
|
Порт `2001` — это выполнение команд. **Не публикуйте его “как есть”**.
|
||||||
export VPS_ENDPOINT=...
|
|
||||||
export VPS_PUBKEY='...'
|
|
||||||
export CLIENT_IP=10.99.0.X
|
|
||||||
export CLIENT_PRIVKEY='...'
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/tunnel/tunnel-install.sh | sh
|
|
||||||
```
|
|
||||||
|
|
||||||
**3. Проверка с VPS:**
|
- **Решение**: `ALLOWED_IPS` (например, только IP вашего VPS) или туннель + reverse‑proxy.
|
||||||
```sh
|
|
||||||
ping -c 3 10.99.0.X
|
|
||||||
curl -I http://10.99.0.X:2001/
|
|
||||||
```
|
|
||||||
|
|
||||||
`hrneo`/`hrweb` (HydraRoute Neo) и любые ваши кастомные репозитории на обоих хостах остаются нетронутыми.
|
## Поддержка проекта
|
||||||
|
|
||||||
---
|
- **Boosty:** `https://boosty.to/andrey27/donate`
|
||||||
|
- **Ozon Bank (СБП):** `https://finance.ozon.ru/apps/sbp/ozonbankpay/019dc200-2a5d-7931-a619-782d285f6798`
|
||||||
## Что лежит где
|
- **Telegram:** `https://t.me/PCAdministration`
|
||||||
|
|
||||||
### keenetic_ssh-web (на роутере)
|
|
||||||
| Путь | |
|
|
||||||
|---|---|
|
|
||||||
| `/opt/share/keenetic_ssh-web/` | приложение, `.env`, `data/store.json`, venv/lib |
|
|
||||||
| `/opt/etc/init.d/S99keenetic-ssh-web` | init-скрипт |
|
|
||||||
| `/opt/etc/rc.d/S99keenetic-ssh-web` | автозапуск |
|
|
||||||
| `/opt/var/log/keenetic-ssh-web.log` | лог |
|
|
||||||
| `/opt/var/run/keenetic-ssh-web.pid` | pid |
|
|
||||||
|
|
||||||
### tunnel — клиент (на роутере)
|
|
||||||
| Путь | |
|
|
||||||
|---|---|
|
|
||||||
| `/opt/etc/wireguard/wg0.conf` | конфиг туннеля |
|
|
||||||
| `/opt/etc/init.d/S50kssh-tunnel` | init-скрипт |
|
|
||||||
| `/opt/etc/rc.d/S50kssh-tunnel` | автозапуск |
|
|
||||||
|
|
||||||
### tunnel — сервер (на VPS)
|
|
||||||
| Путь | |
|
|
||||||
|---|---|
|
|
||||||
| `/etc/wireguard/wg0.conf` | конфиг сервера (регенерируется `kssh-tun`) |
|
|
||||||
| `/etc/wireguard/server_{private,public}.key` | серверные ключи |
|
|
||||||
| `/etc/wireguard/peers/<name>.peer` | данные peer-а (имя/IP/ключи) |
|
|
||||||
| `/etc/wireguard/.kssh-tun.env` | параметры запуска |
|
|
||||||
| `/usr/local/bin/kssh-tun` | утилита |
|
|
||||||
| `systemctl status wg-quick@wg0` | сервис |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Поддержка
|
|
||||||
|
|
||||||
- **GitHub:** [andrey271192](https://github.com/andrey271192)
|
|
||||||
- **Boosty:** [донат](https://boosty.to/andrey27/donate)
|
|
||||||
- **Telegram:** [@Iot_andrey](https://t.me/Iot_andrey)
|
|
||||||
|
|
||||||
|
Кнопка **Sponsor** на GitHub ведёт на варианты из `.github/FUNDING.yml`.
|
||||||
## Лицензия
|
## Лицензия
|
||||||
|
|
||||||
MIT — см. [LICENSE](LICENSE).
|
MIT — см. [LICENSE](LICENSE).
|
||||||
|
|||||||
2
app.py
2
app.py
@@ -21,7 +21,7 @@ log = logging.getLogger("kssh")
|
|||||||
APP_DIR = Path(__file__).resolve().parent
|
APP_DIR = Path(__file__).resolve().parent
|
||||||
|
|
||||||
WEB_PASSWORD = os.environ.get("WEB_PASSWORD", "").strip()
|
WEB_PASSWORD = os.environ.get("WEB_PASSWORD", "").strip()
|
||||||
AUTHOR_TG = os.environ.get("AUTHOR_TELEGRAM_USERNAME", "Iot_andrey").strip().lstrip("@") or "Iot_andrey"
|
AUTHOR_TG = os.environ.get("AUTHOR_TELEGRAM_USERNAME", "PCAdministration").strip().lstrip("@") or "PCAdministration"
|
||||||
ALLOWED_IPS_RAW = os.environ.get("ALLOWED_IPS", "").strip()
|
ALLOWED_IPS_RAW = os.environ.get("ALLOWED_IPS", "").strip()
|
||||||
ALLOWED_IPS = {x.strip() for x in ALLOWED_IPS_RAW.split(",") if x.strip()} if ALLOWED_IPS_RAW else set()
|
ALLOWED_IPS = {x.strip() for x in ALLOWED_IPS_RAW.split(",") if x.strip()} if ALLOWED_IPS_RAW else set()
|
||||||
CMD_TIMEOUT = int(os.environ.get("CMD_TIMEOUT", "300"))
|
CMD_TIMEOUT = int(os.environ.get("CMD_TIMEOUT", "300"))
|
||||||
|
|||||||
2
brand.py
2
brand.py
@@ -29,7 +29,7 @@ _DOT = "color:#86868b;user-select:none"
|
|||||||
|
|
||||||
|
|
||||||
def brand_bar_html(telegram_username: str) -> str:
|
def brand_bar_html(telegram_username: str) -> str:
|
||||||
u = (telegram_username or "Iot_andrey").lstrip("@")
|
u = (telegram_username or "PCAdministration").lstrip("@")
|
||||||
tg = f"https://t.me/{u}"
|
tg = f"https://t.me/{u}"
|
||||||
safe_u = html.escape(u, quote=True)
|
safe_u = html.escape(u, quote=True)
|
||||||
return (
|
return (
|
||||||
|
|||||||
BIN
docs/dns-routes-test.png
Normal file
BIN
docs/dns-routes-test.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
BIN
docs/files.png
Normal file
BIN
docs/files.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
56
docs/steps.svg
Normal file
56
docs/steps.svg
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="520" viewBox="0 0 1200 520">
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
.bg{fill:#0d1117}
|
||||||
|
.card{fill:#161b22;stroke:#30363d;stroke-width:2}
|
||||||
|
.txt{fill:#e6edf3;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif}
|
||||||
|
.mut{fill:#8b949e;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif}
|
||||||
|
.ttl{font-size:26px;font-weight:800}
|
||||||
|
.h{font-size:18px;font-weight:800}
|
||||||
|
.p{font-size:15px}
|
||||||
|
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono',monospace}
|
||||||
|
.accent{fill:#1f6feb}
|
||||||
|
.ok{fill:#3fb950}
|
||||||
|
.pill{fill:#0b1220;stroke:#30363d;stroke-width:2}
|
||||||
|
.arrow{stroke:#3fb950;stroke-width:4;fill:none;marker-end:url(#m)}
|
||||||
|
</style>
|
||||||
|
<marker id="m" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||||
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="#3fb950"/>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<rect class="bg" x="0" y="0" width="1200" height="520"/>
|
||||||
|
|
||||||
|
<text class="txt ttl" x="40" y="60">Установка «серый IP через VPS» — всего 2 шага</text>
|
||||||
|
<text class="mut p" x="40" y="92">Выполняете одну команду на VPS, получаете блок — вставляете его на роутере.</text>
|
||||||
|
|
||||||
|
<!-- Step 1 -->
|
||||||
|
<rect class="card" x="40" y="140" rx="16" ry="16" width="520" height="320"/>
|
||||||
|
<circle cx="80" cy="190" r="18" class="accent"/>
|
||||||
|
<text class="txt h" x="110" y="197">Шаг 1 (на VPS)</text>
|
||||||
|
<text class="mut p" x="70" y="235">Ставим туннель и добавляем роутер:</text>
|
||||||
|
|
||||||
|
<rect class="pill" x="70" y="255" rx="12" ry="12" width="460" height="110"/>
|
||||||
|
<text class="txt p mono" x="90" y="295">curl -fsSL https://raw.githubusercontent.com/</text>
|
||||||
|
<text class="txt p mono" x="90" y="320">andrey271192/keenetic_ssh-web/main/setup-vps.sh</text>
|
||||||
|
<text class="txt p mono" x="90" y="345">| sudo bash -s -- add home --dnat 777</text>
|
||||||
|
|
||||||
|
<text class="mut p" x="70" y="400">Результат: VPS печатает блок <tspan class="mono">export ...</tspan> для роутера.</text>
|
||||||
|
|
||||||
|
<!-- Step 2 -->
|
||||||
|
<rect class="card" x="640" y="140" rx="16" ry="16" width="520" height="320"/>
|
||||||
|
<circle cx="680" cy="190" r="18" class="ok"/>
|
||||||
|
<text class="txt h" x="710" y="197">Шаг 2 (на роутере)</text>
|
||||||
|
<text class="mut p" x="670" y="235">Вставляем блок, который выдал VPS:</text>
|
||||||
|
|
||||||
|
<rect class="pill" x="670" y="255" rx="12" ry="12" width="460" height="140"/>
|
||||||
|
<text class="txt p mono" x="690" y="295">export VPS_ENDPOINT=...</text>
|
||||||
|
<text class="txt p mono" x="690" y="320">export VPS_PUBKEY='...'</text>
|
||||||
|
<text class="txt p mono" x="690" y="345">export CLIENT_IP=10.99.0.X</text>
|
||||||
|
<text class="txt p mono" x="690" y="370">export DNAT_PORTS='777'</text>
|
||||||
|
<text class="txt p mono" x="690" y="395">curl -fsSL .../tunnel-install.sh | sh</text>
|
||||||
|
|
||||||
|
<text class="mut p" x="670" y="445">Готово: открываете <tspan class="mono">http://10.99.0.X:2001</tspan></text>
|
||||||
|
|
||||||
|
<path class="arrow" d="M 560 300 C 600 300, 610 300, 640 300"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
69
docs/tunnel-diagram.svg
Normal file
69
docs/tunnel-diagram.svg
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="520" viewBox="0 0 1200 520">
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
.bg{fill:#0d1117}
|
||||||
|
.card{fill:#161b22;stroke:#30363d;stroke-width:2}
|
||||||
|
.txt{fill:#e6edf3;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif}
|
||||||
|
.mut{fill:#8b949e;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif}
|
||||||
|
.ttl{font-size:26px;font-weight:800}
|
||||||
|
.h{font-size:18px;font-weight:700}
|
||||||
|
.p{font-size:15px}
|
||||||
|
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono',monospace}
|
||||||
|
.accent{fill:#1f6feb}
|
||||||
|
.ok{fill:#3fb950}
|
||||||
|
.arrow{stroke:#1f6feb;stroke-width:4;fill:none;marker-end:url(#m)}
|
||||||
|
.arrow2{stroke:#3fb950;stroke-width:4;fill:none;marker-end:url(#m2)}
|
||||||
|
</style>
|
||||||
|
<marker id="m" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||||
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1f6feb"/>
|
||||||
|
</marker>
|
||||||
|
<marker id="m2" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||||
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="#3fb950"/>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<rect class="bg" x="0" y="0" width="1200" height="520"/>
|
||||||
|
|
||||||
|
<text class="txt ttl" x="40" y="60">Схема работы (серый IP → доступ через VPS)</text>
|
||||||
|
<text class="mut p" x="40" y="92">Роутер сам подключается к VPS по WireGuard, и VPS видит роутер как «локальный» IP 10.99.0.X.</text>
|
||||||
|
|
||||||
|
<!-- PC -->
|
||||||
|
<rect class="card" x="40" y="150" rx="16" ry="16" width="320" height="260"/>
|
||||||
|
<text class="txt h" x="70" y="195">Ваш ПК / телефон</text>
|
||||||
|
<text class="mut p" x="70" y="225">Открываете панель:</text>
|
||||||
|
<text class="txt p mono" x="70" y="255">http://10.99.0.X:2001</text>
|
||||||
|
<text class="mut p" x="70" y="290">(если туннель включён)</text>
|
||||||
|
<text class="mut p" x="70" y="335">Или дома в LAN:</text>
|
||||||
|
<text class="txt p mono" x="70" y="365">http://192.168.88.1:2001</text>
|
||||||
|
|
||||||
|
<!-- VPS -->
|
||||||
|
<rect class="card" x="440" y="150" rx="16" ry="16" width="320" height="260"/>
|
||||||
|
<text class="txt h" x="470" y="195">VPS (белый IP)</text>
|
||||||
|
<text class="mut p" x="470" y="225">WireGuard сервер:</text>
|
||||||
|
<text class="txt p mono" x="470" y="255">wg0 10.99.0.1</text>
|
||||||
|
<text class="mut p" x="470" y="295">Порт:</text>
|
||||||
|
<text class="txt p mono" x="520" y="295">UDP 51820</text>
|
||||||
|
<text class="mut p" x="470" y="335">Проверка:</text>
|
||||||
|
<text class="txt p mono" x="470" y="365">ping 10.99.0.X</text>
|
||||||
|
|
||||||
|
<!-- Router -->
|
||||||
|
<rect class="card" x="840" y="150" rx="16" ry="16" width="320" height="260"/>
|
||||||
|
<text class="txt h" x="870" y="195">Роутер Keenetic (Entware)</text>
|
||||||
|
<text class="mut p" x="870" y="225">WireGuard клиент:</text>
|
||||||
|
<text class="txt p mono" x="870" y="255">wg0 10.99.0.X</text>
|
||||||
|
|
||||||
|
<rect x="870" y="285" rx="12" ry="12" width="260" height="44" fill="#0b1220" stroke="#30363d" stroke-width="2"/>
|
||||||
|
<circle cx="892" cy="307" r="8" class="ok"/>
|
||||||
|
<text class="txt p" x="910" y="312">keenetic_ssh-web :2001</text>
|
||||||
|
|
||||||
|
<rect x="870" y="342" rx="12" ry="12" width="260" height="44" fill="#0b1220" stroke="#30363d" stroke-width="2"/>
|
||||||
|
<circle cx="892" cy="364" r="8" class="accent"/>
|
||||||
|
<text class="txt p" x="910" y="369">SSH :22</text>
|
||||||
|
|
||||||
|
<!-- Arrows -->
|
||||||
|
<path class="arrow" d="M 360 280 C 400 280, 410 280, 440 280"/>
|
||||||
|
<path class="arrow2" d="M 760 280 C 800 280, 810 280, 840 280"/>
|
||||||
|
|
||||||
|
<text class="mut p" x="505" y="140">WireGuard туннель</text>
|
||||||
|
<text class="mut p mono" x="515" y="118">10.99.0.0/24</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.6 KiB |
BIN
docs/ui.png
Normal file
BIN
docs/ui.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
@@ -4,6 +4,7 @@
|
|||||||
# Запуск (любой из вариантов):
|
# Запуск (любой из вариантов):
|
||||||
# curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/setup-vps.sh | sudo bash
|
# curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/setup-vps.sh | sudo bash
|
||||||
# curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/setup-vps.sh | sudo bash -s -- add <peer-name>
|
# curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/setup-vps.sh | sudo bash -s -- add <peer-name>
|
||||||
|
# curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/setup-vps.sh | sudo bash -s -- add <peer-name> --dnat 777
|
||||||
#
|
#
|
||||||
# Что делает (одной командой):
|
# Что делает (одной командой):
|
||||||
# 1) сносит предыдущий kssh-tunnel сервер (если был)
|
# 1) сносит предыдущий kssh-tunnel сервер (если был)
|
||||||
@@ -33,7 +34,8 @@ curl -fsSL "$RAW/tunnel/server-install.sh" | bash
|
|||||||
if [ "${1:-}" = "add" ] && [ -n "${2:-}" ]; then
|
if [ "${1:-}" = "add" ] && [ -n "${2:-}" ]; then
|
||||||
echo
|
echo
|
||||||
echo "==> [3/3] Добавление peer '$2'…"
|
echo "==> [3/3] Добавление peer '$2'…"
|
||||||
/usr/local/bin/kssh-tun add "$2"
|
shift 2
|
||||||
|
/usr/local/bin/kssh-tun add "$@"
|
||||||
else
|
else
|
||||||
echo
|
echo
|
||||||
echo "==> [3/3] Сервер готов. Добавьте роутер командой:"
|
echo "==> [3/3] Сервер готов. Добавьте роутер командой:"
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<a class="lnk" href="https://github.com/andrey271192/keenetic_ssh-web" target="_blank" rel="noopener noreferrer">GitHub</a>
|
<a class="lnk" href="https://github.com/andrey271192/keenetic_ssh-web" target="_blank" rel="noopener noreferrer">GitHub</a>
|
||||||
<a class="lnk" id="lnk-tg" href="https://t.me/Iot_andrey" target="_blank" rel="noopener noreferrer">Telegram</a>
|
<a class="lnk" id="lnk-tg" href="https://t.me/PCAdministration" target="_blank" rel="noopener noreferrer">Telegram</a>
|
||||||
<a class="lnk" href="https://boosty.to/andrey27/donate" target="_blank" rel="noopener noreferrer">Boosty</a>
|
<a class="lnk" href="https://boosty.to/andrey27/donate" target="_blank" rel="noopener noreferrer">Boosty</a>
|
||||||
<a class="lnk donate" href="https://finance.ozon.ru/apps/sbp/ozonbankpay/019dc200-2a5d-7931-a619-782d285f6798" target="_blank" rel="noopener noreferrer" title="Поддержать проекта (Ozon Bank, СБП)">Поддержать ❤</a>
|
<a class="lnk donate" href="https://finance.ozon.ru/apps/sbp/ozonbankpay/019dc200-2a5d-7931-a619-782d285f6798" target="_blank" rel="noopener noreferrer" title="Поддержать проекта (Ozon Bank, СБП)">Поддержать ❤</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
Решает задачу: у вас на роутере **серый IP** (нет публичного), но есть **VPS с белым IP**. Поднимаем WireGuard, и любой сервис на VPS обращается к роутеру по адресу из туннельной подсети (`10.99.0.X`), как если бы они были в одной LAN. SSH, HTTP, что угодно — без проброса портов и без переписывания других сервисов (`Domain Hydra`, `keenetic-unified`, `keenetic_ssh-web`, …).
|
Решает задачу: у вас на роутере **серый IP** (нет публичного), но есть **VPS с белым IP**. Поднимаем WireGuard, и любой сервис на VPS обращается к роутеру по адресу из туннельной подсети (`10.99.0.X`), как если бы они были в одной LAN. SSH, HTTP, что угодно — без проброса портов и без переписывания других сервисов (`Domain Hydra`, `keenetic-unified`, `keenetic_ssh-web`, …).
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
- На VPS выполни “1 раз” (раздел 1).
|
||||||
|
- На VPS добавь роутер (раздел 2) — команда напечатает блок `export ...`.
|
||||||
|
- Этот блок вставь на роутере (раздел 3).
|
||||||
|
|
||||||
|
После этого на VPS роутер будет доступен по `10.99.0.X` (SSH/HTTP/панели).
|
||||||
|
|
||||||
```
|
```
|
||||||
[VPS, белый IP] [Роутер, серый IP]
|
[VPS, белый IP] [Роутер, серый IP]
|
||||||
:443 Caddy/Nginx → wg0 10.99.0.1 ⇄ wg0 10.99.0.X → 127.0.0.1:2001 (kssh-web)
|
:443 Caddy/Nginx → wg0 10.99.0.1 ⇄ wg0 10.99.0.X → 127.0.0.1:2001 (kssh-web)
|
||||||
@@ -9,6 +17,8 @@
|
|||||||
…и т. д.
|
…и т. д.
|
||||||
```
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
UDP `51820`, подсеть `10.99.0.0/24`. Параметры можно поменять через ENV.
|
UDP `51820`, подсеть `10.99.0.0/24`. Параметры можно поменять через ENV.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -40,7 +50,15 @@ PublicKey: <SERVER_PUB>
|
|||||||
## 2. На VPS — добавление каждого роутера
|
## 2. На VPS — добавление каждого роутера
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo kssh-tun add router-andrey-1
|
sudo kssh-tun add home
|
||||||
|
```
|
||||||
|
|
||||||
|
`home` — это **имя роутера на VPS** (название peer-а). Можно любое: `dacha`, `office1`, `keenetic_andrey`.
|
||||||
|
|
||||||
|
Если у конкретного роутера сервис слушает на нестандартном порту (например `777`) и нужен авто‑DNAT `wg0:777 → LAN_IP:777`, добавьте:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo kssh-tun add home --dnat 777
|
||||||
```
|
```
|
||||||
|
|
||||||
Утилита:
|
Утилита:
|
||||||
@@ -64,6 +82,36 @@ sudo kssh-tun status # wg show wg0
|
|||||||
|
|
||||||
## 3. На роутере (Keenetic + Entware)
|
## 3. На роутере (Keenetic + Entware)
|
||||||
|
|
||||||
|
### 📦 Установка Entware на Keenetic
|
||||||
|
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
⚠️ Определи свою архитектуру
|
||||||
|
- Mipsel — роутеры на чипе MT7628/MT7621
|
||||||
|
- Aarch64 — роутеры на чипе MT7622/MT7981/MT7988 (ARM)
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
💡 Совет
|
||||||
|
Начиная с KeeneticOS 4.2 Entware можно установить прямо через браузер — просто открой `192.168.1.1/a` и следуй инструкции.
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
🚀 Установка онлайн — одной командой
|
||||||
|
|
||||||
|
🔵 Mipsel (MT7628/MT7621)
|
||||||
|
```sh
|
||||||
|
opkg disk storage:/ https://bin.entware.net/mipselsf-k3.4/installer/mipsel-installer.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
🟢 Aarch64 (MT7622/MT7981/MT7988)
|
||||||
|
```sh
|
||||||
|
opkg disk storage:/ https://bin.entware.net/aarch64-k3.10/installer/aarch64-installer.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
⏳ Дождись окончания установки — это займёт пару минут. После этого Entware готов к работе.
|
||||||
|
|
||||||
|
🔌 Подключение по SSH
|
||||||
|
📋 Данные для входа
|
||||||
|
- Логин: `root`
|
||||||
|
- Пароль: `keenetic`
|
||||||
|
- Порт: `22` (если вы не меняли порт SSH вручную)
|
||||||
|
|
||||||
Скопируйте блок из `kssh-tun add` и выполните на роутере (5 строк, можно блоком, можно по одной):
|
Скопируйте блок из `kssh-tun add` и выполните на роутере (5 строк, можно блоком, можно по одной):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -81,6 +129,7 @@ curl -fsSL https://raw.githubusercontent.com/andrey271192/keenetic_ssh-web/main/
|
|||||||
- поднимает интерфейс `wg0` с адресом `CLIENT_IP/24`
|
- поднимает интерфейс `wg0` с адресом `CLIENT_IP/24`
|
||||||
- маршрутизирует `10.99.0.0/24` через `wg0`
|
- маршрутизирует `10.99.0.0/24` через `wg0`
|
||||||
- ставит init-скрипт `/opt/etc/init.d/S50kssh-tunnel` ({start|stop|restart|status}) и rc.d-симлинк автозапуска
|
- ставит init-скрипт `/opt/etc/init.d/S50kssh-tunnel` ({start|stop|restart|status}) и rc.d-симлинк автозапуска
|
||||||
|
- автоматически добавляет DNAT для портов из `DNAT_PORTS`: вход на `wg0:port` → `LAN_IP:port` (помогает Keenetic‑админке/HTTP Proxy открываться через туннель; удаляется uninstall‑скриптом)
|
||||||
- в конце пингует `10.99.0.1` (VPS) для проверки
|
- в конце пингует `10.99.0.1` (VPS) для проверки
|
||||||
|
|
||||||
Если ping не прошёл — почти всегда дело в фаерволе VPS: `sudo ufw allow 51820/udp` (или эквивалент для iptables/firewalld).
|
Если ping не прошёл — почти всегда дело в фаерволе VPS: `sudo ufw allow 51820/udp` (или эквивалент для iptables/firewalld).
|
||||||
@@ -127,6 +176,7 @@ ssh root@10.99.0.5
|
|||||||
| `WG_IF` | `wg0` | Имя интерфейса. |
|
| `WG_IF` | `wg0` | Имя интерфейса. |
|
||||||
| `WG_SUBNET` | `10.99.0.1/32` | AllowedIPs клиента (что маршрутизировать в туннель). По умолчанию только VPS, чтобы не конфликтовать с существующими WG-маршрутами Keenetic. Поставьте `10.99.0.0/24` если нужно общение peer-to-peer. |
|
| `WG_SUBNET` | `10.99.0.1/32` | AllowedIPs клиента (что маршрутизировать в туннель). По умолчанию только VPS, чтобы не конфликтовать с существующими WG-маршрутами Keenetic. Поставьте `10.99.0.0/24` если нужно общение peer-to-peer. |
|
||||||
| `WG_KEEPALIVE` | `25` | `PersistentKeepalive` в секундах (нужен из-за NAT провайдера). |
|
| `WG_KEEPALIVE` | `25` | `PersistentKeepalive` в секундах (нужен из-за NAT провайдера). |
|
||||||
|
| `DNAT_PORTS` | `81` | Порты через запятую, для которых делаем авто‑DNAT `wg0:port → LAN_IP:port` (исправляет `Connection refused`, когда сервис слушает только на LAN‑IP). Пример: `DNAT_PORTS=81,79`. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ export VPS_ENDPOINT=$PUB_IP:$WG_PORT
|
|||||||
export VPS_PUBKEY='$SERVER_PUB'
|
export VPS_PUBKEY='$SERVER_PUB'
|
||||||
export CLIENT_IP=$CLIENT_IP
|
export CLIENT_IP=$CLIENT_IP
|
||||||
export CLIENT_PRIVKEY='$CLIENT_PRIV'
|
export CLIENT_PRIVKEY='$CLIENT_PRIV'
|
||||||
|
export DNAT_PORTS='${DNAT_PORTS:-81,79}'
|
||||||
curl -fsSL https://raw.githubusercontent.com/${KSSH_REPO}/${KSSH_BRANCH}/tunnel/tunnel-install.sh | sh
|
curl -fsSL https://raw.githubusercontent.com/${KSSH_REPO}/${KSSH_BRANCH}/tunnel/tunnel-install.sh | sh
|
||||||
EOF
|
EOF
|
||||||
echo "============================================================"
|
echo "============================================================"
|
||||||
@@ -104,6 +105,25 @@ case "$cmd" in
|
|||||||
require_root
|
require_root
|
||||||
NAME="${1:-}"
|
NAME="${1:-}"
|
||||||
[ -z "$NAME" ] && { echo "usage: kssh-tun add <name>" >&2; exit 1; }
|
[ -z "$NAME" ] && { echo "usage: kssh-tun add <name>" >&2; exit 1; }
|
||||||
|
shift || true
|
||||||
|
DNAT_PORTS_ARG=""
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--dnat)
|
||||||
|
DNAT_PORTS_ARG="${2:-}"
|
||||||
|
shift 2 || true
|
||||||
|
;;
|
||||||
|
--dnat=*)
|
||||||
|
DNAT_PORTS_ARG="${1#--dnat=}"
|
||||||
|
shift || true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Неизвестный аргумент: $1" >&2
|
||||||
|
echo "usage: kssh-tun add <name> [--dnat 81,79]" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
case "$NAME" in *[!a-zA-Z0-9_-]*) echo "Имя: только [a-zA-Z0-9_-]" >&2; exit 1;; esac
|
case "$NAME" in *[!a-zA-Z0-9_-]*) echo "Имя: только [a-zA-Z0-9_-]" >&2; exit 1;; esac
|
||||||
mkdir -p "$PEERS_DIR"
|
mkdir -p "$PEERS_DIR"
|
||||||
PEER_FILE="$PEERS_DIR/$NAME.peer"
|
PEER_FILE="$PEERS_DIR/$NAME.peer"
|
||||||
@@ -119,6 +139,7 @@ NAME="$NAME"
|
|||||||
CLIENT_IP="$CLIENT_IP"
|
CLIENT_IP="$CLIENT_IP"
|
||||||
CLIENT_PRIV="$CLIENT_PRIV"
|
CLIENT_PRIV="$CLIENT_PRIV"
|
||||||
CLIENT_PUB="$CLIENT_PUB"
|
CLIENT_PUB="$CLIENT_PUB"
|
||||||
|
DNAT_PORTS="$DNAT_PORTS_ARG"
|
||||||
EOF
|
EOF
|
||||||
chmod 600 "$PEER_FILE"
|
chmod 600 "$PEER_FILE"
|
||||||
regen_conf
|
regen_conf
|
||||||
@@ -164,7 +185,7 @@ EOF
|
|||||||
cat <<EOF
|
cat <<EOF
|
||||||
kssh-tun — управление WireGuard-клиентами для keenetic_ssh-web tunnel.
|
kssh-tun — управление WireGuard-клиентами для keenetic_ssh-web tunnel.
|
||||||
|
|
||||||
kssh-tun add <name> добавить peer, вывести ENV-блок для роутера
|
kssh-tun add <name> [--dnat 81,79] добавить peer, вывести ENV-блок для роутера
|
||||||
kssh-tun show <name> повторно вывести ENV-блок
|
kssh-tun show <name> повторно вывести ENV-блок
|
||||||
kssh-tun list список peer-ов
|
kssh-tun list список peer-ов
|
||||||
kssh-tun remove <name> удалить peer
|
kssh-tun remove <name> удалить peer
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ WG_SUBNET="${WG_SUBNET:-10.99.0.1/32}"
|
|||||||
WG_KEEPALIVE="${WG_KEEPALIVE:-25}"
|
WG_KEEPALIVE="${WG_KEEPALIVE:-25}"
|
||||||
WG_DIR="/opt/etc/wireguard"
|
WG_DIR="/opt/etc/wireguard"
|
||||||
INIT="/opt/etc/init.d/S50kssh-tunnel"
|
INIT="/opt/etc/init.d/S50kssh-tunnel"
|
||||||
|
# DNAT для сервисов, которые слушают только на LAN-IP, но не на wg0.
|
||||||
|
# Пример: Keenetic NDM/HTTP Proxy часто на :81 или :79.
|
||||||
|
# Порты через запятую, например: DNAT_PORTS=81,79
|
||||||
|
DNAT_PORTS="${DNAT_PORTS:-81}"
|
||||||
|
NAT_TAG_PREFIX="kssh-tunnel:dnat"
|
||||||
|
|
||||||
[ -z "$VPS_ENDPOINT" ] && { echo "VPS_ENDPOINT обязателен" >&2; exit 1; }
|
[ -z "$VPS_ENDPOINT" ] && { echo "VPS_ENDPOINT обязателен" >&2; exit 1; }
|
||||||
[ -z "$VPS_PUBKEY" ] && { echo "VPS_PUBKEY обязателен" >&2; exit 1; }
|
[ -z "$VPS_PUBKEY" ] && { echo "VPS_PUBKEY обязателен" >&2; exit 1; }
|
||||||
@@ -68,6 +73,8 @@ WG_DIR="$WG_DIR"
|
|||||||
CONF="\$WG_DIR/\$WG_IF.conf"
|
CONF="\$WG_DIR/\$WG_IF.conf"
|
||||||
ADDR="$CLIENT_IP/24"
|
ADDR="$CLIENT_IP/24"
|
||||||
SUBNET="$WG_SUBNET"
|
SUBNET="$WG_SUBNET"
|
||||||
|
DNAT_PORTS="$DNAT_PORTS"
|
||||||
|
NAT_TAG_PREFIX="$NAT_TAG_PREFIX"
|
||||||
|
|
||||||
up() {
|
up() {
|
||||||
ip link show "\$WG_IF" >/dev/null 2>&1 && ip link del "\$WG_IF" 2>/dev/null
|
ip link show "\$WG_IF" >/dev/null 2>&1 && ip link del "\$WG_IF" 2>/dev/null
|
||||||
@@ -87,6 +94,28 @@ up() {
|
|||||||
if command -v iptables >/dev/null 2>&1; then
|
if command -v iptables >/dev/null 2>&1; then
|
||||||
iptables -C INPUT -i "\$WG_IF" -j ACCEPT 2>/dev/null || iptables -I INPUT 1 -i "\$WG_IF" -j ACCEPT
|
iptables -C INPUT -i "\$WG_IF" -j ACCEPT 2>/dev/null || iptables -I INPUT 1 -i "\$WG_IF" -j ACCEPT
|
||||||
iptables -C OUTPUT -o "\$WG_IF" -j ACCEPT 2>/dev/null || iptables -I OUTPUT 1 -o "\$WG_IF" -j ACCEPT
|
iptables -C OUTPUT -o "\$WG_IF" -j ACCEPT 2>/dev/null || iptables -I OUTPUT 1 -o "\$WG_IF" -j ACCEPT
|
||||||
|
# Некоторые сервисы на Keenetic слушают только на LAN-IP:port, но не на wg0:port.
|
||||||
|
# Для доступа через туннель делаем DNAT wg0:port → LAN_IP:port для заданных портов.
|
||||||
|
LAN_IP=""
|
||||||
|
for IF in br0 br-lan; do
|
||||||
|
LAN_IP=\$(ip -4 -o addr show "\$IF" 2>/dev/null | awk '{print \$4}' | cut -d/ -f1 | head -n 1)
|
||||||
|
[ -n "\$LAN_IP" ] && break
|
||||||
|
done
|
||||||
|
if [ -z "\$LAN_IP" ]; then
|
||||||
|
LAN_IP=\$(ip -4 -o addr show 2>/dev/null | awk -v wg="\$WG_IF" '\$2!=wg && \$2!=\"lo\" {print \$4}' | cut -d/ -f1 | head -n 1)
|
||||||
|
fi
|
||||||
|
if [ -n "\$LAN_IP" ]; then
|
||||||
|
OLD_IFS="\$IFS"
|
||||||
|
IFS=","
|
||||||
|
for P in \$DNAT_PORTS; do
|
||||||
|
P=\$(echo "\$P" | tr -d ' ')
|
||||||
|
case "\$P" in ""|*[!0-9]*) continue ;; esac
|
||||||
|
TAG="\$NAT_TAG_PREFIX:\$WG_IF:\$P"
|
||||||
|
iptables -t nat -C PREROUTING -i "\$WG_IF" -p tcp --dport "\$P" -m comment --comment "\$TAG" -j DNAT --to-destination "\$LAN_IP:\$P" 2>/dev/null || \
|
||||||
|
iptables -t nat -I PREROUTING 1 -i "\$WG_IF" -p tcp --dport "\$P" -m comment --comment "\$TAG" -j DNAT --to-destination "\$LAN_IP:\$P" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
IFS="\$OLD_IFS"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if ! wg show "\$WG_IF" | grep -q '^peer:'; then
|
if ! wg show "\$WG_IF" | grep -q '^peer:'; then
|
||||||
echo "ВНИМАНИЕ: peer не появился в \$WG_IF — handshake не состоится."
|
echo "ВНИМАНИЕ: peer не появился в \$WG_IF — handshake не состоится."
|
||||||
@@ -103,6 +132,11 @@ down() {
|
|||||||
while iptables -C OUTPUT -o "\$WG_IF" -j ACCEPT 2>/dev/null; do
|
while iptables -C OUTPUT -o "\$WG_IF" -j ACCEPT 2>/dev/null; do
|
||||||
iptables -D OUTPUT -o "\$WG_IF" -j ACCEPT 2>/dev/null || break
|
iptables -D OUTPUT -o "\$WG_IF" -j ACCEPT 2>/dev/null || break
|
||||||
done
|
done
|
||||||
|
# удалить наши DNAT-правила (если были) — только с tag-prefix
|
||||||
|
while iptables -t nat -S PREROUTING 2>/dev/null | grep -q "\$NAT_TAG_PREFIX:\$WG_IF:"; do
|
||||||
|
RULE=\$(iptables -t nat -S PREROUTING | grep "\$NAT_TAG_PREFIX:\$WG_IF:" | head -n 1 | sed 's/^-A /-D /')
|
||||||
|
[ -n "\$RULE" ] && iptables -t nat \$RULE 2>/dev/null || break
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
echo "stopped \$WG_IF"
|
echo "stopped \$WG_IF"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ WG_IF="${WG_IF:-wg0}"
|
|||||||
WG_DIR="/opt/etc/wireguard"
|
WG_DIR="/opt/etc/wireguard"
|
||||||
INIT="/opt/etc/init.d/S50kssh-tunnel"
|
INIT="/opt/etc/init.d/S50kssh-tunnel"
|
||||||
RCD="/opt/etc/rc.d/S50kssh-tunnel"
|
RCD="/opt/etc/rc.d/S50kssh-tunnel"
|
||||||
|
NAT_TAG_PREFIX="kssh-tunnel:dnat"
|
||||||
|
|
||||||
echo "==> kssh-tunnel: удаление клиента ($WG_IF)"
|
echo "==> kssh-tunnel: удаление клиента ($WG_IF)"
|
||||||
|
|
||||||
@@ -33,6 +34,11 @@ if command -v iptables >/dev/null 2>&1; then
|
|||||||
while iptables -C OUTPUT -o "$WG_IF" -j ACCEPT 2>/dev/null; do
|
while iptables -C OUTPUT -o "$WG_IF" -j ACCEPT 2>/dev/null; do
|
||||||
iptables -D OUTPUT -o "$WG_IF" -j ACCEPT 2>/dev/null || break
|
iptables -D OUTPUT -o "$WG_IF" -j ACCEPT 2>/dev/null || break
|
||||||
done
|
done
|
||||||
|
# удалить наши DNAT-правила (только наши теги)
|
||||||
|
while iptables -t nat -S PREROUTING 2>/dev/null | grep -q "$NAT_TAG_PREFIX:$WG_IF:"; do
|
||||||
|
RULE="$(iptables -t nat -S PREROUTING | grep "$NAT_TAG_PREFIX:$WG_IF:" | head -n 1 | sed 's/^-A /-D /')"
|
||||||
|
[ -n "$RULE" ] && iptables -t nat $RULE 2>/dev/null || break
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 3. Удалить файлы туннеля (НЕ трогаем чужие WG-конфиги в этой папке)
|
# 3. Удалить файлы туннеля (НЕ трогаем чужие WG-конфиги в этой папке)
|
||||||
|
|||||||
Reference in New Issue
Block a user