LINUX.ORG.RU
ФорумAdmin

Linux Advanced Routing: несколько аплинков (PBR) + port forwarding

 , ,


0

1

ЛОР, побудь моим личным LARTC :)

Есть линуксовый роутер (ядро 4.14), который обслуживает одну локальную сеть с двумя аплинками от разных провайдеров. Маршруты от провайдеров распиханы по разным таблицам. Таблицы маршрутов и правил выглядят так:

# ip rule
0:      from all lookup local 
10000:  from 192.168.255.2 lookup rtk 
10000:  from 95.84.198.125 lookup onl 
20000:  from all to 192.168.255.2/24 lookup rtk 
20000:  from all to 95.84.198.125/23 lookup onl 
32766:  from all lookup main 
32767:  from all lookup default 
39999:  from 10.196.254.2 lookup onl 
40001:  from all lookup rtk
90007:  from all iif lo lookup onl 
90008:  from all iif lo lookup rtk

# ip route show table onl
default via 95.84.198.1 dev eth0.2  src 95.84.198.125  metric 100 
95.84.198.0/23 dev eth0.2 scope link  metric 100 

# ip route show table rtk
default via 192.168.255.1 dev eth0.3  metric 110 
192.168.255.0/24 dev eth0.3 scope link  metric 110 

# ip route show table main
10.0.0.0/8 via 10.196.254.2 dev br-lan  metric 200 # OpenVPN-сервер
10.196.254.0/24 dev br-lan scope link  src 10.196.254.1 

Правила 39999-40001 добавлены вручную и задают «дефолтный» аплинк. Остальные сгенерированы OpenWRT. 192.168.255.1 — это своеобразный DMZ (мерзкий двойной NAT, потому что GPON); на самом деле там статический IPv4 128.0.130.85.

В такой конфигурации есть доступ в Интернет из локальной сети, также роутер корректно принимает соединения из Интернета на любом интерфейсе. Но port forwarding не работает: 10.196.254.2 отвечает только на соединения, перенаправленные с 95.84.198.125 (таблица onl), а все остальные хосты — только на соединения с 128.0.130.85. Я подозреваю, что ответные пакеты уходят в дефолтный аплинк для данного хоста, а не в тот, с чьего адреса пришёл запрос.

Вопрос: как это исправить? Без хаков с fwmark.

★★★★★

А для rtk src в dgw специально не задан ?

а портфорвардинг на 192.168.255.2 точно работает ?

Может попробовать dual-nat ?

на первом канале

-t nat PREROUTING -d 95.84.198.125 -p tcp --dport X1 -j DNAT --to-destination 10.196.254.2:X1
-t nat POSTROUTING -d 10.196.254.2 -j SNAT --to-source 95.84.198.125
на втором
-t nat PREROUTING -d 192.168.255.2 -p tcp --dport X1 -j DNAT --to-destination 10.196.254.2:X1
-t nat POSTROUTING -d 10.196.254.2 -j SNAT --to-source 192.168.255.2

Но тогда 10.196.254.2 не узнает реальный внешний адрес (если вообще оно будет работать).

IMHO CONNMARK как раз нормальное решение, а не хак.

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

А для rtk src в dgw специально не задан ?

Так сгенерировал OpenWRT.

Меня это тоже напрягло, но ведь если preferred-src нет, то используется первый адрес на интерфейсе, с которого уходит пакет. Он там правильный, 192.168.255.2. Я попытался придумать пример, когда это не будет работать, но ничего не придумал. Можешь привести такой пример?

а портфорвардинг на 192.168.255.2 точно работает ?

Да, в каком-то смысле работает (так, как я описал выше).

Может попробовать dual-nat ?
...
Но тогда 10.196.254.2 не узнает реальный внешний адрес (если вообще оно будет работать).

Это должно работать, но да, тоже криво.

Просто вот в чём дело: когда роутер делает DNAT, он запоминает настоящий адрес назначения (т. е. свой адрес со стороны WAN) где-то в conntrack. Когда на роутер приходит ответ, он должен сделать ему «комплементарный» SNAT (заменить адрес отправителя со стороны локалки на свой адрес из WAN). В какой момент это происходит? До routing decision или после?

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

До routing decision или после?

А вам «POSTROUTING» ни о чём не намекает? Вначале произойдёт рутинг, с src «серым адресом», то есть зачастую там будет по дефолту, потом уже snat.

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

IMHO CONNMARK как раз нормальное решение, а не хак.

