tunnel: WireGuard VPS↔роутер для серых IP, без правки других сервисов

Решает доступ к роутеру с серым IP через белый VPS — поднимаем WG-туннель
(UDP 51820, подсеть 10.99.0.0/24), и любой сервис на VPS обращается к
роутеру по 10.99.0.X. SSH, HTTP, что угодно — без проброса портов и
без изменений в keenetic_ssh-web/keenetic-unified/Domain Hydra/etc.

Что добавлено:
- tunnel/server-install.sh — установка WG-сервера на Ubuntu VPS,
  генерация ключей, запуск wg-quick@wg0, открытие 51820/udp в ufw.
- tunnel/kssh-tun — утилита управления peer-ами на VPS:
  add/list/show/remove. add генерит ключи и IP, печатает ENV-блок
  с одной командой для роутера.
- tunnel/tunnel-install.sh — клиент для роутера (Entware), принимает
  4 ENV (VPS_ENDPOINT/VPS_PUBKEY/CLIENT_IP/CLIENT_PRIVKEY), ставит
  wireguard-tools, поднимает wg0 и init-скрипт автозапуска.
- tunnel/README.md — пошаговая инструкция массовой установки.
- README.md: краткая ссылка из основного раздела.

Параметры подсети/порта/имени репо — через ENV для масштабной установки.
This commit is contained in:
Андрей Бобырев
2026-04-26 11:12:19 +03:00
parent 7c2adf95b9
commit c46273e72a
5 changed files with 562 additions and 0 deletions

118
tunnel/tunnel-install.sh Executable file
View File

@@ -0,0 +1,118 @@
#!/bin/sh
# tunnel/tunnel-install.sh — установка WireGuard-клиента на роутере (Entware).
# Запускается с роутера, принимает 4 ENV-переменные (выдаёт kssh-tun add на VPS):
# VPS_ENDPOINT=<ip>:<port> — публичный endpoint VPS, UDP
# VPS_PUBKEY=<base64> — публичный ключ сервера
# CLIENT_IP=10.99.0.X — IP роутера в туннельной подсети
# CLIENT_PRIVKEY=<base64> — приватный ключ роутера
# По желанию:
# WG_IF=wg0 — имя интерфейса (по умолчанию wg0)
# WG_SUBNET=10.99.0.0/24 — какие IP маршрутизируются через туннель
# WG_KEEPALIVE=25 — PersistentKeepalive в секундах
set -e
WG_IF="${WG_IF:-wg0}"
WG_SUBNET="${WG_SUBNET:-10.99.0.0/24}"
WG_KEEPALIVE="${WG_KEEPALIVE:-25}"
WG_DIR="/opt/etc/wireguard"
INIT="/opt/etc/init.d/S50kssh-tunnel"
[ -z "$VPS_ENDPOINT" ] && { echo "VPS_ENDPOINT обязателен" >&2; exit 1; }
[ -z "$VPS_PUBKEY" ] && { echo "VPS_PUBKEY обязателен" >&2; exit 1; }
[ -z "$CLIENT_IP" ] && { echo "CLIENT_IP обязателен" >&2; exit 1; }
[ -z "$CLIENT_PRIVKEY" ] && { echo "CLIENT_PRIVKEY обязателен" >&2; exit 1; }
echo "==> WireGuard-клиент: $WG_IF $CLIENT_IP$VPS_ENDPOINT"
# wireguard-tools (на Keenetic ядре уже есть модуль wireguard, нужны только утилиты)
if ! command -v wg >/dev/null 2>&1; then
if command -v opkg >/dev/null 2>&1; then
opkg update || echo "(opkg update: частичные ошибки источников — продолжаем)"
opkg install wireguard-tools >/dev/null 2>&1 || true
fi
fi
if ! command -v wg >/dev/null 2>&1; then
echo "wg не найден. Установите вручную: opkg install wireguard-tools" >&2
exit 1
fi
mkdir -p "$WG_DIR"
chmod 700 "$WG_DIR"
CONF="$WG_DIR/$WG_IF.conf"
umask 077
cat > "$CONF" <<EOF
[Interface]
PrivateKey = $CLIENT_PRIVKEY
Address = $CLIENT_IP/24
[Peer]
PublicKey = $VPS_PUBKEY
Endpoint = $VPS_ENDPOINT
AllowedIPs = $WG_SUBNET
PersistentKeepalive = $WG_KEEPALIVE
EOF
chmod 600 "$CONF"
# Init-скрипт автозапуска
cat > "$INIT" <<INIEOF
#!/bin/sh
WG_IF="$WG_IF"
WG_DIR="$WG_DIR"
CONF="\$WG_DIR/\$WG_IF.conf"
ADDR="$CLIENT_IP/24"
SUBNET="$WG_SUBNET"
up() {
ip link show "\$WG_IF" >/dev/null 2>&1 && ip link del "\$WG_IF" 2>/dev/null
ip link add "\$WG_IF" type wireguard
wg setconf "\$WG_IF" "\$CONF"
ip addr add "\$ADDR" dev "\$WG_IF"
ip link set "\$WG_IF" up
ip route add "\$SUBNET" dev "\$WG_IF" 2>/dev/null || true
echo "started \$WG_IF \$ADDR"
}
down() {
ip link del "\$WG_IF" 2>/dev/null || true
echo "stopped \$WG_IF"
}
case "\$1" in
start) up ;;
stop) down ;;
restart) down; sleep 1; up ;;
status)
ip -4 -o addr show "\$WG_IF" 2>/dev/null && wg show "\$WG_IF" 2>/dev/null || echo "(\$WG_IF не поднят)"
;;
*) echo "usage: \$0 {start|stop|restart|status}"; exit 1 ;;
esac
INIEOF
chmod +x "$INIT"
# Поднять
"$INIT" restart || true
# Автозапуск через rc.d, если поддерживается
if [ -d /opt/etc/rc.d ] && [ ! -e /opt/etc/rc.d/S50kssh-tunnel ]; then
ln -sf "$INIT" /opt/etc/rc.d/S50kssh-tunnel 2>/dev/null && \
echo "==> Автозапуск: /opt/etc/rc.d/S50kssh-tunnel → $INIT"
fi
sleep 1
echo
echo "============================================================"
echo "Туннель $WG_IF поднят: $CLIENT_IP$VPS_ENDPOINT"
echo "Конфиг: $CONF"
echo "Init: $INIT {start|stop|restart|status}"
echo
ip -4 -o addr show "$WG_IF" 2>/dev/null | sed 's/^/ /'
wg show "$WG_IF" 2>/dev/null | sed 's/^/ /'
echo
VPS_IP="$(echo "$VPS_ENDPOINT" | cut -d: -f1)"
SERVER_TUN_IP="$(echo "$WG_SUBNET" | sed 's|0/24$|1|')"
echo "Проверка: ping -c 2 $SERVER_TUN_IP"
ping -c 2 -W 2 "$SERVER_TUN_IP" 2>/dev/null | sed 's/^/ /' || echo " (ping не прошёл — проверьте VPS firewall: ufw allow 51820/udp)"
echo
echo "Теперь с VPS ($VPS_IP) роутер доступен по адресу: $CLIENT_IP"
echo "Например, веб-панель: http://$CLIENT_IP:2001"
echo "============================================================"