“ip rule to” работает, но “ip rule fwmark” не работает – почему?

Вопрос или проблема

У меня есть роутер на CentOS 6 (ядро 2.6.32) с работающим клиентом OpenVPN, и я хочу перенаправить некоторый трафик через VPN-сервер.

Клиент (192.168.60.159) отправляет запрос на роутер (192.168.60.6:1443), и роутер перенаправляет его через VPN-соединение (10.200.0.54) на сервер (185.61.149.21:443).

Я создал отдельную таблицу маршрутизации tunde и правило для использования этой таблицы на пакетах, помеченных iptables. Это правило имеет шлюз по умолчанию на VPN, в то время как основная таблица маршрутизации имеет реальный шлюз. Когда я пытаюсь использовать ip rule add fwmark 0x64 lookup tunde, это не удается. Запрос проходит на сервер нормально, сервер отвечает, роутер получает ответ, но не передает его клиенту.

Но если я добавлю ip rule add to 185.61.149.21 lookup tundeвсё работает прекрасно. (Но это правило не удовлетворяет моим потребностям, мне нужно маршрутизировать по портам)

Похоже, что iptables по какой-то причине не может демаскировать ответы.

Есть какие-нибудь идеи? Спасибо!

#ip rule ls
32765:  from all fwmark 0x64 lookup tunde

Эта таблица маршрутизации имеет шлюз по умолчанию на VPN:

#ip route ls table tunde
10.200.0.53 dev tunde  proto kernel  scope link  src 10.200.0.54
192.168.60.0/24 dev eth0  proto kernel  scope link  src 192.168.60.6
default via 10.200.0.53 dev tunde  src 10.200.0.54

В то время как основная таблица маршрутизации имеет реальный шлюз по умолчанию:

# ip route ls
10.200.0.53 dev tunde  proto kernel  scope link  src 10.200.0.54
192.168.60.0/24 dev eth0  proto kernel  scope link  src 192.168.60.6
default via 192.168.60.1 dev eth0

Tcpdump показывает как запросы, так и ответы на интерфейсе TUN:

# tcpdump -i tunde -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tunde, link-type RAW (Raw IP), capture size 65535 bytes
15:50:37.136708 IP 10.200.0.54.51409 > 185.61.149.21.443: Flags [S], seq 302961260, win 65280, options [mss 1360,nop,wscale 8,nop,nop,sackOK], length 0
15:50:37.209278 IP 185.61.149.21.443 > 10.200.0.54.51409: Flags [S.], seq 390829204, ack 302961261, win 29200, options [mss 1357,nop,nop,sackOK,nop,wscale 9], length 0
15:50:38.219458 IP 185.61.149.21.443 > 10.200.0.54.51409: Flags [S.], seq 390829204, ack 302961261, win 29200, options [mss 1357,nop,nop,sackOK,nop,wscale 9], length 0
15:50:40.136933 IP 10.200.0.54.51409 > 185.61.149.21.443: Flags [S], seq 302961260, win 65280, options [mss 1360,nop,wscale 8,nop,nop,sackOK], length 0
15:50:40.182989 IP 185.61.149.21.443 > 10.200.0.54.51409: Flags [S.], seq 390829204, ack 302961261, win 29200, options [mss 1357,nop,nop,sackOK,nop,wscale 9], length 0
15:50:42.191772 IP 185.61.149.21.443 > 10.200.0.54.51409: Flags [S.], seq 390829204, ack 302961261, win 29200, options [mss 1357,nop,nop,sackOK,nop,wscale 9], length 0
15:50:42.892051 IP 185.61.149.21.443 > 10.200.0.54.51391: Flags [S.], seq 528990609, ack 3345061728, win 29200, options [mss 1357,nop,nop,sackOK,nop,wscale 9], length 0

В журнале iptables я также вижу ответы. Все пакеты помечены и используют правильную таблицу маршрутизации:

