Рейтинг:2

Conntrack, не удалось преобразовать NAT собственные TCP-пакеты из другого VRF.

флаг us

Я столкнулся со сложной проблемой с исходным 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? Если что-то будет непонятно, с удовольствием отвечу на любые вопросы по этому поводу.

Рейтинг:1
флаг us

Проблема присутствовала в Debian 10 с ядром 4.19.0-12-amd64, но после обновления до Debian 11 с ядром 5.10.0-11-amd64 она работает, как и ожидалось, даже для потоков TCP.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.