LINUX.ORG.RU
решено ФорумAdmin

Multihomed, CONNMARK и rp_filter.

 


0

1

Сабж. http://habrahabr.ru/sandbox/38722/

На ЛОР-е тоже встречал много ответов типа «отключи rp_filter» по этой же проблеме

К примеру, у меня eth174 - линк одного из провайдеров(маршрут НЕ по-умолчанию) и eth0 - локальная сеть. iptables настроен с помощью CONNMARK. Таблицы, маршрутизация, всё настроено. Если отключить rp_filter тогда DNAT до eth0 192.168.1.1 будет работать, если нет то не будет(при rp_fiter=2 все работает). Т.е. что делать понятно, непонятно почему.... Ведь там используюся известные IP-адреса...

Не могу понять почему так. Кто-нибудь может дать развёрнутый ответ почему так?

ЗЫ. Хотя завтро с утра всяко будет виднее...

★★

Последнее исправление: greek_31 (всего исправлений: 1)

rp_filter будет срабатывать при роутинге пакета, по твоей же ссылке соединение маркируют _после_ роутинга. Возможно, поэтому пакеты у тебя и отбрасываются. Надо маркировать в PREROUTING, либо в post-up интерфейса сделать добавление правила ip rule для адреса на интерфейсе. Т.е., ip rule add to $addr table $table.

Если не поможет, приложи вывод ip rule, ip route той таблицы, которая относится к провайдеру на eth174, а также выдержку из вывода iptables-save, касающуюся маркировки пакетов и соединений.

anonymous
()

игры с rp_filter обычно устраивают при ассиметричной машрутизации, когда пакеты туда и обратно ходят через разные интерфейсы.

vel ★★★★★
()
Ответ на: комментарий от anonymous

ну вот

ip rule
32762:	from all fwmark 0x14 lookup isp1
32763:	from all fwmark 0xa lookup isp2
32764:	from xxx.xxx.xxx.xxx lookup isp1
32765:	from xxx.xxx.xxx.xxx lookup isp2
32766:	from all lookup main 
32767:	from all lookup default

ip ro list table isp2
default via xxx.xxx.xxx dev eth2 
link-local
iptables -t mangle -v -n
Chain PREROUTING (policy ACCEPT 9059K packets, 6790M bytes)
 pkts bytes target     prot opt in     out     source               destination         
67943 5338K CONNMARK   all  --  eth2   *       0.0.0.0/0            0.0.0.0/0            CONNMARK restore
  661 52814 CONNMARK   all  --  eth2   *       0.0.0.0/0            xxx.xxx.xxx.xxx       CONNMARK set 0x14
5109K 6449M CONNMARK   all  --  eth1   *       0.0.0.0/0            xxx.xxx.xxx.xxx        CONNMARK set 0xa

Chain INPUT (policy ACCEPT 714K packets, 239M bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 8336K packets, 6550M bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 629K packets, 239M bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 8953K packets, 6788M bytes)
 pkts bytes target     prot opt in     out     source               destination

И где-то в NAT PREROUTING:

Chain PREROUTING (policy ACCEPT 432K packets, 30M bytes)
 pkts bytes target     prot opt in     out     source               destination         
   19   964 DNAT       tcp  --  eth2   *       0.0.0.0/0            xxx.xxx.xxx.xxx       multiport dports 4444:4444 to:192.168.1.1
    7   308 DNAT       tcp  --  eth1   *       0.0.0.0/0            xxx.xxx.xxx.xxx        multiport dports 3333:4444 to:192.168.1.1

greek_31 ★★
() автор топика
Ответ на: комментарий от vel

игры с rp_filter обычно устраивают при ассиметричной машрутизации, когда пакеты туда и обратно ходят через разные интерфейсы.

Так вот я и не понимаю почему с rp_filter работает. Я хочу как раз симметричную.

greek_31 ★★
() автор топика

В общем, сделал трассировку пакета в iptables при rp_filter = 1. Судя по диаграмме: https://upload.wikimedia.org/wikipedia/ru/a/ad/Netfilter-diagram-rus.png

Пакет проходит mangle PREROUTING и nat PREROUTING и дальше идет этап маршрутизации, где пакет отбрасывается.

Последнее правило перед дропом(слегка сократил):

nat:PREROUTING:rule:1 IN=eth2 OUT= SRC=REMOTE IP DST=ETH2_IP LEN=44 TTL=38 ID=58041 PROTO=TCP OPT (020405B4)
Это правило делает DNAT на один из локальных адресов которые видит eth0.

Итак, мои выводы.

Путь пакета будет такой начиная с mangle(состояние соединения уже определено conntrack) Для примера входящий интерфейс eth15, НЕ являющийся шлюзом по-умолчанию, а локальная сеть eth0:

  1. mangle PREROUTING маркирует пакет в зависимости от интерфейса eth1 - 0x1, eth15 - 0x15 и т.д.
  2. nat PREROUTING Если тут срабатывает правило DNAT на локальный или другой интерфейс, то на входе на следующий этап получается такая картина: in_if=«eth15» DST_IP=«ETH0_IP»
  3. Если rp_filter включен, то пакет будет отброшен, т.к. на eth15 нет адреса ETH0_IP. Этап форвардинга еще не наступил, поэтому система еще не знает, что пакет — правильный.

Т.к. правила DNAT должны быть в PREROUTING(не вижу другого use-case), то необходима установка rp_filter в значение 2 для всех внешний интерфейсов, которые используют DNAT

Занавес...

greek_31 ★★
() автор топика

виной тому route cache который не очень дружит со маркировками

у самого роутер с 3 разными маршрутами в интернет, так же отключил rp_filter на внешних интерфейсах и не долблю себе мозгсплю спокойно

