• 4.1. Простая маршрутизация по источнику.
  • 4.2. Маршрутизация через несколько каналов/провайдеров.
  • 4.2.1. Раздельный доступ
  • 4.2.2. Распределение нагрузки.
  • Глава 4. Правила — база политик маршрутизации

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

    Если вы хотите использовать эту возможность, убедитесь что ядро собрано с поддержкой "IP: advanced router" и "IP: policy routing".

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

    Правила по-умолчанию:

    [ahu@home ahu]$ ip rule list

    0:     from all lookup local

    32766: from all lookup main

    32767: from all lookup default

    В этом листинге приведены приоритеты всех правил. Мы видим, что правила применяются ко всем пакетам (from all). Мы уже видели таблицу 'main', она выводится командой ip route ls , но таблицы 'local' и 'default' для нас новые.

    Если мы хотим сделать что-то интересное, то нужно задать правила, использующие разные таблицы маршрутизации. Это позволит нам переопределить общесистемную таблицу маршрутизации.

    За точной семантикой происходящего в ядре, когда есть несколько подходящих правил, обратитесь к документации ip-cref Алексея Кузнецова.

    4.1. Простая маршрутизация по источнику.

    Давайте опять рассмотрим реальный пример. У меня есть 2 (вообще-то 3, пора бы вернуть их) кабельных модема, подключенных к маршрутизатору Linux с NAT ('masquerading'). Люди с которыми я живу в одном доме, платят мне за использование Internet. Допустим одни из моих соседей ходит только на hotmail и хочет платить меньше. Мне это подходит, но при этом будет использоваться медленный канал.

    Быстрое соединение имеет с моей стороны адрес 212.64.94.251, а с другой — 212.64.94.1. Медленное соединение получает динамический адрес, в данном примере это 212.64.78.148, адрес провайдера — 195.96.98.253.

    Таблица local:

    [ahu@home ahu]$ ip route list table local

    broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1

    local 10.0.0.1 dev eth0 proto kernel scope host src 10.0.0.1

    broadcast 10.0.0.0 dev eth0 proto kernel scope link src 10.0.0.1

    local 212.64.94.251 dev ppp0 proto kernel scope host src 212.64.94.251

    broadcast 10.255.255.255 dev eth0 proto kernel scope link src 10.0.0.1

    broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1

    local 212.64.78.148 dev ppp2 proto kernel scope host src 212.64.78.148

    local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1

    local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1

    Много очевидных вещей, но они должны быть где-то указаны. Вот здесь они и заданы. Таблица default — пустая.

    Посмотрим теперь на таблицу main:

    [ahu@home ahu]$ ip route list table main

    195.96.98.253 dev ppp2 proto kernel scope link src

    212.64.78.148 212.64.94.1 dev ppp0 proto kernel scope link src 212.64.94.251

    10.0.0.0/8 dev eth0 proto kernel scope link src 10.0.0.1

    127.0.0.0/8 dev lo scope link default via 212.64.94.1 dev ppp0

    Создадим новое правило для нашего гипотетического соседа, которое будет называться 'John'. Хотя мы можем работать просто с числами, намного проще и понятней если мы определим названия наших таблиц в файле /etc/iproute2/rt_tables.

    # echo 200 John >> /etc/iproute2/rt_tables

    # ip rule add from 10.0.0.10 table John

    # ip rule ls

    0:     from all lookup local

    32765: from 10.0.0.10 lookup John

    32766: from all lookup main

    32767: from all lookup default

    Теперь нам нужно лишь сгенерировать таблицу John и очистить кэш маршрутов:

    # ip route add default via 195.96.98.253 dev ppp2 table John

    # ip route flush cache

    Вот и все. В качестве упражнения вы можете добавить это в скрипт ip-up.

    4.2. Маршрутизация через несколько каналов/провайдеров.

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

                                                                     _______

                                              +------------+        /

                                              |            |       |

                                +-------------+ Провайдер 1+-------

            __                  |             |            |     /

        ___/  \_         +------+-------+     +------------+    |

      _/        \__      |     if1      |                      /

    /              \     |    Linux     |                      |

    | Локальная сеть-----+ маршрутизатор|                      |     Internet

    \_           __/     |              |                      |

       \__     __/       |     if2      |                      \

          \___/          +------+-------+     +------------+    |

                                |             |            |     \

                                +-------------+ Провайдер 2+-------

                                              |            |       |

                                              +------------+        \_______

           В этом случае обычно возникает два вопроса.

    4.2.1. Раздельный доступ

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

    Давайте определим некоторые переменные. Пусть $IF1 будет именем первого интерфейса (if1 на рисунке), а $IF2 — именем второго. Тогда $IP1 будет IP адресом $IF1, а $IP2 — IP адресом $IF2. Далее, $P1 это IP-адрес шлюза провайдера 1, а $P2 — IP адрес шлюза провайдера 2. Наконец, $P1_NET это IP сеть, к которой принадлежит $P1, а $P2_NET — сеть, к которой принадлежит $P2.

    Создадим две дополнительные таблицы маршрутизации, скажем T1 и 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

    Ничего особо эффектного, маршрут к шлюзу и маршрут по-умолчанию через этот шлюз. Точно так же, как и в случае одного провайдера, но по таблице на каждого провайдера. Заметьте, что маршрута к сети, в которой находится шлюз достаточно, потому что он определяет как найти все хосты в этой сети, включая сам шлюз.

    Теперь нужно настроить главную таблицу маршрутизации. Хорошо бы маршрутизировать пакеты для сетей провайдеров через соответствующие интерфейсы. Обратите внимание на аргумент `src', который обеспечивает правильный выбор исходного IP-адреса.

    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 rule add from $IP1 table T1

    ip rule add from $IP2 table T2

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

    Warning

    Заметка читателя Рода Роака (Rod Roark):  если $P0_NET это локальная сеть, а $IF0 — соответствующий ей интерфейс, желательно задать следующие команды:

    ip route add $P0_NET     dev $IF0 table T1

    ip route add $P2_NET     dev $IF2 table T1

    ip route add 127.0.0.0/8 dev lo   table T1

    ip route add $P0_NET     dev $IF0 table T2

    ip route add $P1_NET     dev $IF1 table T2

    ip route add 127.0.0.0/8 dev lo   table T2

    Итак, мы рассмотрели очень простой пример. Он будет работать для всех процессов, выполняющихся на маршрутизаторе и для локальной сети, если настроено преобразование адресов (NAT/masquerading). В противном случае, вам будет необходим диапазон IP адресов обоих провайдеров, или выполнять маскирование для одного из провайдеров. В любом случае, вы можете задать правила выбора провайдера для каждого конкретного адреса вашей локальной сети.

    4.2.2. Распределение нагрузки.

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

    Вместо выбора одного из провайдеров в качестве маршрута по-умолчанию, вы настраиваете т.н. многолучевой (multipath) маршрут. В стандартном ядре это обеспечит балансировку нагрузки между двумя провайдерами. Делается это следующим образом (повторюсь, мы основываемся на примере из раздела Раздельный доступ):

    ip route add default scope global nexthop via $P1 dev $IF1 weight 1 \

     nexthop via $P2 dev $IF2 weight 1

    Результатом команды будет попеременный выбор маршрута по-умолчанию. Вы можете изменить параметр weight, так чтобы один из провайдеров получал большую нагрузку.

    Обратите внимание, что балансировка не будет идеальной, так как она основывается на маршрутах, а маршруты кэшируются. Это означает, что маршруты к часто посещаемым сайтам не будут проходить через разных провайдеров.

    Если вы действительно интересуетесь этим, вам стоит посмотреть на патчи Юлиана Анастасова (Julian Anastasov), расположеные по адресу http://www.ssi.bg/~ja/#routes. Они могут вам помочь.







     

    Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх