Я столкнулся со сложной проблемой с исходным NAT при использовании нескольких VRF на маршрутизаторе на основе Debian. Это немного сложно объяснить, поэтому я постараюсь быть ясным, но это не будет коротким, извините за это. Однако проблема должна быть легко воспроизводимой.
Чтобы изолировать «управляющую» часть маршрутизатора (ssh и другие службы) от его работы маршрутизатора (маршрутизация и пакеты NAT), я попытался настроить VRF «mgmt» в VRF по умолчанию (проще иметь дело с сокетами служб) и маршрутизация в VRF под названием «брандмауэр».
Диаграмму можно обобщить следующим образом:
Диаграмма сети
Сеть «управления» — 192.168.100.0/24, и она маршрутизируется коммутатором L3, у которого есть L3 с VRF «брандмауэра» маршрутизатора через сеть 10.254.5.0/24. Третий интерфейс маршрутизатора — это «интернет», и пакеты, проходящие через него, проходят через NAT источника. Эта установка прекрасно работает для всего в подсети mgmt, за исключением собственных пакетов маршрутизатора из-за conntrack.
О правилах iptables:
# Фильтр таблицы
# цепочка ВХОД
-A ВВОД -m conntrack --ctstate СВЯЗАННО, УСТАНОВЛЕНО -j ПРИНЯТЬ
(некоторые правила INPUT для ssh, snmp и т. д.)
-A ВВОД -j DROP
# цепочка ВПЕРЕД
-A FORWARD -m conntrack --ctstate СВЯЗАННО, УСТАНОВЛЕНО -j ПРИНЯТЬ
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A ВПЕРЕД -o eth2 -j ПРИНЯТЬ
-A ВПЕРЕД -j ОПУСКАТЬ
# Таблица физ.
# цепочка РАЗМЕЩЕНИЕ
-A ОТПРАВКА -o eth2 -j SNAT --to-source 192.168.122.100
О таблице маршрутизации:
# VRF по умолчанию
по умолчанию через 192.168.100.1 dev eth0 proto static metric 20
192.168.100.0/24 dev eth0 ссылка области прото-ядра src 192.168.100.90
# межсетевой экран VRF
по умолчанию через 192.168.122.1 dev eth2 proto static metric 20
10.254.5.0/24 dev eth1 ссылка на область ядра proto src 10.254.5.2
192.168.100.0/24 proto bgp metric 20 nexthop via 10.254.5.10 dev eth1 вес 1
192.168.122.0/24 dev eth2 ссылка на область ядра proto src 192.168.122.100
Таким образом, когда пакет из VRF по умолчанию пытается получить доступ к Интернету, он выходит из eth0, маршрутизируется коммутатором L3, входит в VRF брандмауэра через eth1 и маршрутизируется и обрабатывается NAT через eth2. Поскольку я отслеживаю соединения INPUT и FORWARD, conntrack немного сбивается с толку, когда пакет возвращается, и не может знать, что делать с пакетом.
Я смог исправить это для ICMP и UDP, используя зону conntrack в необработанной таблице.
# Необработанная таблица
# цепь PREROUTING
-A PREROUTING -i eth0 -j CT --zone 5
# цепочка ВЫХОД
-A ВЫХОД -o eth0 -j CT --zone 5
С этими правилами пакеты, исходящие от маршрутизатора и проходящие через eth0
являются тегом зона 5
и когда пакеты приходят eth0
они также отмечены зона 5
.
При пинге до 8.8.8.8 это выглядит так (командой коннтрек -E
):
[НОВОЕ] icmp 1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 [БЕЗ ОТВЕТА] src=8.8.8.8 dst=192.168.100.90 type=0 code=0 id=1999 zone=5
[НОВОЕ] icmp 1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 [БЕЗ ОТВЕТА] src=8.8.8.8 dst=192.168.122.100 type=0 code=0 id=1999
[ОБНОВЛЕНИЕ] icmp 1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 src=8.8.8.8 dst=192.168.122.100 type=0 code=0 id=1999
[ОБНОВЛЕНИЕ] icmp 1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 src=8.8.8.8 dst=192.168.100.90 type=0 code=0 id=1999 zone=5
Мы видим здесь первый НОВЫЙ
соединение создается, когда пакет проходит eth0
с зона=5
тег, затем новый, когда он входит в брандмауэр VRF через эт1
без тега. Когда приходит ответ, сначала обновляется второе соединение (поскольку оно выходит в Интернет), а затем первое.
Это также работает с UDP, например, с DNS-запросом на 8.8.8.8.
[НОВОЕ] udp 17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 [БЕЗ ОТВЕТА] src=8.8.8.8 dst=192.168.100.90 sport=53 dport=53369 zone=5
[НОВОЕ] udp 17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 [БЕЗ ОТВЕТА] src=8.8.8.8 dst=192.168.122.100 sport=53 dport=53369
[ОБНОВЛЕНИЕ] udp 17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 src=8.8.8.8 dst=192.168.122.100 sport=53 dport=53369
[ОБНОВЛЕНИЕ] udp 17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 src=8.8.8.8 dst=192.168.100.90 sport=53 dport=53369 zone=5
Но с TCP это не работает. Telnet-запрос к порту 80 172.16.10.10 выглядит следующим образом:
[НОВОЕ] tcp 6 120 SYN_SENT src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 [БЕЗ ОТВЕТА] src=172.16.10.10 dst=192.168.100.90 sport=80 dport=60234 zone=5
[НОВОЕ] tcp 6 120 SYN_SENT src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 [БЕЗ ОТВЕТА] src=172.16.10.10 dst=192.168.122.100 sport=80 dport=60234
[ОБНОВЛЕНИЕ] TCP 6 58 SYN_RECV src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 src=172.16.10.10 dst=192.168.122.100 sport=80 dport=60234
[ОБНОВЛЕНИЕ] TCP 6 57 SYN_RECV src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 src=172.16.10.10 dst=192.168.122.100 sport=80 dport=60234
(Последняя строка повторяется несколько раз)
Если я tcpdump эт2
ответ там:
IP 192.168.122.100.60236 > 172.16.10.10.80: флаги [S], seq 4203590660, win 62720, параметры [mss 1460,sackOK,TS val 1511828881 ecr 0,nop,wscale 7], длина 0
IP 172.16.10.10.80 > 192.168.122.100.60236: Флаги [S.], seq 3672808466, ack 4203590661, win 65535, параметры [mss 1430, sackOK, TS val 2474659117 ecr 1511828881], length, 08nop, ww
IP 192.168.122.100.60236 > 172.16.10.10.80: флаги [S], seq 4203590660, win 62720, параметры [mss 1460,sackOK,TS val 1511829887 ecr 0,nop,wscale 7], длина 0
IP 172.16.10.10.80> 192.168.122.100.60236: флаги [S.], seq 3672808466, ack 4203590661, win 65535, параметры [mss 1430, sackOK, TS val 2474660123 ecr 1511828881], length, 08nop w
Но поскольку SIN ACK никогда не подтверждается, маршрутизатор продолжает отправлять новый SIN.
Теперь, если я tcpdump эт1
:
IP 192.168.100.90.60238 > 172.16.10.10.80: флаги [S], seq 3124513394, win 62720, параметры [mss 1460,sackOK,TS val 1511928806 ecr 0,nop,wscale 7], длина 0
IP 192.168.100.90.60238 > 172.16.10.10.80: флаги [S], seq 3124513394, win 62720, параметры [mss 1460,sackOK,TS val 1511929823 ecr 0,nop,wscale 7], длина 0
IP 192.168.100.90.60238 > 172.16.10.10.80: флаги [S], seq 3124513394, win 62720, параметры [mss 1460,sackOK,TS val 1511931839 ecr 0,nop,wscale 7], длина 0
Мы видим, что ответ никогда не направляется обратно на 192.168.100.90.
Если отключить отслеживание соединений и разрешить все в iptables, все работает. Итак, я думаю, что у conntrack есть проблемы с управляемыми TCP-соединениями от себя к другой зоне, когда они NAT? Если что-то будет непонятно, с удовольствием отвечу на любые вопросы по этому поводу.