Настройка линукс маршрутизатора через iptables + iproute2 на два (и
больше) внешних интерфейса.

Предполагается:

  • то вы уже знакомы с понятием маршрутизации и ната.
  • теоретически понимаете как работает нат, что такое маршрутизация и
    файрвол, но не знаете как это реализовать на вашей системе.

Имеется:

  • две входящие сетевые соски от двух разных провайдеров.
  • локальная сеть
  • три сетевых интерфейса на маршрутизаторе.

Задача:

Объеденить всех пользователей в одну локальную сеть и пускать одних
пользователей в интернет через одного провайдера, других – через
другого.

В рассматриваемом примере, все пользователи в локальной сети будут
находиться в сети 172.16.0.0/16, при этом пользователей из подсети
172.16.0.0/24 надо пропускать в интернет через первого провайдера, а
пользователей 172.16.1.0/24 – через второго.

Будем использовать iproute2 для таблиц маршуризации и iptables для ната.

Обозначим:

    $IP_LOCAL="172.16.0.1" - адрес нашего маршрутизатора в локальной сети.
    $IP_INET1="1.1.1.2" - адрес нашего маршрутизатора в сети первого провайдера.
    $IP_INET2="2.2.2.2" - адрес нашего марщрутизатора в сети второго провайдера.

    $IF_LOCAL="eth0" - имя интерфейса на локальную сеть
    $IF_INET1="eth1" - имя интерфейса на первого провайдера.
    $IF_INET2="eth2" - имя интерфейса на второго провайдера.

    $NET_LOCAL="172.16.0.0/16" - локальная сеть.
    $NET_INET1="1.1.1.0/24" - адрес сети в которой гейт нашего первого провайдера.
    $NET_INET2="2.2.2.0/24" - адрес сети в которой гейт нашего второго провайдера.
    $NET_SUB1="172.16.0.0/24" - подсеть пользователей на первого провайдера
    $NET_SUB2="172.16.1.0/24" - подсеть пользователей на второго провайдера

    $GW1="1.1.1.1" - гейт первого провайдера.
    $GW2="2.2.2.1" - гейт второго провайдера.

Настраиваем статические адреса на сетевые карты.

Debian (ubuntu) хранит настройки в файле

   /etc/network/interfaces.

пишем:

    auto lo
    iface lo inet loopback

    #local
    auto eth0
    iface eth0 inet static
            address 172.16.0.1
            netmask 255.255.0.0
            network 172.15.0.0
            broadcast 172.16.255.255

    #inet 1
    auto eth1
    iface eth1 inet static
            address 1.1.1.2
            netmask 255.255.255.0
            gateway 1.1.1.1
            network 1.1.1.0
            broadcast 1.1.1.255

    #inet 2
    auto eth2
    iface eth2 inet static
    #если надо - меняем мак адреса
    #        pre-up ifconfig eth2 hw ether aa:bb:cc:cc:bb:aa
            address 2.2.2.2
            netmask 2.2.2.0
    # себе я второй гейт не прописываю, в следствии чего сам маршрутизатор ходит в инет через первый инет
    #       gateway 2.2.2.1
            network 2.2.2.0
            broadcast 2.2.2.255

тем самым мы сказали, что все сетвые у нас имеют статические адреса, и
указали их.

Настаиваем маршрутизацию с утилитой ip.

Утилита route позволяет нам обратиться к таблице маршртизации.

Сила утилиты ip в том, что она позволяет создать большое количество
таблиц для самых разных потребностей, а так же, способна считывать
флаги, которые расставляет файрвол iptables (об этом ниже) и на их
основе тоже делать какие-то действия.

Основа маршрутизации через разные таблицы – правила (rule)

А сила различных таблиц в том, что мы можем хранить огромное количество
различных таблиц маршрутизации, через которые и будем пропускать пакеты.

Просмотреть список уже имеющихся таблиц можно командой

    ip rule list

    0:      from all lookup 255
    32766:  from all lookup main
    32767:  from all lookup default

Мы видим, что у нас есть три правила: таблица 255, main и default.
То, что выдает нам route – хранится в таблице main, что можно увидеть командой

    ip route list table main

В качестве номеров таблиц можно использовать цифры, ( пример: 0: from
all lookup 255 ), а можно прописать на эти цифры какие-то более понятные
простым смертным имена ( пример: 32766: from all lookup main ).

Так что обозначим свои таблицы:

Редактируем файл

    /etc/iproute2/rt_tables

и добавляем туда записи вида:

    #
    # reserved values
    #
    255     local
    254     main
    253     default
    0       unspec
    #
    # local
    #
    #1      inr.ruhep

    10      T1
    20      T2

номер – это то самое число, которое мы можем использовать если не
именовать таблицы, а строковое значение – то, что мы в действительности
будем использовать. (кстати, тут же мы видим и уже встречавшиеся нам в
списке правил таблицы)

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

