У меня есть сервер debian с 3 сетевыми интерфейсами:
Между этими интерфейсами находится межсетевой экран. Множественные маршруты на сервере приводят к асимметричной маршрутизации, которая была заблокирована межсетевым экраном как недопустимый трафик.
По этой причине я добавил несколько правил на основе политик, чтобы IP-адрес назначения / источника остался прежним. Я добился этого, отредактировав свой /etc/network/interfaces
как это:
# The primary network interface
allow-hotplug eno1
iface eno1 inet dhcp
post-up ip route add 10.0.0.0/24 dev eno1 table 1
post-up ip route add default via 10.0.0.1 table 1
post-up ip rule add from 10.0.0.35/32 table 1 priority 100
post-up ip route flush cache
pre-down ip rule del from 10.0.0.35/32 table 1 priority 100
pre-down ip route flush table 1
pre-down ip route flush cache
# VLANS
auto eno1.10
iface eno1.10 inet dhcp
post-up ip route add 10.0.10.0/24 dev eno1.10 table 2
post-up ip route add default via 10.0.10.1 table 2
post-up ip rule add from 10.0.10.65/32 table 2 priority 110
post-up ip route flush cache
pre-down ip rule del from 10.0.10.65/32 table 2 priority 110
pre-down ip route flush table 2
pre-down ip route flush cache
auto eno1.40
iface eno1.40 inet dhcp
post-up ip route add 10.0.40.0/24 dev eno1.40 table 3
post-up ip route add default via 10.0.40.1 table 3
post-up ip rule add from 10.0.40.40/32 table 3 priority 120
post-up ip route flush cache
pre-down ip rule del from 10.0.40.40/32 table 3 priority 120
pre-down ip route flush table 3
pre-down ip route flush cache
Все сервисы работают на сервер теперь работал так, как должен.
Кроме того, у меня есть докер-хост, работающий на сервере, на котором размещены некоторые контейнеры, привязанные к различным интерфейсам на сервере.
Теперь проблема в том, что созданные мной правила, по-видимому, не применяются к трафику, исходящему из контейнеров докеров, и я не могу получить к ним доступ, потому что трафик блокируется как недействительный.
Что мне нужно сделать здесь, чтобы контейнеры докеров знали, какой маршрут использовать в соответствии с исходным IP-адресом?
Быстрое решение:
ip rule add fwmark 0x1 lookup 1 pref 10001
ip rule add fwmark 0x2 lookup 2 pref 10002
ip rule add fwmark 0x3 lookup 3 pref 10003
iptables -t mangle -A PREROUTING -m conntrack --ctstate NEW -i eno1 -j CONNMARK --set-mark 0x1
iptables -t mangle -A PREROUTING -m conntrack --ctstate NEW -i eno1.10 -j CONNMARK --set-mark 0x2
iptables -t mangle -A PREROUTING -m conntrack --ctstate NEW -i eno1.40 -j CONNMARK --set-mark 0x3
-i
сопоставить или сопоставить по адресу источника, в противном случае вам нужно добавить напрямую подключенные маршруты в дополнительные таблицы.iptables -t mangle -A PREROUTING -i docker0 -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING --src <container-subnet> -j --restore-mark
DNAT
.tcpdump
и conntrack
инструмент для устранения проблем.rp_filter
. В некоторых случаях он может отбрасывать пакеты. Лучше установите его в loose
Режим (sysctl -w net.ipv4.conf.all.rp_filter=2
).После нескольких тестов в лаборатории я нашел идеальный набор правил. Для этого требуется только одно значение отметки и одно дополнительное правило маршрутизации для каждого восходящего канала. Он также обрабатывает сложные случаи, когда вы используете публичные адреса на нескольких интерфейсах.
ip route add <uplink-subnet> dev <uplink-iface> table <uplink-table>
ip route add 0/0 via <uplink-gw> dev <uplink-iface> table <uplink-table>
ip rule add fwmark <uplink-mark> table <uplink-table>
iptables -t mangle -A PREROUTING -i <uplink-iface> -m conntrack --ctstate NEW --ctdir ORIGINAL -j CONNMARK --set-mark <uplink-mark>
...
iptables -t mangle -A PREROUTING -m conntrack ! --ctstate NEW --ctdir REPLY -m connmark ! --mark 0x0 -j CONNMARK --restore-mark
iptables -t mangle -A OUTPUT -m conntrack ! --ctstate NEW --ctdir REPLY -m connmark ! --mark 0x0 -j CONNMARK --restore-mark