Rost ★★★★★
()
Последнее исправление: Rost (всего исправлений: 1)
Ответ на: комментарий от greek_31

Все это вполне можно заставить работать с включенным rp_filter, надо только знать, что происходит внутри.

Если rp_filter включен, то пакет будет отброшен, т.к. на eth15 нет адреса ETH0_IP. Этап форвардинга еще не наступил, поэтому система еще не знает, что пакет — правильный.

Во-первых, rp_filter работает не так, как ты описал. Пакет отбрасывается, если он пришел не на тот интерфейс, куда пойдет ответ. Интерфейс, куда должен пойти ответ, определяется таблицей маршрутизации, в которую пакет попал согласно правил ip rule.

Во-вторых, таргетом CONNMARK ты маркируешь соединение, не пакет. Поэтому он не матчится правилом from all fwmark 0xa lookup isp2 и попадает в таблицу main, где дефолтный маршрут - через другой интерфейс.

Хороший вариант - добавить такие правила:

ip rule add to xx.xx.xx.xx table isp1
ip rule add to xx.xx.xx.xx table isp2
, где xx.xx.xx.xx - внешние адреса, соответствующие провайдерам isp1 и isp2. Тогда пакет попадет в правильную таблицу, и все должно заработать.

Deleted
()
Ответ на: комментарий от Deleted

Впрочем, мне тоже не удалось заставить все это работать с rp_filter=1 на интерфейсе. Пакет проделал такой путь:

TRACE: raw:PREROUTING:policy:7 SRC=ip1 DST=ip2 SYN URGP=0 OPT (020405B40402080A29CC523E0000000001030307) 
TRACE: mangle:PREROUTING:rule:1 SRC=ip1 DST=ip2 SYN URGP=0 OPT (020405B40402080A29CC523E0000000001030307) 
TRACE: mangle:PREROUTING:rule:2 SRC=ip1 DST=ip2 SYN URGP=0 OPT (020405B40402080A29CC523E0000000001030307) 
TRACE: mangle:PREROUTING:policy:5 SRC=ip1 DST=ip2 SYN URGP=0 OPT (020405B40402080A29CC523E0000000001030307) MARK=0x4 
TRACE: nat:PREROUTING:rule:46 SRC=ip1 DST=ip2 SYN URGP=0 OPT (020405B40402080A29CC523E0000000001030307) MARK=0x4
После этого его отбросили. rp_filter=1 - на интерфейсе с адресом ip2. Правила в таблице mangle, которые применились к нему:
-A PREROUTING -d ip2 -p tcp -m tcp --dport 1194 -j CONNMARK --set-xmark 0x4/0xffffffff
-A PREROUTING -m connmark --mark 0x4 -j MARK --set-xmark 0x4/0xffffffff
В таблице nat:
-A PREROUTING -d ip2 -p tcp -m tcp --dport 1194 -j DNAT --to-destination ip3
Два самых приоритетных правила в RPDB:
0:      from all lookup local 
32752:  from all fwmark 0x4 lookup isp1
И в таблице isp1 маршрут по умолчанию - через интерфейс, на котором ip2. Маршрутов до ip1, либо до подсети, содержащей в себе ip1, там нет.

И теперь я понимаю, что не знаю, как работает rp_filter в дебиановском (3.2) ядре :(

Deleted
()
Ответ на: комментарий от Deleted

И теперь я понимаю, что не знаю, как работает rp_filter в дебиановском (3.2) ядре :(

Во-во...

-A PREROUTING -d ip2 -p tcp -m tcp --dport 1194 -j DNAT --to-destination ip3

Ну вот после этого правила пакет стал примерно таким:

TRACE: nat:PREROUTING:rule:46 SRC=ip1 DST=---->ip3<---- SYN URGP=0 OPT (020405B40402080A29CC523E0000000001030307) MARK=0x4
А поскольку в правиле указано ххх.ххх.ххх.ххх — внешник, то правило:
ip rule add to xx.xx.xx.xx table isp2
Не работает, пакет дропается фильтром.

Во-первых, rp_filter работает не так, как ты описал. Пакет отбрасывается, если он пришел не на тот интерфейс, куда пойдет ответ.

Не уверен. Как я считаю, что пакет дропается, если пакет пришел с адресом назначения, который не назначен данному интерфейсу.

Вообще надо попробовать пропилить rule, если что получится — отпишу.

greek_31 ★★
() автор топика
Ответ на: комментарий от greek_31

Не уверен. Как я считаю, что пакет дропается, если пакет пришел с адресом назначения, который не назначен данному интерфейсу.

Зачем считать, если можно обратиться к документации :) . Вот что пишут в lartc:

Basically, if the reply to a packet wouldn't go out the interface this packet came in, then this is a bogus packet and should be ignored.

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

Интерфейс, куда должен пойти ответ, определяется таблицей маршрутизации, в которую пакет попал согласно правил ip rule

, но я могу в этом ошибаться.

anonymous
()
Ответ на: комментарий от Rost

виной тому route cache который не очень дружит со маркировками

Сброс кэша (ip route flush cache) мне не помогал. Даже если не использовать маркировки и вводить дополнительный внутренний ip адрес, то все равно работать не будет. Сетап такой же, как несколькими постами выше, только нет двух правил в mangle, вместо одного правила в nat - 2:

-A PREROUTING -d ext_ip1 -p tcp --dport X -j DNAT --to int_ip1
-A PREROUTING -d ext_ip2 -p tcp --dport X -j DNAT --to int_ip2
, и другие правила ip rule:
from all to int_ip2 lookup isp2
from int_ip2 lookup isp2
И дальше правил в nat пакет не проходит.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.