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

DNAT с двух внешних интерфейсов на один внутренний

 , ,


0

1

Добрый день. Имеется роутер (Centos7), два провайдера и одна внутренняя сеть. Внешние интерфейсы роутера (собрал макет рабочей системы на vm ws)

внеш ens224 172.16.30.5/29 шлюз 172.16.30.4
внеш ens256 172.16.50.5/28 шлюз 172.16.50.4
внут ens161 10.0.1.1/24
Маршрут по умолчанию default via 172.16.30.4 dev ens224. Из внутренней сетки все идет через ens224. Чтобы снаружи роутер был доступен по обоим адресам, добавил правила
ip route add default via 172.16.30.4 table 30
ip route add default via 172.16.50.4 table 50
ip rule add from 172.16.30.5 table 30
ip rule add from 172.16.50.5 table 50
Все это работает без проблем. Но сейчас понадобилось сделать форвардинг порта с внешки на сервер внутри локальной сети. Добавил правила в iptables
iptables -t nat -A PREROUTING -p TCP -d 172.16.30.5 --dport 25 -j DNAT --to-destination 10.0.1.2:25
iptables -t nat -A PREROUTING -p TCP -d 172.16.50.5 --dport 25 -j DNAT --to-destination 10.0.1.2:25
iptables -A FORWARD -j ACCEPT
По адресу 172.16.30.5:25 внутренний сервер доступен, все работает. А вот по 172.16.50.5:25 - нет. По логам видно, что в nat prerouting пакеты dest 172.16.50.5:25 приходят, но дальше дропаются, DNAT не срабатывает, в mangle forward ничего. Если сменить default route на 172.16.50.4, ситуация противоположная. Может ip rule/route для транзитных пакетов не работает? Куда еще копать?


Получается ситуация, когда на входе имеем пакет вида «МИР -> router:25». Т.к. «МИР» - это любой внешний IP, то возникает проблема с ответными пакетами: почтовый сервер возвращает ответ, и после обратного NAT-а на router-е он превращается в «router:25 -> МИР». Вот в этом месте маршрутизатор и запутывается (точнее он запутывается ещё до отправки в локальную сеть, т.к. rp_filter выполняет проверку в виде маршрутизации обратного пакета и убивает пакет). Ему нужно как-то определить через какого провайдера слать пакет наружу.

Для того, чтоб всё работало нужно маркировать «соединения» - iptables -j CONNMARK, и на основе этих маркировок выполнять маршрутизацию. Также не забыть, что этот модуль делает ctmark (маркировку, которую хранит где-то у себя), а маршрутизационный код анализирует nfmark (маркировка, хранящаяся где-то в сопроводительных данных о пакете, ядро её помнит пока пакет не покинул пределы router-а), поэтому ctmark нужно всегда восстанавливать в nfmark.

Примерно так (!!! правила ориентировочные, могут сразу не работать):

# МИР -> router

# восстановить маркировку (ctmark -> nfmark)
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
# пакет промаркирован ? да - выйти
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j RETURN
# нет - это первый пакет нового соединения, промаркировать
iptables -t mangle -A PREROUTING -i ens224 -j CONNMARK --set-xmark 0x30
iptables -t mangle -A PREROUTING -i ens256 -j CONNMARK --set-xmark 0x50
# и закинуть в nfmark
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark


# локальная сеть -> МИР

iptables -t mangle -A POSTROUTING -j CONNMARK --restore-mark
iptables -t mangle -A POSTROUTING -m mark ! --mark 0 -j RETURN
iptables -t mangle -A POSTROUTING -o ens224 -j CONNMARK --set-xmark 0x30
iptables -t mangle -A POSTROUTING -o ens256 -j CONNMARK --set-xmark 0x50
# маршрутизация уже выполнена, restore-mark делать не нужно

Маршрутизация:
ip rule add pref 10 to 10.0.1.1/24 table main
ip rule add pref 20 fwmark 0x30 table 30
ip rule add pref 30 fwmark 0x50 table 50

Не забыть выключить rp_filter:
sysctl net.ipv4.conf.ens224.rp_filter=0
sysctl net.ipv4.conf.ens256.rp_filter=0

spirit ★★★★★
()

Надеюсь общая идея ясна.
POSTROUTING-правила возможно избыточны, можно попробовать без них.
Вообще подобные вещи можно искать в google по словам multihomed routing.

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

Спасибо! В принципе, все заработало после установки

net.ipv4.conf.ens224.rp_filter=2
net.ipv4.conf.ens256.rp_filter=2
но с одним нюансом - пакеты, приходящие на ens256, уходят с ens224. Это работает на тестовом стенде, но, боюсь, в реальном мире вызовет проблемы. Буду настраивать маркировку соединений.

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

iptables -t mangle -A POSTROUTING -o ens224 -j CONNMARK --set-xmark 0x30

На построуте connmark ? Это вообще зачем простите?

ip rule add pref 10 to 10.0.1.1/24 table main
10.0.1.1/24

Потрясающе.

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

На построуте connmark ? Это вообще зачем простите?

А где вы предлагаете маркировать пакеты, идущие в мир ? Нам нужно знать через какого провайдера будет выход, т.е. output интерфейс.
Транзитный трафик пройдёт через mangle FORWARD -> POSTROUTING, локальный (от самого маршрутизатора) - через mangle OUTPUT -> POSTROUTING.
Значит имеем либо один набор правил в POSTROUTING, либо 2 набора - FORWARD + копия в OUTPUT, к чему избыточность ?
В случае автора, как я уже говорил, подобное направление можно и не обрабатывать. Тут главное помнить, что соединения могут устанавливаться в обоих направлениях, а для порядка лучше маркировать, начиная с первого пакета, а не с середины.

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

Вас не смущает в название POSTROUTING приставка POST ?
Транзитные и входящие локальные маркируются в mangle PREROUTING
Локальные исходящие в mangle OUTPUT

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

Правила POSTROUTING действительно не понадобились, все работает без них. В остальном все ок, еще раз спасибо за помощь.

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