# tail -f /var/log/messages
Oct 10 15:50:37 toy2 kernel: INPUT from Cli:  IN=eth0 OUT= MAC=00:15:5d:3c:bc:03:1c:39:47:f0:74:87:08:00 SRC=192.168.60.159 DST=192.168.60.6 LEN=52 TOS=0x00 PREC=0x00 TTL=128 ID=19050 DF PROTO=TCP SPT=51409 DPT=1443 WINDOW=65280 RES=0x00 SYN URGP=0 MARK=0x64
Oct 10 15:50:37 toy2 kernel: Forward To TUN:   IN=eth0 OUT=tunde SRC=192.168.60.159 DST=185.61.149.21 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=19050 DF PROTO=TCP SPT=51409 DPT=443 WINDOW=65280 RES=0x00 SYN URGP=0 MARK=0x64
Oct 10 15:50:37 toy2 kernel: OUTPUT To TUN:  IN= OUT=tunde SRC=192.168.60.159 DST=185.61.149.21 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=19050 DF PROTO=TCP SPT=51409 DPT=443 WINDOW=65280 RES=0x00 SYN URGP=0 MARK=0x64
Oct 10 15:50:37 toy2 kernel: INPUT from TUN:  IN=tunde OUT= MAC= SRC=185.61.149.21 DST=10.200.0.54 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=443 DPT=51409 WINDOW=29200 RES=0x00 ACK SYN URGP=0 MARK=0x64
Oct 10 15:50:38 toy2 kernel: INPUT from TUN:  IN=tunde OUT= MAC= SRC=185.61.149.21 DST=10.200.0.54 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=443 DPT=51409 WINDOW=29200 RES=0x00 ACK SYN URGP=0 MARK=0x64
Oct 10 15:50:40 toy2 kernel: INPUT from Cli:  IN=eth0 OUT= MAC=00:15:5d:3c:bc:03:1c:39:47:f0:74:87:08:00 SRC=192.168.60.159 DST=192.168.60.6 LEN=52 TOS=0x00 PREC=0x00 TTL=128 ID=19063 DF PROTO=TCP SPT=51409 DPT=1443 WINDOW=65280 RES=0x00 SYN URGP=0 MARK=0x64
Oct 10 15:50:40 toy2 kernel: Forward To TUN:   IN=eth0 OUT=tunde SRC=192.168.60.159 DST=185.61.149.21 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=19063 DF PROTO=TCP SPT=51409 DPT=443 WINDOW=65280 RES=0x00 SYN URGP=0 MARK=0x64
Oct 10 15:50:40 toy2 kernel: INPUT from TUN:  IN=tunde OUT= MAC= SRC=185.61.149.21 DST=10.200.0.54 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=443 DPT=51409 WINDOW=29200 RES=0x00 ACK SYN URGP=0 MARK=0x64
Oct 10 15:50:42 toy2 kernel: INPUT from TUN:  IN=tunde OUT= MAC= SRC=185.61.149.21 DST=10.200.0.54 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=443 DPT=51409 WINDOW=29200 RES=0x00 ACK SYN URGP=0 MARK=0x64
Oct 10 15:50:42 toy2 kernel: INPUT from TUN:  IN=tunde OUT= MAC= SRC=185.61.149.21 DST=10.200.0.54 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=443 DPT=51391 WINDOW=29200 RES=0x00 ACK SYN URGP=0 MARK=0x64

(смотрите MARK=0x64 на исходящих и входящих пакетах)

Теперь правила iptables:

# iptables-save

*mangle
:PREROUTING ACCEPT [6278:3182515]
:INPUT ACCEPT [4169:3043489]
:FORWARD ACCEPT [9:468]
:OUTPUT ACCEPT [677:98865]
:POSTROUTING ACCEPT [703:101438]
-A PREROUTING -d 192.168.60.6/32 -i eth0 -p tcp -m tcp --dport 1443 -m state --state NEW -j CONNMARK --set-xmark 0x64/0xffffffff
-A PREROUTING -m state --state RELATED,ESTABLISHED -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff
-A PREROUTING -m connmark --mark 0x64 -j MARK --set-xmark 0x64/0xffffffff
-A PREROUTING -m state --state NEW -m connmark ! --mark 0x0 -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff
-A PREROUTING -i tunde -j LOG --log-prefix " INPUT from TUN:  "
-A PREROUTING -s 192.168.60.159/32 -i eth0 -p tcp -m tcp --dport 1443 -j LOG --log-prefix " INPUT from Cli:  "
COMMIT

*nat
:PREROUTING ACCEPT [3487:307264]
:POSTROUTING ACCEPT [57:13668]
:OUTPUT ACCEPT [57:13668]
-A PREROUTING -d 192.168.60.6/32 -i eth0 -p tcp -m tcp --dport 1443 -j DNAT --to-destination 185.61.149.21:443
-A POSTROUTING -o tunde -j LOG --log-prefix " OUTPUT To TUN:  "
-A POSTROUTING -d 192.168.60.159/32 -o eth0 -p tcp -m tcp --sport 1443 -j LOG --log-prefix " OUTPUT To Cli:  "
-A POSTROUTING -o tun+ -j MASQUERADE
COMMIT

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [680:99605]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m multiport --dports 22,23 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 1443 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -i tunde -j LOG --log-prefix " Forward From TUN: "
-A FORWARD -o tunde -j LOG --log-prefix " Forward To TUN:   "
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -p icmp -j ACCEPT
-A FORWARD -i eth0 -o tun+ -j ACCEPT
-A FORWARD -i tun+ -o eth0 -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