Понятное дело, что каждый использует свой любимый редактор =)

/etc/init.d/route
#!/bin/sh

IP_LOCAL="172.16.0.1" # адрес нашего маршрутизатора в локальной сети.
IP_INET1="1.1.1.2" # адрес нашего маршрутизатора в сети первого провайдера.
IP_INET2="2.2.2.2" # адрес нашего марщрутизатора в сети второго провайдера.

IF_LOCAL="eth0" # имя интерфейса на локальную сеть
IF_INET1="eth1" # имя интерфейса на первого провайдера.
IF_INET2="eth2" # имя интерфейса на второго провайдера.

NET_LOCAL="172.16.0.0/16" # локальная сеть.
NET_INET1="1.1.1.0/24" # адрес сети в которой гейт нашего первого провайдера.
NET_INET2="2.2.2.0/24" # адрес сети в которой гейт нашего второго провайдера.

GW1="1.1.1.1" # гейт первого провайдера.
GW2="2.2.2.1" # гейт второго провайдера.

        ip route flush table T1			#обнуляем первую таблицу маршрутов
        ip route flush table T2			#обнуляем вторую таблицу маршрутов

        ip route add $NET_INET1 dev $IF_INET1 src $IP_INET1 table T1	#закидываем в первую таблицу инфу о сети первого провайдера
        ip route add $NET_LOCAL dev $IF_LOCAL table T1			#закидываем в первую таблицу инфу о том, что у нас существует локальная сеть
        ip route add $NET_INET2 dev $IF_INET2 table T1			#закидываем в первую таблицу инфу о том, что у нас существует еще одна сеть
        ip route add 127.0.0.0/8 dev lo   table T1			#закидываем в первую таблицу инфу о существовании лупбека
        ip route add default via $GW_INET1 table T1			#закидываем в первую таблицу дефолтный гейт на первого провайдера

        ip route add $NET_INET2 dev $IF_INET2 src $IP_INET2 table T2	#закидываем во вторую таблицу инфу о сети второго провайдера	
        ip route add $NET_LOCAL dev $IF_LOCAL table T2			#закидываем во вторую таблицу инфу о том, что у нас существует локальная сеть.
        ip route add $NET_INET1 dev $IF_INET1 table T2			#закидываем во вторую таблицу инфу о том, что у нас существует еще одна сеть.
        ip route add 127.0.0.0/8 dev lo   table T2			#закидываем во вторую таблицу инфу о существовании лупбека.
        ip route add default via $GW_INET2 table T2			#закидываем во вторую таблицу дефолтный гейт на второго провайдера

        ip route add $NET_INET1 dev $IF_INET1 src $IP_INET1	#заполняем основную таблицу адресов. сеть на первого провайдера
        ip route add $NET_INET2 dev $IF_INET2 src $IP_INET2	#заполняем основную таблицу адресов. сеть на второго провайдера

        ip route add default via $GW_INET1			#заполняем основную таблицу адресов. дефолтный гейт.

        ip rule delete table T1		#удаляем наши таблицы, если они присутсвуют в текущей конфигурации (вдруг мы просто перезапускаем скрипт?)
        ip rule delete table T2		#аналогично для второй.
        ip rule delete table T1		#и делаем это два раза, так как у нас два правила на каждую таблицу.
        ip rule delete table T2		#аналогично для второй.

        #а вот это важно для понимая! если понять что происходит в следующих строчках - то можно настраивать любые правила маршрутизации.

        ip rule add from $IP_INET1 table T1	#все пакеты от ip адреса первого провайдера маршрутизировать по таблице T1
        ip rule add from $IP_INET2 table T2	#все пакеты от ip адреса второго провайдера маршрутизировать по таблице T2

        ip rule add fwmark 10 table T1	#все пакеты, которые имеют метку 10 маршрутизировать по таблице T1
        ip rule add fwmark 11 table T2	#все пакеты, которые имеют метку 11 маршрутизировать по таблицу T2

        ip route flush cache		#ну и на последок очистить кеш

exit 0

В целом, понятно все, за исключением одного вопроса – что же это за
метка такая в последних строчках?

Тут мы обращаемся к утилите iptables.

Краткая теория. (полную и на русском языке можно, а вообще-то, даже
нужно, читать тут https://www.opennet.ru/docs/RUS/iptables/ )

Утилита iptables так же основана на таблицах. только таблиц в ней
фиксированно – три.

mangles – таблица используется для изменений заголовков пакетов.
filter – самая наша основаная таблица для файрвола – тут мы производим все блокировки, разрешения.
nat – таблица, как понятно из названия для ната.

Каждая таблица уже имеет некоторые предлопределенные цепочки, в которые
можно добавлять правила, а так же поддерживает создание пользовательские
цепочки.

Когда паркт попадает на интерфейс, и, его ловит iptables, то он проходит
следующие таблицы и цепочки, важные для нас:

  1. таблица mangle цепочка PREROUTING
  2. обработка маршрутизации.
  3. таблица nat цепочка POSTROUTING
    (в действительно пакет проходит еще и через другие таблицы и цепочки,
    но, для планируемой маршрутизации они нафик не сдались – изучение этого
    вопроса уже полностью на вашей совести =) ).

Скрипт для маршрутизации:

/etc/init.d/iptables

#!/bin/sh

IP_LOCAL="172.16.0.1" # адрес нашего маршрутизатора в локальной сети.
IP_INET1="1.1.1.2" # адрес нашего маршрутизатора в сети первого провайдера.
IP_INET2="2.2.2.2" # адрес нашего марщрутизатора в сети второго провайдера.

IF_LOCAL="eth0" # имя интерфейса на локальную сеть
IF_INET1="eth1" # имя интерфейса на первого провайдера.
IF_INET2="eth2" # имя интерфейса на второго провайдера.

NET_LOCAL="172.16.0.0/16" # локальная сеть.
NET_INET1="1.1.1.0/24" # адрес сети в которой гейт нашего первого провайдера.
NET_INET2="2.2.2.0/24" # адрес сети в которой гейт нашего второго провайдера.
NET_SUB1="172.16.0.0/24" # подсеть пользователей на первого провайдера
NET_SUB2="172.16.1.0/24" # подсеть пользователей на второго провайдера

GW1="1.1.1.1" # гейт первого провайдера.
GW2="2.2.2.1" # гейт второго провайдера.

IPT="/sbin/iptables"

 $IPT -t nat -F #очищаем таблицу nat
 $IPT -t mangle -F #очищаем таблицу mangle
 
 #все пакеты, которые попали в цепочку PREROUTING таблицы mangle обрабатываем по двум правилам:
 $IPT -t mangle -A PREROUTING -s $NET_SUB1 -d ! $NET_LOCAL -j MARK --set-mark 10 # все пакеты которые идут от $NET_SUB1 и не в $NET_LOCAL маркируем меткой 10
 $IPT -t mangle -A PREROUTING -s $NET_SUB2 -d ! $NET_LOCAL -j MARK --set-mark 11 # все пакеты которые идут от $NET_SUB1 и не в $NET_LOCAL маркируем меткой 10
 
 #все пакеты, которые попали в цепочку POSTROUTING таблицы nat обрабатываем по двум правилам:
 $IPT -t nat -A POTROUTING -m mark --mark 10 -j MASQUERADE # натим все пакеты которые имеют метку 10 
 $IPT -t nat -A POTROUTING -m mark --mark 11 -j MASQUERADE # натим все пакеты которые имеют метку 11 
 
exit 0

И так, что же происходит.

Пусть адрес пользователя 172.16.0.2

У пользователя прописан дефолтный гейт 172.16.0.1 – т.е. все пакеты
которые направлены не в локальную сеть пойдут туда.

На наш маршрутизатор приходит пакет от 172.16.0.2 и на адрес (к примеру) 4.4.4.4

  1. пакет попадает в таблицу mangle в цепоку PREROUTING и там по правилу
    “все пакеты от $NET_SUB1 и не в $NET_LOCAL” маркируется меткой 10 и
    попускается дальше.
  2. пакет попадает в правила маршрутизации и обрабатывается по правилу
    “все пакеты, которые имеют метку 10 маршрутизировать по таблице T1”.
    попав в эту таблицу маршрутизатор отправляет пакет в дефолтный гейт для
    этой таблицы, т.к. адрес 4.4.4.4 не подходит ни под одну сеть, которые
    есть в этой таблице.
  3. пакет попадает в таблицу nat в цепочку POSTROUTING и там по правилу
    “натим все пакеты которые имеют метку 10” натится наружу.

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

Сам факт подобной реализации маршрутизации возможен только из-за того,
что когда пакет обрабатывается правилами маршрутизации метка существует,
так как после пакет возвращается на обработку в таблицы iptables.

В целом, все =)

Осталось только сделать наши скрипты исполняемыми и закинуть их на
автозагрузку.

Важно обратить внимание, что данный маршрутизатор будет маршрутизировать
пакеты в обе стороны, так что если кто-то из внешних сетей пропишет себе
ip нашей локальной сети, и укажет в качестве маршрутизатора ip нашего
маршрутизатора – он спокойно попадет к нам.

Но настройка файрвола – это уже второй вопрос, который в эту статью не
входит.

Источник

0 0 голоси
Рейтинг статьи
Підписатися
Сповістити про

0 комментариев
Найновіше
Найстаріші Найбільше голосів
Зворотній зв'язок в режимі реального часу
Переглянути всі коментарі