Точечная маршрутизация IPv6 через warp openwrt

Linux admin Openwrt

Обсуждение тут

Роутим ручками через марку на основе ипсета

ipset (через firewall)

/etc/config/firewall:

config ipset
        option name 'list2warp6'
        option family 'ipv6'
        option match 'dest_net'
        list domain 'ntc.party'
        list domain 'ifconfig.co'

OpenWrt сам создаст inet fw4 set list2warp6 и будет наполнять его через dnsmasq при запросах.


firewall rule (маркировка пакетов из LAN)

config rule
        option name 'Mark2warp6'
        option family 'ipv6'
        option src 'lan'
        option proto 'all'
        option dest '*'
        option target 'MARK'
        option set_mark '0x28'
        option ipset 'list2warp6'

В итоге: если клиент в LAN резолвит ntc.party или ifconfig.co, его пакеты получат метку 0x28.


Policy routing (warp6 таблица)

/etc/config/network:

config rule6
        option mark '0x28'
        option lookup 'warp6'

config route6
        option table 'warp6'
        option target '::/0'
        option interface 'warp'
        option src 'твой ип warp'
        option metric '1'

NAT66 для warp

В hotplug (чтобы правило не дублировалось):

/etc/hotplug.d/iface/99-warp6:

#!/bin/sh

# Hotplug script for warp6 route and NAT66
# Автоматически подставляет IPv6 адрес warp-интерфейса
# Удаляет маршрут, правила и таблицу при ifdown

if [ "$INTERFACE" = "warp" ]; then
    case "$ACTION" in
        ifup)
            # Получаем глобальный IPv6 адрес интерфейса warp (/128)
            WARP_ADDR="$(ip -6 addr show dev warp scope global | awk '/inet6/ {print $2}' | head -n1 | cut -d/ -f1)"

            if [ -n "$WARP_ADDR" ]; then
                logger -t warp6 "ifup: using IPv6 source $WARP_ADDR"

                # --- Policy route для warp6 ---
                ip -6 route replace default dev warp table warp6 src "$WARP_ADDR" metric 1

                # --- NAT66 warp6 ---
                nft add table ip6 nat 2>/dev/null
                nft add chain ip6 nat postrouting '{ type nat hook postrouting priority srcnat; }' 2>/dev/null

                # Удаляем все старые masquerade для warp
                for h in $(nft -a list chain ip6 nat postrouting 2>/dev/null | \
                           awk '/oifname "warp" masquerade/ {print $NF}'); do
                    nft delete rule ip6 nat postrouting handle "$h"
                done

                # Добавляем одно новое masquerade
                nft add rule ip6 nat postrouting oifname "warp" masquerade
            else
                logger -t warp6 "ifup: no global IPv6 address found on warp"
            fi
        ;;
        ifdown)
            logger -t warp6 "ifdown: cleaning up warp6 rules"

            # Удаляем маршрут
            ip -6 route flush table warp6

            # Удаляем все masquerade для warp
            for h in $(nft -a list chain ip6 nat postrouting 2>/dev/null | \
                       awk '/oifname "warp" masquerade/ {print $NF}'); do
                nft delete rule ip6 nat postrouting handle "$h"
            done

            # Если таблица ip6 nat пуста → удаляем её
            if nft list table ip6 nat 2>/dev/null | grep -q 'chain postrouting'; then
                RULES="$(nft list chain ip6 nat postrouting 2>/dev/null | grep masquerade | wc -l)"
                if [ "$RULES" -eq 0 ]; then
                    nft delete table ip6 nat
                    logger -t warp6 "ifdown: ip6 nat table removed (empty)"
                fi
            fi
        ;;
    esac
fi

Проверка

С клиента в LAN:

ping6 ntc.party

С роутера:

nft list ruleset | grep list2warp6 -A5 ip -6 rule show ip -6 route show table warp6