На форуме часто задается вопрос, по поводу маршрутизации сети, подключенной к двум провайдерам.
В частном случае проблема расширяется тем, что нужно осуществлять проброс соединений к сервисам,
расположенным в локальной сети. Это делается с помощью DNAT, и при этом снова возникает
проблема - по каналу какого провайдера отправлять ответ. Проблема усугубляется тем,
что обратное преобразование адресов выполняется уже после принятия
решения о маршрутизации,
т.е. примерно в районе цепочки POSTROUTING, но скрытно от пользователя.Решить эту нерешаемую проблему поможет модуль CONNMARK. Принцип работы маршрутизатора для
решения описанной задачи будет выглядеть примерно так:Входящие соединения маркируются определенным флажком, после чего делается их проброс в нужное назначение.
Каждый обратный пакет соединения _до принятия решения о маршрутизации_ маркируется
флажком соответствующего ему соединения (флажок восстанавливается).
На основании флажков принимается решение о маршрутизации пакета в соответствующую сеть.
В нижеописанном примере обеспечение доступности сервиса по двум каналам/провайдерам
делалось для локального сервиса маршрутизатора. В связи с этим маркировка исходящих
пакетов делается в цепочке OUTPUT таблицы mangle. Для проброса порта к серверу в локальной сети
(в DMZ) проверку и восстановление маркера надо делать в цепочке PREROUTING.
Таким образом, "обратный DNAT" будет происходить когда пакет уже будет идти по нужному маршруту.Все не маркированные пакеты будут идти по маршруту по умолчанию. В моем случае это первый
провайдер first и айпи интерфейса first_ip. Входящие пакеты/соединения с порта второго провайдера
(destination <second_ip>) будут помечены маркером и к ним будет применен DNAT.
Все исходящие (обратные) пакеты будут промаркированы значением маркера соединения
в цепочке OUTPUT таблицы mangle.Более корректным вариантом, не зависящим от значения шлюза по умолчанию,
является обязательная маркировка пакетов для соединений от любого провадера и
создание соответствующих правил маршрутизации.
[root@test z]# iptables -t nat -nvL PREROUTINGChain 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>
[root@test z]# iptables -t mangle -nvL OUTPUTChain 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
[root@test z]# ip ru sh0: 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
URL:
Обсуждается: http://www.opennet.me/tips/info/1651.shtml
плавали, проблема интересная.
но есть более правильный способ.
если есть желание, пиши на мыло, пообщаемся.
Можете прямо тут описать интересное решение, с интересом же почитаю Ваш вариант.
Мыло в подписи под статьей,если сильно хочется. Но в принципе, можно и в комменты описание задвинуть, если оно уже вылизано и не требует обсуждения. В общем - интересно, рассказывай.
PS: я уже и забыл когда отправлял текстовочку-то....
Ок, вечерком постараюсь отписать.
Есть рабочее решение, описание еще предстоит накидать.
В кратце - идея в том, что на каждый канал провайдера создается своя подсеть DMZ (в идеале - vlan, но это не обязательно). Соответственно на обратном пути по подсети источника можно опознать пакет (с какого из внешних каналов он пришел) и применить к нему соответствующую таблицу роутинга.
>Ок, вечерком постараюсь отписать.
>Есть рабочее решение, описание еще предстоит накидать.
>В кратце - идея в том, что на каждый канал провайдера создается
>своя подсеть DMZ (в идеале - vlan, но это не обязательно).
>Соответственно на обратном пути по подсети источника можно опознать пакет (с
>какого из внешних каналов он пришел) и применить к нему соответствующую
>таблицу роутинга.Понятно, в общем-то известное решение - позволяет обходиться без маркировки пакетов...
Можно через xinetdнапример:
service rdp
{
disable = no
port = 3389
socket_type = stream
protocol = tcp
user = root
redirect = 192.168.2.8 3389
type = UNLISTED
wait = no
}ну и разрешающее правило iptables
iptables -A INPUT -p tcp --dport 3389 -m state --state NEW -m recent --name CITRIX --set
iptables -A INPUT -p tcp --dport 3389 -m state --state NEW -m recent --name CITRIX --update --seconds 60 --hitcount 5 -j LOG
iptables -A INPUT -p tcp --dport 3389 -m state --state NEW -m recent --name CITRIX --update --seconds 60 --hitcount 5 -j DROP
iptables -A INPUT -p tcp --dport 3389 -m state --state NEW -j ACCEPT
При условии, что маршрутизация настроена вот так http://gazette.linux.ru.net/rus/articles/lartc/x348.htmlТак и не получилось у меня мапнуть порт через маркировку пакетов через DNAT, чет видимо не до понимаю чутка, если можно выложить конкретный пример с правилами iptables как пробросить порт в локалку и чтоб он был доступен на 2-x интерфейсах буду признателен.
>[оверквотинг удален]
>iptables -A INPUT -p tcp --dport 3389 -m state --state NEW -j
>ACCEPT
>
>
>При условии, что маршрутизация настроена вот так http://gazette.linux.ru.net/rus/articles/lartc/x348.html
>
>Так и не получилось у меня мапнуть порт через маркировку пакетов через
>DNAT, чет видимо не до понимаю чутка, если можно выложить конкретный
>пример с правилами iptables как пробросить порт в локалку и чтоб
>он был доступен на 2-x интерфейсах буду признателен.То что описано в "статье" - это и есть реальные примеры. Не забудьте добавить разрешающие правила в FORWARD и всё, всё остальное есть в статье.
Есть один неприятный момент в решениях предложенных автором и dry. Если у меня есть сервис на который должны попадать люди из-вне значит я должен прописать на 2 ip от разных провайдеров одно имя, нет ну конечно я могу и разные имена прописать, но для пользаков это не удобно ИМХО. Так вот если при этом один пров падает то половина народа попасть ко мне не смогут :-(. В общем как мне кажется нет тут нормальных решений кроме как AS получать :-(. А конторым типа моей, которой не более 10 ИП белых надо это не очень по карману :-(.
>Есть один неприятный момент в решениях предложенных автором и dry. Если у
>меня есть сервис на который должны попадать люди из-вне значит я
>должен прописать на 2 ip от разных провайдеров одно имя, нет
>ну конечно я могу и разные имена прописать, но для пользаков
>это не удобно ИМХО. Так вот если при этом один пров
>падает то половина народа попасть ко мне не смогут :-(. В
>общем как мне кажется нет тут нормальных решений кроме как AS
>получать :-(. А конторым типа моей, которой не более 10 ИП
>белых надо это не очень по карману :-(.Это вообще не относится к обсуждаемой теме. Обсуждаемая тема называется _маршрутизация_, и решение может иметь кучу применений. Так например тот же самый openvpn, smtp умеют балансироваться на два адреса штатно, и "никаких неприятных моментов".
Статья в точности описывает мою проблему, да вот только пример непонятный и неполный.
В нем смешался доступ к локальному сервису и проброс DNAT, получился неслыханный бред.
Пакет, приходящий со второго инета, почему то пробрасывается на первый инет, причем вовнутрь ! Ладно, фиг с ним, далее еще лучше, метка восстанавливается в цепочке OUTPUT ! Как "оно" там окажется ??? Значит это относится к локальному сервису ? А где тогда восстанавливается метка для пробрасываемого порта ?
Еще интересна цепочка маршрутизации, таблица main присутствует в ней дважды. Разъясните, пожалуйста, сей хитрый трюк и зачем он ? :)
[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Там еще два раза default присутствует :)
В общем случае, достаточно конечно же такого варианта:[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>
32767: from all lookup defaultНо таблица правил по умолчанию выглядит так:
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
и я удалять из неё правило 32766 не рискнул.-----------
Правило "1000: from all lookup main" требуется чтобы напрямую присоединенные к маршрутизатору подсети маршрутизировались через локальные линки, а не через проход через провайдерские шлюзы. Более подробно можно почитать тут: http://www.opennet.me/tips/info/2009.shtml
mangle/OUTPUT нужна для отработки пакетов роутер-инет, для ДНАТов все танцы чисто в цепочке mangle/PREROUTING:
1. -i ifINET1 -m state --state NEW -j CONNMARK --set-mark 0x1
-i ifINET2 -m state --state NEW -j CONNMARK --set-mark -0x2
2. после этих правил надо делать -j CONNMARK --restore-mark, НО! при условии что пакет из локалки в инет! я для этого заводил отдельную цепочку в mangle, в которую заворачивал все пакеты из локалок, а в самой цепочке поставил три правила:
-d 10.0.0.0/8 -j RETURN
-d 192.168.0.0/16 -j RETURN
-j CONNMARK --restore-mark
А как во фрибсд это сделать?
"Для проброса порта к серверу в локальной сети
(в DMZ) проверку и восстановление маркера надо делать в цепочке PREROUTING.
Таким образом, "обратный DNAT" будет происходить когда пакет уже будет идти по нужному маршруту."А разве не в POSTROUTING?