MyTetra Share
Делитесь знаниями!
Используем 2+ провайдера
Время создания: 22.03.2009 23:02
Автор: Роман AKA Hexbot
Текстовые метки: сеть, два провайдера
Раздел: Компьютер - Linux - Сеть в Linux
Запись: xintrea/mytetra_syncro/master/base/0000000845/text.html на raw.github.com

Здесь я хочу рассказать о настройке шлюза на Linux'e, для использования 2-х (и более) провайдеров интернета.

Для настройки мы будем использовать возможности iptables и утилиты ip из пакета, который как правило называется iproute2. А для решения поставленной задачи пакеты мы будем маршрутизировать на основе «policy routing» (т.е. маршрутизация на основе политик), а не «destination routing» (маршрутизация на основе адреса получателя).

Итак, приступим. Для начала определимся с переменными:

#!/bin/bash

IF1=eth1

IF2=eth2

IF — это сетевые интерфейсы, которые смотрят в интернет, через наших провайдеров

IP1=10.10.10.10

IP2=20.20.20.20

IP — это наши внешние IP-адреса, которые нам выдали провайдеры

P1=10.10.10.1

P2=20.20.20.1

P — это шлюзы по умолчанию у наших провайдеров

Policy routing позволяет выполнять маршрутизацию на основе адреса источника поэтому перечислим сервера которые будут учавствовать:

SRV11=192.168.0.11

SRV12=192.168.0.12

Здесь SRV11 и SRV12 — это два айпишника одного и тогоже сервера (это важно!), это позволяет одному серверу обрабатывать входящие соединения с двух провайдеров. Конечно же, существуют и другие варианты реализовать эту возможность, но я буду использовать именно айпишники, мне кажется для начала так будет проше.

Ну а теперь самое интересное — пишем правило для маршрутизации. Первое что мы должны сделать это добавить свои таблицы маршрутизации, для этого необходимо отредактировать файл /etc/iproute2/rt_tables, например так:

#echo «101 T1» >> /etc/iproute2/rt_tables

#echo «102 T2» >> /etc/iproute2/rt_tables

Заполняем первую таблицу:

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

Затем разберемся с основной таблицей, которая называется «main». Ее мы видим, когда набираем ip route:

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

Первые две строчки аналогичны предыдущим записям, только опущено «table main». В третьей строчке задается маршрут по умолчанию с указанием метрики.

На этом с маршрутизацией разобрались, чтобы посмотреть что у нас находится в таблице маршрутизации можно выполнить команду «ip route show table <имя таблицы>». Теперь приступим к правилам. Как раз по правилам и будет приниматься решения какой пакет по какой таблице будет маршрутизироваться.

ip rule add from $IP1 table T1

ip rule add from $IP2 table T2

Здесь мы указали, что если адрес источника равен первому внешнему адресу, тогда маршрутизация выполняется по таблице T1. Аналогично вторая запись. И наконец самое интересное:

ip rule add from $SRV11 fwmark 10 table T1

ip rule add from $SRV12 fwmark 20 table T2

Используя iptables мы можем маркировать интересующие нас пакеты и маршрутизировать их на основе этих меток. Собственно здесь мы добавили два правила: для пакетов, имеющих метку 10, использовать таблицу T1, для пакетов с меткой 20 — T2. Сейчас возможно не очень понятно для чего это может потребоваться, но из правил iptables все станет ясно. Для просмотра правил выполняем «ip rule», при маршрутизации они проверяются по порядку.

Ну вот, половина работы сделана осталось написать правила для iptables. Сейчас мы настроим сеть состоящую из шлюза и сервера. На шлюзе будет работать SSH и DNS, а сервер у нас будет виндовый на нем у нас RDP и SMTP. Сеть будет настроена таким образом, что через любой из внешних айпишников мы сможем подключаться к любому из серверов, а SMTP сервер будет выходить наружу через основного провайдера.

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

#!/bin/bash

export GLOBAL_ETH_PRIM=eth1

export GLOBAL_ETH_SEC=eth2

export GLOBAL_IP_PRIM=10.10.10.10

export GLOBAL_IP_SEC=20.20.20.20

export MARK_PRIM=10

export MARK_SEC=20

Назовем этот файл ipt_p1.conf. А содержит он данные о том, какой из интерфейсов является главным, а какой запасным (PRIM и SEC соответственно) и значения для маркировки пакетов.

Перейдем к основному файлу конфигурации iptables, назовем его ipt.conf. Запишем переменные ;-)

