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

ip rule на роутере с NAT

 , ,


0

1

Привет, коллеги. Почему-то не срабатывает правило ip rule, если пакет предварительно обработан NAT-маскарадингом (на этом же компьютере). Что хотелось бы получить: принимать входящие на 192.168.8.252:2023 и 192.168.8.254:2023; DNAT-ить их во внутреннюю сеть на 10.0.0.241. Фишка в том, что 192.168.8.10 и 192.168.8.12, с которых приходят входящие - это тоже роутеры, они тоже DNAT-ят снаружи. 192.168.8.10 перенаправляет на 192.168.8.254, а 192.168.8.12 - на 192.168.8.252. Ответ, естественно, должен уходить на тот же роутер, с которого пришёл запрос. Вот что написано в правилах:

# ip rule show
0:      from all lookup local
32762:  from 192.168.8.252 lookup 3
32763:  from 192.168.8.254 lookup 1
32766:  from all lookup main
32767:  from all lookup default

# ip route show table 3
default via 192.168.8.12 dev br0

# ip route show table 1
default via 192.168.8.10 dev br0

# ip route show table main
default via 192.168.8.10 dev br0  src 192.168.8.254
В IPTABLES всё просто:
*nat
-A PREROUTING -p tcp -d 192.168.8.252 --dport 2023 -j DNAT --to 10.0.0.241

-A POSTROUTING -o br0 -j MASQUERADE
И вот что получается:
# tcpdump -enni br0 port 2023
12:15:25.821772 b8:a3:86:65:a3:0f > 00:1e:8c:8b:bc:aa, ethertype IPv4 (0x0800), length 66: 178.93.15.150.62250 > 192.168.8.252.2023: Flags [S], seq 4294154921, win 64240, options [mss 1260,nop,wscale 2,nop,nop,sackOK], length 0

12:15:25.822038 00:1e:8c:8b:bc:aa > b8:a3:86:65:a2:3d, ethertype IPv4 (0x0800), length 66: 192.168.8.252.2023 > 178.93.15.150.62250: Flags [S.], seq 2354228401, ack 4294154922, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 6], length 0

# arp -a
? (192.168.8.12) at b8:a3:86:65:a3:0f [ether] on br0
? (192.168.8.10) at b8:a3:86:65:a2:3d [ether] on br0
То есть, по MAC-адресам видно, что запрос приходит с b8:a3:86:65:a3:0f (192.168.8.12), а ответ на него отсылается на b8:a3:86:65:a2:3d (192.168.8.10), несмотря на правило «from 192.168.8.252 lookup 3», в котором указан маршрут «default via 192.168.8.12». Вместо него, видимо, используется маршрут из table main, несмотря на то, что там явно указано «src 192.168.8.254», что не совпадает с содержимым пакетов.

Интересно, что такого не проиходит с локальными портами, т.е. открытыми непосредственно на роутере, а не транслируемыми через DNAT внутрь сети. Там ответ чётко уходит на нужный роутер в зависимости от адреса, на который пришёл запрос.

Вопрос: чего я не понимаю в этой кухне? Я знаю ещё один способ - маркировать пакеты в iptables и правила писать в зависимости от метки fwmark, но описанный здесь способ мне кажется красивее и правильнее, хотелось бы довести его до конца.

Оглядел в целом, что я написал, и сам увидел где проблема: iptables POSTROUTING выполняется после ip rule и ip route! Соответственно, на момент проверок правил ip rule пакет ещё имеет исходный адрес из 10.X.X.X, и под правило from 192.168.8.242, соответственно, не попадает.

Вопрос тогда следующий: а как это сделать правильно? Я ведь даже правило в iptables не могу написать, т.к. исходящий адрес присваивается только на этапе MASQUERADE, а до этого я даже не знаю с каким адресом должен уйти ответ. Магия какая-то. Наверное, это знает CONNTRACK - больше некому.

Можно ли MASQUERADE указать в PREROUTING, а не в POSTROUTING? Чем это грозит?

shamus24
() автор топика

До конца понимать одновременное использование ip ru & iptables & nf_bridge очень не просто.

т.к. ты натишь два адреса в 10.0.0.241 IMHO единственный способ отправить их назад тем же путем, это маркировать conntrack через CONNMARK при создании соединения, дальше маркировать пакеты через --restore-mark и в ip ru использовать fwmark. Тем более, что это нужно только в случае DNAT, а не для любого пакета с адресам 192.168.8.252,192.168.8.254

192.168.8.254 у тебя локальный, а 192.168.8.252 просто роутиться к тебе или это второй адрес на бридже ?

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

NAT срабатывает 1 раз для conntrack.

Если сработал DNAT, то ответные пакеты уже не попадут в MASQUERADE.

Можно ли MASQUERADE указать в PREROUTING, а не в POSTROUTING? Чем это грозит?

нет. На target есть ограничение: в каких таблицах и каких цепочках его можно использовать. SNAT & MASQUERADE только в POSTROUTING.

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

До конца понимать одновременное использование ip ru & iptables & nf_bridge очень не просто.

