Как оказалось, в Linux можно использовать ipset соответствия для выбора таблиц маршрутизации. Дополнительным компонентом является использование правила сетевого фильтра, которое будет сопоставлять исходящие пакеты и применять fwmark к ним, которые затем могут быть использованы для выбора выделенной таблицы маршрутизации. Затем эта выделенная таблица маршрутизации будет содержать только один маршрут по умолчанию через VPN.
Вот в виде скрипта общая идея, как это настроить.
# Подсети для маршрутизации через TUN
ДСТНЕТС=.../...../..
# Исключаем эти пункты назначения из маршрутизации через TUN
ИСКЛЮЧИТЬ=... ...
# Устройство TUN, используемое для этого соединения, и его параметры. Обычно они предоставляются демоном VPN.
ТУНДЕВ=...
ТУНАДДР=.../..
ТУНПЕР=...
# Имя для ipset, используемого для сопоставления адресатов. База на названии TUN
IPSET=${TUNDEV}ipset
# Нам нужен сетевой фильтр fwmark и таблица iproute2. fwmarks и таблицы представляют собой 32-битные значения, ограниченные диапазоном целых чисел со знаком, т. е. [0, 2³¹-1] fwmarks могут использоваться как битовые маски, сигнализирующие о нескольких флагах, поэтому в зависимости от наших потребностей либо установите один конкретный бит (или несколько), либо очень конкретное значение, которое затем сравнивается на равенство.
FWMARK=0x...
ТАБЛИЦА=0x...
# Создайте ipset и заполните его диапазонами IP-адресов и подсетей, которые должны соответствовать или не соответствовать.
ipset создать $IPSET hash:net
для d в $DSTNETS ; добавить ipset $IPSET $d ; сделано
для x в $EXCLUDE ; do ipset add $IPSET $x nomatch ; сделано
# Создать новую таблицу правил iproute2, которая будет использоваться для поиска маршрута для всех пакетов, для которых установлен наш fwmark выбора
ip правило добавить fwmark $FWMARK таблицу $TABLE
# Вот где происходит волшебство: создайте правило netfilter, которое будет сопоставлять пакеты, исходящие с этого хоста, для пунктов назначения, которые соответствуют только что созданному нами ipset, и пометьте их выбранной нами fwmark. Из-за правила, которое мы только что создали ранее, эти пакеты будут маршрутизироваться с использованием этой конкретной таблицы, а не глобальных.
iptables -t mangle -A ВЫВОД -m set --match-set $IPSET dst -j MARK --set-mark $FWMARK
# Также добавьте правило сетевого фильтра для перезаписи исходного адреса для этих пакетов, так как сеть назначения, скорее всего, отклонит их, если они не соответствуют диапазону адресов, используемому для VPN
iptables -t nat -A POSTROUTING -m set --match-set $IPSET dst -j SNAT --to-source $INTERNAL_IP4_ADDRESS
# Теперь мы можем настроить фактическое устройство TUN.Строго говоря, эти шаги можно было сделать и раньше, но тогда в течение короткого промежутка времени между появлением TUN и установлением правил маршрутизации некоторые пакеты могли оказаться в подвешенном состоянии.
ip link set dev $TUNDEV up
IP-адрес добавить узел $TUNADDR $TUNPEER dev $TUNDEV
# Наконец, установите маршрут по умолчанию, проходящий через TUN в нашей выделенной таблице маршрутизации, которая из-за правила fwmark будет затронута только пакетами, соответствующими нашему ipset
ip route добавить устройство по умолчанию $TUNDEV таблица $TABLE
Чтобы все снести, просто следуйте сценарию в обратном порядке, удаляя вещи; в ipset возможно разрушать
ed с помощью одной команды.