#!/bin/bash

IPTABLES=/sbin/iptables

MODPROBE=/sbin/modprobe

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

LOCAL_ETH=eth0

GLOBAL_ETH_P1=eth1

GLOBAL_ETH_P2=eth2

LOCAL_IP=192.168.0.1

LOCAL_NET=192.168.0.0/24

GLOBAL_IP_P1=10.10.10.10

GLOBAL_IP_P2=20.20.20.20

Тут мы описали конфигурацию нашей сети, по порядку: локальный интерфейс, интерфейсы, которые смотрят к провайдерам, локальный айпишник и подсеть, айпишники, которые выданы провайдерами.

SRV11=192.168.0.11

SRV12=192.168.0.12

А это наш сервер, для которого мы настраивали маршрутизацию на основе политик, используя метки. Как я уже говорил этот сервер на своем сетевом интерфейсе имеет два айпишника, чуть ниже я расскажу для чего это нам пригодиться.

. $1

Зацепили внешние настройки, в данном случае это будет наш файл ipt_p1.conf.

Хватит о скучном, приступим к настройке, причем попытаемся все сделать красиво:

echo "[+] Flushing existing iptables rules..."

$IPTABLES -F

$IPTABLES -F -t nat

$IPTABLES -F -t raw

$IPTABLES -F -t mangle

$IPTABLES -X

$IPTABLES -P INPUT DROP

$IPTABLES -P OUTPUT DROP

$IPTABLES -P FORWARD DROP

Очищаем все правила iptables, в первой строке говорим, что делаем, почему по английски, а чтобы не было проблем с кодировками. Последние три строчки устанавливают правила по умолчанию — все пакеты не подходящие под список правил будут просто отброшены.

$MODPROBE ip_conntrack

$MODPROBE iptable_nat

Загрузили модули ядра, которые будем использовать.

Теперь пройдемся по цепочкам iptables и заполним их необходимыми правилами:

echo "[+] Setting up INPUT chain..."

$IPTABLES -A INPUT -m state --state INVALID -j DROP

$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Используя возможности модуля state мы отбрасываем некорректные пакеты и принимаем пакеты относящиеся к уже установленным соединениям либо ко вторичными соединениям (таким как передача данных в ftp).

$IPTABLES -A INPUT -p tcp --dport 22 --syn -m state --state NEW -j ACCEPT

Принимаем подключения по SSH отовсюду.

$IPTABLES -A INPUT -i $LOCAL_ETH -s $LOCAL_NET -j ACCEPT

Локальный трафик будет ходить без ограничений, хотя это не всегда правильно.

$IPTABLES -A INPUT -i lo -j ACCEPT

Тоже на localhost.

Продолжаем с цепочкой OUTPUT:

echo "[+] Setting up OUTPUT chain..."

$IPTABLES -A OUTPUT -m state --state INVALID -j DROP

$IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Эти правила аналогичны правилам в цепочке INPUT.

$IPTABLES -A OUTPUT -o $GLOBAL_ETH_PRIM -p udp --dport 53 -j ACCEPT

Мы разрешили работать нашему DNS серверу через основного провайдера

$IPTABLES -A OUTPUT -o $GLOBAL_ETH_PRIM -p tcp --dport 22 --syn -m state --state NEW -j ACCEPT

А также разрешили выходить наружу по SSH.

$IPTABLES -A OUTPUT -o $LOCAL_ETH -d $LOCAL_NET -m state --state NEW -j ACCEPT

Опять же на исходящий локальный трафик ограничений нет.

Переходим к обработке трафика из локальной сети:

echo "[+] Setting up FORWARD chain..."

$IPTABLES -A FORWARD -m state --state INVALID -j DROP

$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

Все те же два удобных правила.

$IPTABLES -A FORWARD -i $GLOBAL_ETH_P1 -d $SRV11 -p tcp --dport 25 --syn -m state --state NEW -j ACCEPT

$IPTABLES -A FORWARD -i $GLOBAL_ETH_P2 -d $SRV12 -p tcp --dport 25 --syn -m state --state NEW -j ACCEPT

$IPTABLES -A FORWARD -i $GLOBAL_ETH_P1 -d $SRV11 -p tcp --dport 3389 --syn -m state --state NEW -j ACCEPT

$IPTABLES -A FORWARD -i $GLOBAL_ETH_P2 -d $SRV12 -p tcp --dport 3389 --syn -m state --state NEW -j ACCEPT

