Настройка iptables и sing-box на роутере под Asuswrt-merlin

Привет! Призываются умельцы разбирающиеся в настройке iptables.

Цель:

  1. Нужно чтобы трафик всех устройств(кроме одного) в локальной сети роутера заворачивался в TPROXY
  2. Для проксируемых IP dns должен резолвиться через sing-box
    • когда домен попадает в local-dns в sing-box - он должен быть разеловлен на прямую, как обычно, если бы никакого прокси не было

Контекст:

  • Имеется роутер ASUS RT-AX86U.

    • Прошит на merlin.
  • Установлен entware.

  • Установлен sing-box 1.12.12.

    • config.json
      {
        "log": {
          "level": "warn"
        },
        "dns": {
          "strategy": "ipv4_only",
          "reverse_mapping": true,
          "final": "dns-local",
          "servers": [
            {
              "type": "https",
              "tag": "dns-remote",
              "server": "8.8.8.8",
              "tls": {
                "server_name": "dns.google"
              },
              "detour": "vps-proxy-selector"
            },
            {
              "type": "local",
              "tag": "dns-local"
            }
          ],
          "rules": [
            {
              "action": "predefined",
              "rcode": "REFUSED",
              "rule_set": [
                "geosite:category-ads-all"
              ]
            },
            {
              "action": "predefined",
              "rcode": "REFUSED",
              "domain_suffix": [
                "appcenter.ms",
                "firebase.io",
                "crashlytics.com"
              ]
            },
            {
              "domain_suffix": [
                "sagernet.org",
      		  ...
              ],
              "rule_set": [
                "geosite:discord",
                "geosite:jetbrains"
              ],
              "server": "dns-remote"
            },
            {
              "domain_suffix": [
                ".ru",
                ...
              ],
              "rule_set": [
                "geosite:category-ru"
              ],
              "server": "dns-local"
            },
      	  {
      		"action": "predefined",
      		"domain_suffix": [
                "ntc.party"
              ],
              "answer": [
      		  "ntc.party. IN A 130.255.77.28"
      		]
            }
          ]
        },
        "inbounds": [
          {
            "type": "tproxy",
            "tag": "tproxy-ipv4",
            "listen": "127.0.0.1",
            "listen_port": 12345,
            "tcp_fast_open": true
          }
        ],
        "outbounds": [
          {
            "type": "direct",
            "tag": "direct"
          },
          {
            "type": "selector",
            "tag": "vps-proxy-selector",
            "outbounds": [
              "vless-sfy",
              "vless-yahoo",
              "ss2"
            ],
            "default": "vless-yahoo"
          },
          {
            "type": "vless",
            "tag": "vless-sfy",
      	  ...
          },
          {
            "type": "vless",
            "tag": "vless-yahoo",
      	  ...
          },
          {
            "type": "shadowsocks",
            "tag": "ss2",
      	  ...
          }
        ],
        "route": {
          "final": "direct",
          "auto_detect_interface": true,
          "default_domain_resolver": {
            "server": "dns-remote"
          },
          "rules": [
            {
              "action": "sniff",
              "sniffer": [
                "http",
                "tls",
                "dns",
                "quic"
              ],
              "inbound": [
                "tproxy-ipv4"
              ] 
            },
            {
              "action": "resolve",
              "inbound": [
                "tproxy-ipv4"
              ] 
            },
            {
              "action": "hijack-dns",
              "protocol": "dns"
            },
            {
              "ip_is_private": true,
              "outbound": "direct"
            },
            {
              "action": "reject",
              "network": "udp",
              "port": 443
            },
            {
              "action": "reject",
              "rule_set": [
                "geosite:category-ads-all"
              ]
            },
            {
              "protocol": "bittorrent",
              "outbound": "direct"
            },
            {
              "domain_suffix": [
                ".ru",
                ...
              ],
              "rule_set": [
                "geosite:category-ru",
                "geoip:ru",
                "geoip:by"
              ],
              "outbound": "direct"
            },
            {
              "domain_suffix": [
                "sagernet.org",
                "ntc.party",
      		  ...
              ],
              "rule_set": [
                "geosite:discord",
                ...
              ],
              "ip_cidr": [
              ],
              "outbound": "vps-proxy-selector"
            }
          ],
          "rule_set": [
      	  ...
          ]
        },
        "experimental": {
          "cache_file": {
            "enabled": true,
      	  "path": "/opt/sing-box/cache.db"
          }
        }
      }
      
      
  • Есть вот такой draft bash скрипт конфигурации iptables

    • setup-iptables-ipv4_v5.sh
      #!/bin/sh
      # =====================================================
      # sing-box TPROXY (IPv4) for ASUS Merlin
      # =====================================================
      
      # Включает немедленное завершение скрипта при любой ошибке
      set -e
      
      ### =========================
      ### CONFIG
      ### =========================
      
      # Клиенты в LAN через пробел
      # Примеры:
      # "192.168.1.10"
      # "192.168.1.10 192.168.1.20"
      # "192.168.1.0/24"
      PROXY_CLIENTS="192.168.1.0/24"
      EXCLUDED_CLIENTS="192.168.1.10"
      
      # --- служебные параметры ---
      TPROXY_PORT="12345"
      TPROXY_MARK="1"
      TPROXY_TABLE="100"
      LAN_V4="192.168.1.0/24"
      
      ### =========================
      ### KERNEL MODULES
      ### =========================
      
      modprobe xt_TPROXY
      
      ### =========================
      ### POLICY ROUTING (IPv4)
      ### =========================
      
      ip rule del fwmark $TPROXY_MARK table $TPROXY_TABLE 2>/dev/null || true
      ip route flush table $TPROXY_TABLE
      
      ip rule add fwmark $TPROXY_MARK lookup $TPROXY_TABLE
      ip route add local 0.0.0.0/0 dev lo table $TPROXY_TABLE
      
      ### =========================
      ### Проксирование устройств локальной сети (IPv4)
      ### =========================
      
      # --- Сброс и создание цепочки SINGBOX ---
      iptables -t mangle -D PREROUTING -j SINGBOX 2>/dev/null || true
      iptables -t mangle -F SINGBOX 2>/dev/null || true
      iptables -t mangle -X SINGBOX 2>/dev/null || true
      iptables -t mangle -N SINGBOX
      
      # --- Исключения ---
      iptables -t mangle -A SINGBOX -d $LAN_V4 -p tcp -j RETURN
      iptables -t mangle -A SINGBOX -d $LAN_V4 -p udp ! --dport 53 -j RETURN
      iptables -t mangle -A SINGBOX -d 127.0.0.1/32 -j RETURN
      iptables -t mangle -A SINGBOX -d 224.0.0.0/4 -j RETURN
      iptables -t mangle -A SINGBOX -d 239.0.0.0/8 -j RETURN
      iptables -t mangle -A SINGBOX -d 255.255.255.255 -j RETURN
      iptables -t mangle -A SINGBOX -j RETURN -m mark --mark 0xff
      
      # --- Непроксируемые клиенты ---
      for CLIENT in $EXCLUDED_CLIENTS; do
        iptables -t mangle -A SINGBOX -s $CLIENT -j RETURN
      done
      
      # --- Проксируемые клиенты ---
      for CLIENT in $PROXY_CLIENTS; do
        iptables -t mangle -A SINGBOX -s $CLIENT -p tcp \
          -j TPROXY --on-ip 127.0.0.1 --on-port $TPROXY_PORT \
          --tproxy-mark $TPROXY_MARK
      
        iptables -t mangle -A SINGBOX -s $CLIENT -p udp \
          -j TPROXY --on-ip 127.0.0.1 --on-port $TPROXY_PORT \
          --tproxy-mark $TPROXY_MARK
      done
      
      iptables -t mangle -I PREROUTING -j SINGBOX
      
      ### =========================
      ### Проксирование хоста шлюза (IPv4)
      ### =========================
      
      # --- Cоздание защиты от зацикливания --- НЕ РАБОТАЕТ
      #iptables -t mangle -A OUTPUT -m mark --mark $TPROXY_MARK -j RETURN
      
      ### =========================
      ### MSS FIX
      ### =========================
      
      iptables -t mangle -A FORWARD \
        -p tcp --tcp-flags SYN,RST SYN \
        -j TCPMSS --clamp-mss-to-pmtu
      
      echo "[OK] sing-box TPROXY IPv4 loaded"
      
    • Если не перенаправлять DNS запросы в sing-box - все работает как ожидается, кроме, очевидно, dns (он всегда идет в обход sing-box)

Проблема:

  • Текущая настройка iptables отлично работает для всех устройств, которые должны быть проксированы, но как только я пытаюсь открывать сайты с НЕ-проксируемого устройства - dns перестает работать везде. Как будто что-то где-то зацикливается.