Policy-routing на CentOS

Довольно распространённая ситуация — на моёй рабочей станции есть два интерфейса и два айпишника, скажем из подсети А и подсети Б. При обращении клиента с хоста из сети Б к моему айпишнику из подсети А ответ к нему уходит через другой интерфейс с моего айпишника из подсети Б, т.к. он из той же подсети, что и адрес клиента. Мне надо сделать, чтобы эти ответы уходили с того же адреса на который пришли.

Тут нужен policy-routing — маршрутизация на основе определённых правил. Логика получается такая: ответы на запросы из подсети Б к моему адресу из подсети А отправлять с адреса из подсети А (т.е. на шлюз подсети А).

Маркируем соединения из сети Б к нашему адресу из сети А при помощи iptables и таблицу mangle (используется для изменения пакетов):
iptables -t mangle -I INPUT -i eth0 -s 10.1.100.0/24 -d 10.2.96.3 -j CONNMARK --set-mark 1
А на выходе копируем маркировку соединения в маркировку пакетов, насколько я понимаю, это означает, что мы маркируем пакеты промаркированных ранее соединений:
iptables -t mangle -I OUTPUT -s 10.2.96.3 -d 10.1.100.0/24 -j CONNMARK --restore-mark
Вероятно, в этом правиле можно обойтись и без указания адресов источника и адресата, но мне кажется так будет правильнее, более точно чтоли )

В таблицу маршрутизации 111 добавляем маршрут для сети Б, но на шлюз из подсети А:
ip route add to 10.1.100.0/24 via 10.2.96.1 dev eth0 table 111
И, наконец, добавляем правило для перенаправления пакетов с нашей маркировкой в отдельную таблицу маршрутизации:
ip rule add fwmark 1 lookup 111

Для удобства можно назначить название для таблицы в файле /etc/iproute2/rt_tables, которое можно будет использовать вместо номера.

Так же нужно проверить не включена ли проверка обратного пути (reverse path checking):
sysctl net.ipv4.conf.eth0.rp_filter
Если включена, то система будет проверять пакеты на соответствие источника интерфейсу, с которого пакет получен. Например, если пакет пришёл с адреса, который виден через другой интерфейс (а не тот, с которого пакет пришёл), то значит этот пакет надо отбросить.

Если всё заработало как надо, то сохраняем правила iptables в файл "/etc/sysconfig/iptables", а правила для маршрутизации в файл "/etc/sysconfig/network-scripts/route-eth0".

Далее несколько вспомогательных команд, которые могут пригодиться.

Посмотреть определённую таблицу маршрутизации:
ip route show table 111
Удалить маршрут из указанной таблицы
ip route del table 111 to 10.1.100.0/24
Посмотреть правила маршрутизации:
ip rule show
Удалить правило маршрутизации:
ip rule del fwmark 1

Как посмотреть правила iptables писать не буду )

Утилита управления сетевыми настройками ip

Странно как-то в Линуксе организовано управление сетевыми настройками — какие-то дополнительные утилиты, которые делают то, что во ФриБСД делается уже существующими утилитами. В частности утилита ip, которая частично дублирует функции утилит ifconfig, route и ещё бог весть каких. При этом утилитой ifconfig можно назначить айпишник, а удалить уже не получается.

Несколько примеров применения утилиты ip:

ip addr show dev eth1
ip addr add 10.1.1.224/26 dev eth1 (второй адрес добавляется также)
ip addr del 10.1.1.224/26 dev eth1

Добавить IPv6-адрес на интерфейс, можно как второй для уже существующего IPv4-адреса:
ip addr add 2001:0db8::21d:fff:febe:afec/64 dev eth0.10
ip addr del 2001:0db8::21d:fff:febe:afec/64 dev eth0.10

ip link show dev eth1
ip link set up dev eth1
ip link set down dev eth1

Добавить ВЛАН-интерфейс:
ip link add dev eth1.10 link eth1 type vlan id 10
Удалить интерфейс:
ip link del dev eth1.10

ip route show
Показать маршрут по-умолчанию по слову default или маршруту 0.0.0.0 утилита отказалась — показала всю таблицу, надо вот так:
ip route show 0/0
ip -6 route show ::/0

Показать точный маршрут к хосту (если есть маршрут на подсеть, в которую входит указанный хост, то он не учитывается):
ip route show 10.2.2.1
ip route show to exact 10.2.2.1
ip -6 route show 2001:db8::/64

Показать подходящий маршрут к хосту, например, если есть маршрут на соответствующую подсеть:
ip route show to match 10.2.2.1

ip route add 10.2.2.0/24 via 10.1.1.1
ip route add to 10.2.2.0/24 via 10.1.1.1

ip route delete 10.2.2.1
ip route delete 10.2.2.0/24

Удалить маршрут по-умолчанию и добавить его:
ip route delete default
ip route add default via 10.1.1.1