
Я пытаюсь заставить часть трафика проходить через VPN, а часть — нет.
Пакеты с заданным fwmark должны идти на мой интерфейс по умолчанию ( wlo1
), а весь остальной трафик — на туннельный интерфейс ( tun0
, использующий OpenVPN) в основной таблице. Я добавил это правило в nftables:
table ip test {
chain test {
type route hook output priority mangle; policy accept;
meta cgroup 1234 meta mark set 1
}
}
В основной таблице маршрутизации у меня есть следующие записи:
default via 10.11.0.1 dev tun0
10.11.0.0/16 dev tun0 proto kernel scope link src 10.11.0.20
[WANIP.0]/24 dev wlo1 proto kernel scope link src [WANIP]
128.0.0.0/1 via 10.11.0.1 dev tun0
[VPNIP] via [WANGATEWAY] dev wlo1
Пакеты с fwmark 1
вместо этого направляются в их собственную таблицу маршрутизации: ip rule add from all fwmark 1 lookup test
. В test
таблицу я добавил следующий маршрут:
default via [WANGATEWAY] dev wlo1
Когда я запускаю ping 8.8.8.8
из этой cgroup, он застрял. Кажется, он может отправлять, но не получать пакеты.
VPN-трафик работает как положено.
Что именно происходит?
решение1
При отправке пакета принимается решение о маршрутизации: это решение выбирает исходящий интерфейс.исоответствующий исходный IP-адрес для использования.
Когдамаршрут/выходцепь устанавливает отметку, она запускаетперенаправить проверку, как видно в этомсхема(который был сделан дляiptablesв виду, но полностью пригоден для использованияnftables). Проверка перенаправления изменяет маршрут... но не изменяет исходный IP-адрес. Так что нужно проделать больше работы.
- добавьте правило NAT для изменения исходного IP-адреса.
Это должно быть сделанопослепроверка перенаправления, поэтому это сделано вnat/постмаршрутизация. Обратите внимание, что одна и та же таблица может иметь разные типы цепочек (в отличие отiptablesгде таблица <=> тип).
nft add chain ip test testnat '{ type nat hook postrouting priority srcnat; policy accept; }'
nft add rule ip test testnat meta mark 1 masquerade
Теперь действительно уходит правильный пакет.
- и разрешить принимать ответный поток, несмотря на то, что он не приходит по маршруту по умолчанию
Вы можете либо расслабитьсяПересылка обратного путив режим Loose, изменив
rp_filter
:sysctl -w net.ipv4.conf.wlo1.rp_filter=2
или пометить ответный поток для использования той же таблицы маршрутизации, что и исходящий поток. Это не улучшит безопасность, но в любом случае:
nft add chain ip test testpre '{ type filter hook prerouting priority mangle; policy accept; }' nft add rule ip test testpre iif "wlo1" meta mark set 1
Увы, это не будет работать без еще одной настройки, которая необходима, поскольку новыйнедокументированная функцияпоявились в 2010 году:
sysctl -w net.ipv4.conf.wlo1.src_valid_mark=1
Примечания:
Можно добиться большей безопасности, сохранив отметку в conntrackконнмарк(
ct mark
) чтобы разрешить только правильные потоки ответов и ничего больше, чтобы обойти Strict Reverse Path Forwarding. В строгом режиме ничего не дойдет черезwlo1больше, если только это не ответ от исходящего трафика. Вот полный соответствующий файл правил nftables для этого (для использования с опцией 2. выше при замене правил nftables):table ip test { chain test { type route hook output priority mangle; policy accept; meta cgroup 1234 meta mark set 1 ct mark set meta mark } chain testnat { type nat hook postrouting priority srcnat; policy accept; meta mark 1 masquerade } chain testpre { type filter hook prerouting priority mangle; policy accept; ct mark 1 meta mark set ct mark } }
Кроме того, проверка перенаправления отметки может в некоторых случаях мешать правильному PMTU / TCP MSS, согласно тому, что я смог прочитать там вдиапазон жидкостивход:https://kernelnewbies.org/Linux_4.10#Сеть
Если вы можете преобразовать использование cgroups в ограниченный набор uid, то это можно сделать правильно, используя только стек маршрутизации, без netfilter или nftables, используя,
ip rule add ... uidrange ...
как описано выше. Смотрите мой ответ там об этом:Маршрутизация трафика для пользователя через определенный интерфейс (tum1).