Почему я называю fwmark хаком: роутер уже располагает достаточной информацией (исходный адрес назначения в таблице conntrack) для того, чтобы принять правильное решение, но почему-то ей не пользуется. fwmark будет дублировать эту информацию.

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

Я не совсем понимаю, как это работает.

Когда я явно делаю маскарад или SNAT, он происходит в POSTROUTING, это понятно. А когда на роутер приходит ответ на заDNAT-енный пакет, он ему делает обратный SNAT автомагически или это на самом деле всё тот же маскарад, который явно прописан?

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

Я не совсем понимаю, как это работает.

У вас есть возможность включить анализатор пакетов.

он ему делает обратный SNAT автомагически

Да, потому если второй канал допускает асимметричный рутинг, то есть разрешает прохождение пакетов с src другого провайдера, то пакеты таки будут ходить. SNAT же сработает, и поменяет src на белый.

или это на самом деле всё тот же маскарад, который явно прописан?

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

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

У вас есть возможность включить анализатор пакетов

Да я тут с прошлого вечера сижу с tcpdump'ом. Только tcpdump не показывает, что творится внутри ядра.

Да, потому если второй канал допускает асимметричный рутинг, то есть разрешает прохождение пакетов с src другого провайдера, то пакеты таки будут ходить. SNAT же сработает, и поменяет src на белый.

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

Так да или нет? :) Или они оба в POSTROUTING происходят?

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

SNAT же сработает, и поменяет src на белый

, вспомнив, какой он был. У dnat автомат snat, а не маскарад к исходящему интерфейсу.

Ну вот я об этом и говорю. Если он такой умный, почему он происходит после routing decision?

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

Вообще моя исходная задача — поменять провайдера, но без даунтайма для сервера, который крутится в локалке за NAT'ом. План в том, чтобы настроить port forwarding для обоих провайдеров, потом поменять DNS, подождать сутки и потушить старый аплинк.

Но хотелось бы сделать обобщённо, чтобы потом заслать это в OpenWRT и избавить будущих недоадминов от этого головняка :)

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

Так да или нет? :) Или они оба в POSTROUTING происходят?

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

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

Если он такой умный, почему он происходит после routing decision?

Чтобы не делать бесконечный цикл и руками рисовать какие-то дополнительные правила «тут играть, тут не играть, тут рыбу заворачивали» проще всего было сделать так: nat/contract отвязан от рутинга, следовательно правильнее dnat до него, а snat - после. И они же у вас срабатывают. Только вам не нравится, что автомат snat не желает поменять исходящий интерфейс.

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

Да, теперь понятно: автоматический SNAT на исходный адрес делается для того, чтобы соблюсти семантику соединения со стороны клиента (чтобы ответ всегда приходил с того же адреса, на который ушёл запрос), но он тоже делается в POSTROUTING, чтобы поддержать асимметричный роутинг и отвязать политику от механизма.

Сейчас я всё правильно понимаю?

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

Сейчас я всё правильно понимаю?

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

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

Не будет работать :( Что-то меня вчера совсем переклинило.

Я бы попробовал прописать на роутете статиком arp от 10.196.254.2 для 10.196.254.3, а на 10.196.254.2 сделал редирект с 10.196.254.3 на 10.196.254.2 (в nat/INPUT)

DNAT с разных каналов на разные адреса работает без проблем.

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

Не будет работать :(

Да? Почему?

Я бы попробовал прописать на роутете статиком arp от 10.196.254.2 для 10.196.254.3, а на 10.196.254.2 сделал редирект с 10.196.254.3 на 10.196.254.2 (в nat/INPUT)

Уж лучше с fwmark. :)

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

vel, vodz

Что вы скажете насчёт такого:

iptables -t mangle -A PREROUTING -m conntrack --ctstate DNAT --ctorigdst 95.84.198.125/32 --ctdir REPLY -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -m conntrack --ctstate DNAT --ctorigdst 192.168.255.2/32 --ctdir REPLY -j MARK --set-mark 2

ip rule add pref 30000 from all fwmark 1 table onl
ip rule add pref 30000 from all fwmark 2 table rtk

Это годится в качестве общего решения? Не годится — ломается hairpin NAT. Есть идеи?

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

Мосты ещё зачем-то.

Это объясняется в первой статье цикла: чтобы пакеты фильтровались централизованно как на прозрачном брандмауэре для белой подсети, но и одновременно он должен быть непрозрачным для сервисов, например для сервера vpn.

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

Маркировать эти соединения по первому пакету (state NEW) для входящех с eth0 пакетов, а для ответных пакетов делать метку равную метки соединения.

mky ★★★★★ ()