РЕШЕНО!

С помощью детального логирования я выяснил, что пакеты были отброшены после mangle/PREROUTING и не проходили в nat/PREROUTING. Это связано с тем, что ядро по умолчанию обрабатывает “нежелательные” пакеты.

Команда

# echo 0 >/proc/sys/net/ipv4/conf/$interface/rp_filter

отключает этот механизм фильтрации, и всё снова работает нормально.

Одно, что спасло бы меня от потери времени:

Для меня пометки файрвола не работали, потому что у меня не была настроена маршрут по умолчанию.

[root@testing ~]# ip ro
10.20.30.0/24 dev ens18 proto kernel scope link src 10.20.30.253 metric 100 
10.20.40.0/24 dev ens19 proto kernel scope link src 10.20.40.253 metric 101 

Моя ситуация:

  • Два независимых файрвола
  • Оба имеют две внутренние сети
  • Внутренний сервер в обеих внутренних сетях

Ничего не работало, пока я не добавил шлюз, так что теперь я подключен 4 раза:

[root@testing ~]# ss -ant | grep EST
ESTAB  0      80                  10.20.40.253:22                home.ipv4.a.37:58512
ESTAB  0      0                   10.20.30.253:22               home.ipv4.b.126:33206
ESTAB  0      0                   10.20.30.253:22               home.ipv4.b.126:57566
ESTAB  0      0                   10.20.40.253:22                home.ipv4.a.37:54238
ESTAB  0      0           [fd00:1:2:3:4::fffd]:22    [2a01:my:own:home:i:p:v:6]:53218

Надеюсь, это сэкономит кому-то время.

Ответ или решение

Вопрос, рассматриваемый в вашем случае, связан с использованием правил маршрутизации в Linux с применением меток пакетов (fwmark) в контексте работы с OpenVPN на маршрутизаторе на базе CentOS 6 с ядром 2.6.32. Судя по вашему описанию, вы столкнулись с проблемой, когда правило ip rule add fwmark не работало должным образом, несмотря на то, что правило ip rule add to работало безотказно.

Суть проблемы

На основе ваших данных, основное различие между двумя правилами заключается в том, что первое использует маркировку пакетов с помощью iptables для маршрутизации трафика, в то время как второе определяет маршрут по конкретному адресу назначения. Вы отметили, что при использовании fwmark маршрутизация не срабатывает должным образом, трафик возвращается от сервера, но не доставляется клиенту.

Анализ и решение

1. Обработка пакетов с использованием fwmark

Ваша установка маршрутизации с использованием меток подключает трафик на основе прибыли через интерфейс TUN. Когда вы добавляете правило с fwmark, пакеты должны маршрутизироваться в соответствии с правилами, установленными в таблице маршрутов, где указаны выходные интерфейсы и основные шлюзы.

2. Особенности фильтрации пакетов

Важным моментом, который вы указываете в своем решении, является необходимость отключения функции проверки обратных маршрутов (reverse path filtering). Данная функция может блокировать пакеты, которые, согласно маршрутизации, не соответствуют ожидаемому пути обратного трафика. Чтобы отключить эту проверку, вы использовали следующую команду:

# echo 0 > /proc/sys/net/ipv4/conf/$interface/rp_filter

3. Роль маршрутов по умолчанию

Вы также заметили, что отсутствие маршрута по умолчанию может быть критическим фактором. Правильная маршрутизация требует корректной настройки маршрутов, чтобы трафик мог направляться к VPN после обработки пакетов. Если используется несколько интерфейсов, необходимо удостовериться, что указаны все необходимые маршруты.

Заключение

На основании предоставленной информации, основная причина, по которой правило ip rule add fwmark не функционировало должным образом, была связана с проверкой обратных маршрутов и отсутствием маршрута по умолчанию. Теперь, когда вы отключили проверку реверсивных маршрутов и удостоверились в правильности маршрутизации, проблема была успешно решена.

Работа с маркировкой пакетов и многоуровневой маршрутизацией может оказаться сложной задачей, но соблюдение этих аспектов поможет избежать большинства накапливающихся проблем. Рекомендуется также регулярно проверять и анализировать ваши iptables и маршруты для поддержания их актуальности и функционирования.

Такое решение может быть полезным не только вам, но и другим администраторам, сталкивающимся с аналогичными ситуациями.

Оцените материал
Добавить комментарий

Капча загружается...