Я уже понял. Накатываю кластер виртуалок для тестирования. С роутерами, натами и прочим блэкджеком. За советы спасибо, буду всё пробовать.

192.168.8.254 у тебя локальный, а 192.168.8.252 просто роутиться к тебе или это второй адрес на бридже ?

Второй адрес. Изначально предполагалось, что у роутера будут просто два внешних интерфейса (на каждый канал), но потом ситуация усложнилась, и вместо двух интерфейсов появились ещё два отдельных роутера, а на этом интерфейс остался один, теперь уже не внутренний, а как-бы промежуточный, к которому я и прицепил два адреса. Сути не меняет, по-моему.

Если сработал DNAT, то ответные пакеты уже не попадут в MASQUERADE.

Попадают. По крайней мере, адрес исправно подменяется, причём подменяется правильно, подставляется именно тот, на который пришло исходное соединение. Я понимаю, что MASQUERADE не совсем для этого, но работает. Говорю же - магия.

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

Если сработал DNAT, то ответные пакеты уже не попадут в MASQUERADE.

Попадают. По крайней мере, адрес исправно подменяется, причём подменяется правильно, подставляется именно тот, на который пришло исходное соединение. Я понимаю, что MASQUERADE не совсем для этого, но работает. Говорю же - магия.

А ты посмотри на счетчики правил в таблице nat

В отличии от «ip ru» iptables имеет замечательное средство диагностики "-j TRACE". Пользоваться им нужно аккуратно, ибо в логи пишет много.

Если оно ничего не выводит в лог, то нужно добавить и тут же удалить правило с "-j LOG".

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

IMHO единственный способ отправить их назад тем же путем, это маркировать conntrack через CONNMARK при создании соединения, дальше маркировать пакеты через --restore-mark и в ip ru использовать fwmark.

В сухом остатке получилось следующее:

*mangle
-A PREROUTING -s 10.0.0.0/24 -m connmark ! --mark 0 -j CONNMARK --restore-mark
-A PREROUTING -d 192.168.8.254/32 -m state --state NEW -j CONNMARK --set-mark 1
-A PREROUTING -d 192.168.8.252/32 -m state --state NEW -j CONNMARK --set-mark 3
и в ip rule добавилось, соответственно
fwmark 0x3 lookup 3
fwmark 0x1 lookup 1
Но пришёл я к этому не быстро. Документация просто изобилует туманными полунамёками, так, что очень долго пришлось изучать связь между MARK, CONNMARK и ip-rule fwmark. Я распишу подробнее на случай, если кто-то так же будет искать. Итак, метки IPTABLES могут быть двух типов: метка пакета MARK и метка соединения CONNMARK. Считается, что метка пакета живёт только до тех пор, пока пакет не придёт на место назначения или не уйдёт за пределы системы, а метка соединения, если была установлена, то присутствует во всех пакетах, обслуживающих это соединение. Они не связаны, т.е. установка метки одного типа не устанавливает метку другого типа. Метка пакета устанавливается через -j MARK --set-mark, а метка соединения - через -j CONNMARK --set-mark. Кроме того, можно скопировать метку пакета в метку соединения через -j CONNMARK --save-mark и обратно через -j CONNMARK --restore-mark. Правила IP RULE FWMARK «видят» только метку пакета, но не метку соединения. Хотите обрабатывать задавать метки в ip rule - делайте --restore-mark. В моём случае это получилось использовать во благо. Дело в том, что в моей конфигурации пакеты, приходящие на 192.168.8.X, должны получать метку (поскольку это единственный момент, когда можно определить какую именно метку ставить), но не должны попадать под правила ip rule, т.к. в дополнительных таблицах маршрутизации отсутствуют записи для сети 10.0.0.X, и пакеты пропадают в никуда. Пакет должен просто без всяких правил пройти по главной таблице маршрутизации. Это очень элегантно решается выставлением метки соединения, которая игнорируется ip rule. А уже в ответах эта метка копируется в метку пакета, и он отправляется по правилам.

У меня просьба посмотреть - упускается ли из виду что-то в приведенной конфигурации, или всё нормально? Работать-то оно работает, но, может быть, там какая-то дополнительная проверка не помешает, например?

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

Логика «ip ru» очень хитрая из-за чего очень много вопросов и граблей.

Есть замечательная картинка про экзамен, но к документации оно тоже относится. Когда ты первый раз читаешь документацию и когда в ней разобрался :)

Если верить схеме, то «ip ru» должно отрабатываться в «routing decision» в 2-х местах, но у меня почему-то сложилось стойкое убеждение, что для входящих пакетов оно срабатывает до iptables/nat.

Кстати, в новых ядрах появился nat/input

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

Метка пакета устанавливается через -j MARK --set-mark, а метка соединения - через -j CONNMARK --set-mark. Кроме того, можно скопировать метку пакета в метку соединения через -j CONNMARK --save-mark и обратно через -j CONNMARK --restore-mark.

В дополнение к этому, так для сведения, еще можно проверять какая метка установлена

-m connmark --mark N
-m mark --mark N
иногда бывает полезно, например при определенном connmark выставить другой mark.

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