From 10852b61b36aa8519c8b6ed937cd070eae895341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=91=D0=BE=D0=B1?= =?UTF-8?q?=D1=8B=D1=80=D0=B5=D0=B2?= Date: Sun, 26 Apr 2026 16:05:59 +0300 Subject: [PATCH] =?UTF-8?q?tunnel:=20DNAT=5FPORTS=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=80=D0=B0=D0=B7=D0=BD=D1=8B=D1=85=20=D0=BF=D0=BE=D1=80=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=20(81/79/...)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made-with: Cursor --- tunnel/README.md | 1 + tunnel/tunnel-install.sh | 31 ++++++++++++++++++++++--------- tunnel/tunnel-uninstall.sh | 8 ++++---- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/tunnel/README.md b/tunnel/README.md index cd1d7d3..fe940d8 100644 --- a/tunnel/README.md +++ b/tunnel/README.md @@ -128,6 +128,7 @@ ssh root@10.99.0.5 | `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 провайдера). | +| `DNAT_PORTS` | `81` | Порты через запятую, для которых делаем авто‑DNAT `wg0:port → LAN_IP:port` (исправляет `Connection refused`, когда сервис слушает только на LAN‑IP). Пример: `DNAT_PORTS=81,79`. | --- diff --git a/tunnel/tunnel-install.sh b/tunnel/tunnel-install.sh index 6cbce54..c696bcc 100755 --- a/tunnel/tunnel-install.sh +++ b/tunnel/tunnel-install.sh @@ -20,7 +20,11 @@ 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" -NAT_TAG="kssh-tunnel:ndm81" +# 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_PUBKEY" ] && { echo "VPS_PUBKEY обязателен" >&2; exit 1; } @@ -69,7 +73,8 @@ WG_DIR="$WG_DIR" CONF="\$WG_DIR/\$WG_IF.conf" ADDR="$CLIENT_IP/24" SUBNET="$WG_SUBNET" -NAT_TAG="$NAT_TAG" +DNAT_PORTS="$DNAT_PORTS" +NAT_TAG_PREFIX="$NAT_TAG_PREFIX" up() { ip link show "\$WG_IF" >/dev/null 2>&1 && ip link del "\$WG_IF" 2>/dev/null @@ -89,8 +94,8 @@ up() { 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 OUTPUT -o "\$WG_IF" -j ACCEPT 2>/dev/null || iptables -I OUTPUT 1 -o "\$WG_IF" -j ACCEPT - # NDM/HTTP Proxy на Keenetic часто слушает на LAN-IP:81, но не на wg0:81. - # Для доступа к /auth через туннель делаем DNAT wg0:81 → LAN_IP:81. + # Некоторые сервисы на 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) @@ -100,8 +105,16 @@ up() { 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 - iptables -t nat -C PREROUTING -i "\$WG_IF" -p tcp --dport 81 -m comment --comment "\$NAT_TAG" -j DNAT --to-destination "\$LAN_IP:81" 2>/dev/null || \ - iptables -t nat -I PREROUTING 1 -i "\$WG_IF" -p tcp --dport 81 -m comment --comment "\$NAT_TAG" -j DNAT --to-destination "\$LAN_IP:81" 2>/dev/null || true + 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 if ! wg show "\$WG_IF" | grep -q '^peer:'; then @@ -119,9 +132,9 @@ down() { 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 done - # удалить наши DNAT-правила (если были) - while iptables -t nat -S PREROUTING 2>/dev/null | grep -q "\$NAT_TAG"; do - RULE=\$(iptables -t nat -S PREROUTING | grep "\$NAT_TAG" | head -n 1 | sed 's/^-A /-D /') + # удалить наши 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 diff --git a/tunnel/tunnel-uninstall.sh b/tunnel/tunnel-uninstall.sh index 50e5dad..17d6fe3 100755 --- a/tunnel/tunnel-uninstall.sh +++ b/tunnel/tunnel-uninstall.sh @@ -14,7 +14,7 @@ WG_IF="${WG_IF:-wg0}" WG_DIR="/opt/etc/wireguard" INIT="/opt/etc/init.d/S50kssh-tunnel" RCD="/opt/etc/rc.d/S50kssh-tunnel" -NAT_TAG="kssh-tunnel:ndm81" +NAT_TAG_PREFIX="kssh-tunnel:dnat" echo "==> kssh-tunnel: удаление клиента ($WG_IF)" @@ -34,9 +34,9 @@ if command -v iptables >/dev/null 2>&1; then 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 done - # удалить наши DNAT-правила для доступа к NDM через wg0:81 - while iptables -t nat -S PREROUTING 2>/dev/null | grep -q "$NAT_TAG"; do - RULE="$(iptables -t nat -S PREROUTING | grep "$NAT_TAG" | head -n 1 | sed 's/^-A /-D /')" + # удалить наши 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