Используем 2+ провайдера (вторая часть)

    Продолжим настройку нашего шлюза, про который я говорил в предыдущей статье. Напомню, там мы настроили правила маршрутизации, теперь нам надо заняться 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+ провайдера (вторая часть)
    p.s. Написано, чтобы понять самому и рассказать другим.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 10

      –1
      Опубликовал у себя на сайте.Спасибо огромное.
      PS копирайты автора соблюдены _http://secnull.ru/index.php?showtopic=1761&pid=4718&st=0&
        +1
        я гей
          +1
          Тема хорошая и интересная, только не совсем понятно чего вы хотите добиться. То-ли балансировки нагрузки, то-ли отказоустойчивости, то-ли того и другого вместе.

          Я совсем не понял «Сейчас мы настроим сеть состоящую из шлюза и сервера. На шлюзе будет работать SSH и DNS, а сервер у нас будет виндовый на нем у нас RDP и SMTP. Сеть будет настроена таким образом, что через любой из внешних айпишников мы сможем подключаться к любому из серверов....» — так все-таки у вас один сервер или много? Где эти сервера вообще стоят? В DMZ? — Было бы хорошо, если бы была схемка!

          Не проще ли рассмотреть ситуацию без шлюза, просто хост с двумя интерфейсами во внешнюю сеть? Я полагаю тогда и двух внутренних айпишниках необходимость отпадет — они вводят в замешательство. Да и не понятно какой из них будет шлюзом в локальной сети. Первый? второй? любой?

          Путанно все как-то пока (
            0
            Здесь я, конечно же, имел ввиду, что подключения по SSH, SMTP, RDP будут корректно обрабатываться вне зависимости от того к какому из внешних ip мы подключаемся.
            +1
            Зачем iptables мучать, маркировать пакеты… Роутинг это умеет. Конкретнее,- ip ru add from [prov1_ip] lookup [prov1_routing_table]
            ip ru add from any lookup [main_routing_table]

            в prov1_routing_table — роуты как для 1-го прова
            в main_routing_table — распределение, можно по весу, можно еще как.

            При коннекте, маршрутизация кешируется и никаких проблем
              +2
              #ip ru s
              210: from 193.17.X.X lookup tdm
              220: from 217.144.X.X lookup lincom
              230: from 217.12.X.X lookup itl
              240: from 217.144.65.170 lookup dmz
              310: from all to 193.17.X.X/30 lookup tdm
              320: from all to 217.144.64.0/24 lookup lincom
              330: from all to 217.12.X.X/24 lookup itl
              30000: from all lookup multiway

              # ip ro s ta multiway
              217.12.X.X via 217.12.X.X dev ppp0
              192.168.5.0/24 via 192.168.5.1 dev eth0 proto static
              172.16.1.0/24 via 172.16.1.2 dev tun0 proto static
              192.168.10.0/24 via 192.168.10.1 dev eth1 proto static
              default proto static
              nexthop via 193.17.X.X dev eth2 weight 10
              nexthop via 193.17.X.X dev eth2 weight 10
              nexthop via 217.12.X.X dev ppp0 weight 2

              # ip ro s ta itl
              217.12.212.X/30 dev ppp0 scope link src 217.12.X.X
              192.168.5.0/24 via 192.168.5.1 dev eth0
              192.168.10.0/24 via 192.168.10.1 dev eth1
              127.0.0.0/8 dev lo scope link
              default via 217.12.X.X dev ppp0 src 217.12.X.X
              prohibit default proto static metric 1

                +1
                через ip ru легко задаётся на какого прова какой трафик слать, а через multiway — переключаем провов, меняя только default route
                0
                Да, но мне надо было маршрутизировать не по айпишнику, а по связке ip+port
                –1
                В конце статьи необходимо дать ссылку на первую часть!
                  –1
                  Уже есть в начале

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое