среда, 25 марта 2009 г.

Используем 2+ провайдера с применением модуля CONNMARK

Еще один способ использования нескольких каналов в интернет, теперь с использованием модуля CONNMARK. Когда я с ним начинал знакомится все выглядело довольно просто, но в процессе настройки я столкнулся со множеством подводных камней.
Допустим мы имеем следующие правила маршрутизации:
#!/bin/bash

IF1=eth1
IF2=eth2
IP1=xx.xx.xx.xx
IP2=xx.xx.xx.xx
P1=xx.xx.xx.xx
P2=xx.xx.xx.xx
P1_NET=xx.xx.xx.xx/24
P2_NET=xx.xx.xx.xx/24
PC=xx.xx.xx.xx

ip route add $P1_NET dev $IF1 src $IP1 table T1
ip route add default via $P1 table T1
ip route add $P2_NET dev $IF2 src $IP2 table T2
ip route add default via $P2 table T2

ip route add $P1_NET dev $IF1 src $IP1
ip route add $P2_NET dev $IF2 src $IP2

ip route add default via $P1 metric 10

ip rule add from $IP1 table T1
ip rule add from $IP2 table T2

ip rule add fwmark 2 table T2

Здесь IF - интерфейсы нашего роутера, смотрящие к провайдерам, IP - внешние айпишники, P - шлюзы, P_NET - провайдерские подсети, PC - ПК во внутренней сети.
Допустим на PC у нас работает SMTP сервер, и необходимо чтобы он обрабатывал соединения поступающие на любой из внешних адресов. Для этого понадобятся правила DNAT:
$IPTABLES -t nat -A PREROUTING -i $GLOBAL_ETH_PRIM -d $GLOBAL_IP_PRIM -p tcp --dport 25 -j DNAT --to-destination $PC
$IPTABLES -t nat -A PREROUTING -i $GLOBAL_ETH_SEC -d $GLOBAL_IP_SEC -p tcp --dport 25 -j DNAT --to-destination $PC

И следующий набор правил:
$IPTABLES -t mangle -A PREROUTING -i $LOCAL_ETH -m state --state ESTABLISHED -j CONNMARK --restore-mark
$IPTABLES -t mangle -A FORWARD -i $GLOBAL_ETH_PRIM -m state --state NEW -j CT
$IPTABLES -t mangle -A FORWARD -i $GLOBAL_ETH_SEC -m state --state NEW -j CT

В первой строке мы восстанавливаем маркер, установленный модулем CONNMARK, причем необходимо явно указать, что применяется это к пакетам идущим из внутренней подсети, либо добавить в таблицы маршрутизации пути к локальной подсети, иначе некорректно будут отрабатыватся правила DNAT. Все новые пакеты отправляются на маркировку в пользовательскую цепочку CT вот она:
$IPTABLES -t mangle -N CT

$IPTABLES -t mangle -A CT -i $GLOBAL_ETH_PRIM -p tcp --dport 25 -j CONNMARK --set-mark 1
$IPTABLES -t mangle -A CT -i $GLOBAL_ETH_SEC -p tcp --dport 25 -j CONNMARK --set-mark 2

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

6 комментариев:

Victor комментирует...

Вы не уточнили два важных параметра sysctl, без которых не будет работать такая схема. И если с первым очевидно (net.ipv4.ip_forward = 1), то про второй знают не все. Обязательно нужно выставить net.ipv4.conf.all.rp_filter = 0. В некоторых ядрах Reverse Path Filter включён по умолчанию. Это означает, что ядро отбросит пакет, если увидит, что он пришёл не с того интерфейса, куда смотрит маршрут к источнику пакета.

Дмитрий Алтухов комментирует...

Огромное спасибо за статью. Именно то, что искал.

У нас не SMTP, а FTP-сервер на одной из станции внутри сети.

Теперь всё работает с любого внешнего ИП (провайдера).

Андрей комментирует...

А будет ли так работать, если надо пробросить диапазон портов ? Например udp 10000:20000 ?

Unknown комментирует...

Огромное спасибо за статью!!
С еепомощью я лучше понял область и получилось заимплементить похожее решение.

Unknown комментирует...

поставленный функционал решается простыми правилами и без использования коннмарка
ip route add $P1_NET dev $IF1 src $IP1
ip route add $P2_NET dev $IF2 src $IP2
ip route add default via $P1

ip route add default via $P1 table T1
ip route add default via $P2 table T2


ip rule add from $IP1 table T1
ip rule add from $IP2 table T2

, коннмарк предпочтительно использовать при более сложной маршрутизации

Unknown комментирует...
Этот комментарий был удален автором.