Так у нас получается, что пакеты приходящие на первого провайдера пропускаются только на первый айпишник сервера, второго — на второй.

$IPTABLES -A FORWARD -i $LOCAL_ETH -s $SRV11 -j ACCEPT

$IPTABLES -A FORWARD -i $LOCAL_ETH -s $SRV12 -j ACCEPT

Разрашаем весь исходящий трафик с нашего сервера, опять же это не совсем правильно.

Далее идут правила NAT:

$IPTABLES -t nat -A POSTROUTING -s $SRV11 -p tcp --dport 25 -j SNAT --to-source $GLOBAL_IP_PRIM

$IPTABLES -t nat -A POSTROUTING -s $SRV12 -p tcp --dport 25 -j SNAT --to-source $GLOBAL_IP_PRIM

Все, что наш сервер попытается отправить по SMTP пойдет через основного провайдера.

И опять самое интересное нам осталось на последок. Переходим к PREROUTING, здесь то мы и воспользуемся возможностью маркировать пакеты, которая нам понадобится для маршрутизации вот в этих двух строчках:

ip rule add from $SRV11 fwmark 10 table T1

ip rule add from $SRV12 fwmark 20 table T2

Итак, наши правила:

$IPTABLES -t mangle -A PREROUTING -i $LOCAL_ETH -s $SRV11 -p tcp --dport 25 -j MARK --set-mark $MARK_PRIM

$IPTABLES -t mangle -A PREROUTING -i $LOCAL_ETH -s $SRV12 -p tcp --dport 25 -j MARK --set-mark $MARK_PRIM

Все пакеты уходящие с нашего внутреннего сервера на 25 порт мы маркируем значением $MARK_PRIM. Давайте проследим, что это нам дает: исходящий пакет маркируется значением 10, значит маршрутизироваться он будет по таблице T1, а соответствуя этой таблице пакет должен уйти через первого провайдера, в цепочке FORWARD есть разрешающее правило, поэтому пакет безпрепятственно проходит — все правильно это нам и требовалось.

Теперь нам надо разобраться с соединениями идущими к нам. Сначала, конечно же, должен отработать DNAT:

$IPTABLES -t nat -A PREROUTING -i $GLOBAL_ETH_P1 -d $GLOBAL_IP_P1 -p tcp --dport 25 -j DNAT --to-destination $SRV11

$IPTABLES -t nat -A PREROUTING -i $GLOBAL_ETH_P1 -d $GLOBAL_IP_P1 -p tcp --dport 3389 -j DNAT --to-destination $SRV11

$IPTABLES -t nat -A PREROUTING -i $GLOBAL_ETH_P2 -d $GLOBAL_IP_P2 -p tcp --dport 25 -j DNAT --to-destination $SRV12

$IPTABLES -t nat -A PREROUTING -i $GLOBAL_ETH_P2 -d $GLOBAL_IP_P2 -p tcp --dport 3389 -j DNAT --to-destination $SRV12

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

$IPTABLES -t mangle -A PREROUTING -i $LOCAL_ETH -s $SRV11 -p tcp --sport 25 -j MARK --set-mark $MARK_PRIM

$IPTABLES -t mangle -A PREROUTING -i $LOCAL_ETH -s $SRV11 -p tcp --sport 3389 -j MARK --set-mark $MARK_PRIM

$IPTABLES -t mangle -A PREROUTING -i $LOCAL_ETH -s $SRV12 -p tcp --sport 25 -j MARK --set-mark $MARK_SEC

$IPTABLES -t mangle -A PREROUTING -i $LOCAL_ETH -s $SRV12 -p tcp --sport 3389 -j MARK --set-mark $MARK_SEC

Теперь на обратном пути мы маркируем пакеты в соответствии с адресом, с которого они отправляются. Далее в дело вступают таблицы маршрутизации T1 и T2, поэтому решение через какой интерфейс отправлять пакеты принимается правильное.

Все! Готово. Для применения правил выполняем команду ./ipt.conf ipt_p1.conf. Теперь наши сервера доступны, пока хотя бы один из провайдеров дает нам доступ в интернет. Еще хотел рассказать, как можно переключаться между провайдерами и сделать парочку замечаний, но объем статьи и так уже слишком большой, видимо будет третья часть.

Оригинал статьи находится в моем блоге "Используем 2+ провайдера"

http://hexbot.blogspot.com/2009/03/2_20.html

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования