Files
keenetic_ssh-web/tunnel/tunnel-install.sh
Андрей Бобырев 677fcc604a tunnel: ufw allow on wg0 + клиент по умолчанию маршрутит только VPS (/32)
После handshake траффик упирался в UFW на сервере (открывали только
51820/udp, не сам интерфейс wg0). Добавляем `ufw allow in/out on wg0`
в server-install.sh — теперь ICMP/HTTP/SSH внутри туннеля проходят.

На клиенте AllowedIPs по умолчанию = 10.99.0.1/32 (только сам VPS),
а не /24. Это устраняет возможный конфликт с существующими маршрутами
для 10.99.0.0/24, если у Keenetic другие WG-интерфейсы используют ту
же подсеть. Hub-and-spoke (роутер→VPS) — типичный сценарий, /32
достаточно. Кому нужен peer-to-peer через хаб — WG_SUBNET=10.99.0.0/24.
2026-04-26 12:09:43 +03:00

132 lines
5.4 KiB
Bash
Executable File
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.

#!/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}"
# Что маршрутизировать в туннель. По умолчанию только сам VPS (/32),
# чтобы не конфликтовать с возможными существующими маршрутами
# 10.99.0.0/24 на роутере (другие WG-интерфейсы Keenetic). Если нужен
# доступ к другим peer-ам в подсети — поставьте WG_SUBNET=10.99.0.0/24.
WG_SUBNET="${WG_SUBNET:-10.99.0.1/32}"
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
# Формат для `wg setconf` — без wg-quick полей (Address/DNS/Table/PostUp...).
# Address выставляем через `ip addr add` в init-скрипте.
cat > "$CONF" <<EOF
# kssh-tunnel client; адрес: $CLIENT_IP/24
[Interface]
PrivateKey = $CLIENT_PRIVKEY
[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 || { echo "ip link add не сработал — нет модуля wireguard в ядре?"; return 1; }
if ! wg setconf "\$WG_IF" "\$CONF"; then
echo "wg setconf вернул ошибку — проверьте \$CONF (формат: только PrivateKey + [Peer])"
return 1
fi
ip addr add "\$ADDR" dev "\$WG_IF"
ip link set "\$WG_IF" up
ip route add "\$SUBNET" dev "\$WG_IF" 2>/dev/null || true
if ! wg show "\$WG_IF" | grep -q '^peer:'; then
echo "ВНИМАНИЕ: peer не появился в \$WG_IF — handshake не состоится."
echo "Проверьте \$CONF и перезапустите."
fi
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 "============================================================"