Книга про Port-forwarding. Специально для opennet.ru и благодаря пользователю Phantom.На форуме часто задается вопрос по поводу маршрутизации сети, подключенной к двум провайдерам.
На этот вопрос уже есть масса ответов, чтобы их найти достаточно воспользоваться поиском.
В частном случае проблема расширяется тем, что нужно осуществлять проброс соединений к сервисам, расположенным в локальной сети.
В обычной ситуации это делается с помощью DNAT, а в случае нескольких провайдеров снова возникает проблема - ответ отправляется в соответствии с таблицей маршрутизации, а не в зависимости от того, по какому каналу пришел запрос.
Проблема усугубляется тем, что обратное преобразование адресов выполняется уже после принятия решения о маршрутизации,
т.е. примерно в районе цепочки POSTROUTING, но скрытно от пользователя.
Решить эту нерешаемую проблему поможет модуль CONNMARK, который позволяет маркировать каждое проходящее через маршрутизатор соединение, и маршрутизация ответных пакетов в зависимости от значения маркера.
Принцип работы маршрутизатора для решения описанной задачи будет выглядеть примерно так:
Входящие соединения маркируются определенным флажком, после чего делается их проброс в нужное назначение.
Каждый обратный(ответный) пакет соединения _до принятия решения о маршрутизации_ маркируется флажком соответствующего ему соединения (флажок восстанавливается).
На основании флажков принимается решение о маршрутизации пакета в соответствующую сеть и,таким образом,"обратный DNAT" будет происходить когда пакет уже будет идти по нужному маршруту.
В нижеописанном примере обеспечение доступности сервиса по двум каналам/провайдерам делалось для локального сервиса маршрутизатора. Также описаны отличия конфигурации для проброса сервиса в DMZ.
Изначально сервис был доступен через канал первого провайдера first на адресе first_ip. Возникла задача обеспечить его доступность по каналу второго провайдера.
Поскольку сервис расположен на реальном айпи, то для входящих соединений с порта первого провайдера DNAT применяться не будет.
Входящие пакеты/соединения с порта второго провайдера (destination <second_ip>) будут помечены маркером и к ним будет применен DNAT.
Пакеты с порта первого провайдера мы маркировать не будем, поскольку провайдеров всего два и первый является шлюзом по умолчанию для сервиса.
(Фактически эти соединения промаркированы флажком 0x00)
[root@test z]# iptables -t nat -nvL PREROUTING
Chain PREROUTING (policy ACCEPT 144M packets, 9659M bytes)
pkts bytes target prot opt in out source destination
1 52 CONNMARK tcp -- * * 0.0.0.0/0 <second_ip> tcp dpt:<port> CONNMARK set 0x1
1 52 DNAT tcp -- * * 0.0.0.0/0 <second_ip> tcp dpt:<port> to:<first_ip>:<port>
Изначально все ответные пакеты от сервиса шли через канал первого провайдера.
Чтобы ответные пакеты уходили через нужный канал, нужно восстановить флажок соединения.
В связи с тем, что сервис локальный, маркировка исходящих пакетов делается в цепочке OUTPUT таблицы mangle.
Для проброса порта к серверу в локальной сети(в DMZ) восстановление маркера надо делать в цепочке PREROUTING таблицы mangle.
[root@test z]# iptables -t mangle -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 6745M packets, 7048G bytes)
pkts bytes target prot opt in out source destination
65915 8600K CONNMARK tcp -- * * <first_ip> 0.0.0.0/0 tcp spt:<port> CONNMARK restore
Далее система принимает решение о маршрутизации пакета.
Все не маркированные пакеты будут идти по маршруту по умолчанию. В моем случае это первый провайдер first и IP интерфейса first_ip.
Все исходящие (обратные) пакеты будут промаркированы значением маркера соединения в цепочке OUTPUT таблицы mangle.
[root@test z]# ip ru sh
0: from all lookup local
1000: from all lookup main
3300: from all fwmark 0x1 lookup <second>
5000: from <first_ip> lookup <first>
5500: from <second_ip> lookup <second>
10000: from all lookup default
32766: from all lookup main
32767: from all lookup default
Более корректным вариантом реализации, не зависящим от значения шлюза по умолчанию, является обязательная маркировка пакетов для соединений
от каждого провадера отдельными флажками и создание соответствующих правил маршрутизации.
(с) Pavel V. Rochnyack