- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF133:Маршрутизация
Материал из Linuxformat.
Содержание |
IP: О политике
- Это не самая подходящая тема для светской беседы, но Андрей Конкин и не собирается заниматься предвыборной агитацией. На повестке дня: маршрутизация в особых условиях.
Классические алгоритмы маршрутизации, используемые в Интернете, обычно основываются лишь на адресе назначения пакета. Но бывают случаи, когда необходимо принять во внимание, например, адрес отправителя (так называемая «маршрутизация от источника»), тип протокола или порты отправителя и получателя. Для этого существует специальный механизм, известный как маршрутизация по политикам (policy routing). Его основная область применения – предоставление равноправного доступа, маршрутизация от источника или по типу протокола. В работе механизма можно условно можно выделить два этапа: выбор и маркировку пакетов по некоторому критерию и маршрутизацию отобранных пакетов в соответствии с определенным для них правилом.
Как он работает?
В реализации Linux механизм маршрутизации по политикам представляет собой набор таблиц и правил. Каждое правило состоит из критерия отбора и действия, определяющего таблицу, по которой будет выполняться маршрутизация. В качестве критерия отбора для правил может использоваться адрес отправителя, адрес получателя, tos и fwmark (пакеты, маркированные iptables). Прежде чем принять решение о маршрутизации пакета, система начинает просматривать правила в порядке возрастания их приоритета, от 0 до 32767. Если пакет удовлетворяет какому-либо критерию отбора, то дальнейший поиск осуществляется по таблице, заданной в правиле.
Изначально ядро ОС создает три правила, которые указывают на три основных таблицы: local, main и default. Таблица local содержит маршруты для локальных и широковещательных адресов. Правило отбора в эту таблицу имеет самый высокий приоритет. Таблица main содержит маршруты, добавляемые пользователем. Это основная таблица маршрутизации. Правило, передающее пакеты в эту таблицу, имеет приоритет 32766. После нее рассматривается только таблица default – обычно она пуста. Вообще, Linux может использовать 255 таблиц маршрутизации с номерами (ID) от 1 до 255. Для вышеописанных таблиц ID выглядят так: local – ID 255, main – ID 254, default – ID 253.
Все таблицы определяются в файле /etc/iproute2/rt_tables. Каждая его строка задает одну таблицу. Сначала идет ID таблицы: он может быть любым в диапазоне 1–255 и должен быть уникальным. Дальше указывается имя таблицы; оно также может быть любым и используется только для удобства при настройке.
Что нам потребуется?
Чтобы механизм маршрутизации по политикам заработал, для начала необходимо, чтобы Linux вообще мог работать в качестве маршрутизатора и пересылать пакеты с одного сетевого интерфейса на другой. Эту возможность обеспечивает ядро. В современных дистрибутивах Linux опция ядра IP: advanced router включена по умолчанию, но для пересылки пакетов между интерфейсами необходимо разрешить использование данной возможности. Последнее достигается через файловую систему proc с помощью следующей команды:
# echo 1 > /proc/sys/net/ipv4/ip_forward
либо с использованием sysctl:
# sysctl -w net.ipv4.ip_forward=1
Маршрутизацию от источника можно сделать несколькими способами: использовать поддержку со стороны ядра Linux либо маркировать пакеты с помощью iptables, основываясь на адресе отправителя и маршрутизировать маркированные пакеты. Чтобы обеспечить поддержку со стороны ядра и не использовать iptables, необходимо включить опцию IP: policy routing. Для реализации маршрутизации от источника с помощью iptables необходимо включить в ядре поддержку iptables и возможность маркировать с его помощью пакеты (опция ядра «MARK» target support).
В итоге в ядре Linux должны быть включены такие опции:
Networking Support Networking Options [*] IP: advanced router [*] IP: policy routing [*] Network Packet filtering framework (Netfilter) Core Netfilter Configuration [*] “MARK” target support
Старые утилиты, такие как ifconfig и route, работают только с таблицами local и main. Утилита ip из пакета iproute2 по умолчанию также работает с таблицей main.
Если для отбора и маркировки пакетов планируется использовать какие-то другие возможности iptables, их также необходимо включить в ядре. Вообще говоря, лучше включить поддержку iptables полностью, хотя бы в виде модулей ядра. В этом случае какое бы правило вы ни захотели написать в будущем, можно быть уверенным, что со стороны ядра поддержка уже есть.
iproute2 – это комплект инструментов для настройки параметров сетевых устройств в Linux. Из всего набора нам понадобится только утилита ip. Она позволяет управлять маршрутизацией, сетевыми устройствами, политиками маршрутизации и туннелями.
iptables – это утилита для конфигурирования встроенного брандмауэра Linux, Netfilter. Все, что он умеет делать – это фильтровать и модифицировать пакеты.
Далее мы рассмотрим два основных примера использования маршрутизации по политикам: маршрутизацию от источника без использования iptables и маршрутизацию по типу протоколов с использованием iptables.
От источника!
Предположим, что у нас есть Linux-машина, на которой установлены три сетевых интерфейса со следующими адресами:
eth0: 192.168.0.1/24 eth1: 172.16.0.1/24 eth2: 10.0.0.1/24
К интерфейсу eth2 подключена сеть из четырех машин:
PC1: 10.0.0.2 PC2: 10.0.0.3 PC3: 10.0.0.4 PC4: 10.0.0.5
Эта схема представлена на рис. 1.
Допустим, весь трафик от PC1 и PC2 нужно направить через eth0 на 192.168.0.2, а от PC3 и PC4 – через eth1 на 172.16.0.2. Будем считать, что шлюз по умолчанию на Linux-машине не настроен.
Для начала проверим, включен ли режим advanced router:
# sysctl net.ipv4.ip_forward
Или так:
# cat /proc/sys/net/ipv4/ip_forward
Какой бы командой вы ни воспользовались, на выходе должна появиться единица. Если же вы видите ноль, режим маршрутизатора необходимо активировать, как было описано выше.
Теперь создадим две дополнительных таблицы и назовем их, например, pc12 и pc34:
# echo '100 pc12' >> /etc/iproute2/rt_tables # echo '101 pc34' >> /etc/iproute2/rt_tables
ID таблиц 100 и 101 мы взяли произвольно; главное, чтобы они не совпадали с уже имеющимися.
Добавляем в каждую из созданных таблиц свой шлюз по умолчанию.
# ip route add default via 192.168.0.2 table pc12 # ip route add default via 172.16.0.2 table pc34
Таблицы готовы, осталось определить политики маршрутизации, выбирающие таблицу для каждого пакета в соответствии с его адресом отправителя.
# ip rule add from 10.0.0.2 table pc12 # ip rule add from 10.0.0.3 table pc12 # ip rule add from 10.0.0.4 table pc34 # ip rule add from 10.0.0.5 table pc34
Если посмотреть на вывод команды
# ip rule show
то мы увидим, что к трем основным правилам у нас добавились дополнительные, определенные нами правила с приоритетами 32762–32765.
0: from all lookup local 32762: from 10.0.0.5 lookup pc34 32763: from 10.0.0.4 lookup pc34 32764: from 10.0.0.3 lookup pc12 32765: from 10.0.0.2 lookup pc12 32766: from all lookup main 32767: from all lookup default
В приведенном примере мы для наглядности специально создали две дополнительные таблицы. На самом же деле можно было обойтись одной. В этом случае необходимо было просто добавить правила для узлов PC1 и PC2 (либо прописать шлюз по умолчанию), не указывая таблицу. Наши правила добавились бы в таблицу main. А в дополнительную, созданную нами, таблицу мы бы отбирали трафик от узлов PC3 и PC4 с помощью правил маршрутизации по политикам.
По протоколу
Во втором примере к нашему Linux-маршрутизатору через интерфейс eth1 будет подключена локальная сеть. Для выхода в Интернет у нашего роутера есть два интерфейса – быстрый eth0 и медленный ppp0. Теперь нам необходимо направить весь ICMP, SSH и DNS трафик через ppp0, а весь остальной – через eth0 на 192.168.0.2. Как и в прошлом примере, мы считаем, что шлюз по умолчанию на Linux-машине не настроен, но она умеет пересылать пакеты между интерфейсами (режим advanced router включен). Схема представлена на рисунке 2.
На этот раз мы не будем делать две дополнительные таблицы: вместо этого используем таблицу main и одну сделаем сами.
Сначала добавим шлюз по умолчанию в уже существующую таблицу main. После этого у нас весь трафик будет направляться через eth0.
# ip route add default via 192.168.0.2
Далее, добавим собственную таблицу – назовем ее ISD:
# echo '30 ISD' >> /etc/iproute2/rt_tables
Чтобы выбрать нужные нам пакеты из всего потока данных, мы будем использовать маркировку через iptables и свойство fwmark правила для указания на таблицу.
Мы будем добавлять правила маркировки пакетов в цепочку PREROUTING таблицы mangle. Эта цепочка отрабатывается до принятия решения о маршрутизации.
Добавляем в iptables правила для маркировки ICMP-, SSH- и DNS-трафика:
# iptables -t mangle -A PREROUTING -p icmp -j MARK --set-mark 10 # iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 10 # iptables -t mangle -A PREROUTING -p udp --dport 53 -j MARK --set-mark 10
Зададим для нашей новой таблицы шлюз по умолчанию через ppp0:
# ip route add default dev ppp0 table ISD
И, наконец, напишем правило для маршрутизации по политикам:
# ip rule add fwmark 10 table ISD
Теперь наш Linux-маршрутизатор будет разбирать маркированные пакеты в соответствии с политикой маршрутизации.
Iptables за 5 минут
В iptables есть три таблицы: mangle, nat и filter. Таблица mangle предназначена для маркировки пакетов и соединений, а также модификации заголовков пакетов. Эта таблица состоит из пяти цепочек: PREROUTING, POSTROUTING, INPUT, OUTPUT, FORWARD.
Таблица nat предназначена для преобразования сетевых адресов и портов обрабатываемых пакетов. В таблицу входят три цепочки: PREROUTING, POSTROUTING, OUTPUT.
Таблица filter предназначена для фильтрации трафика. В эту таблицу входят три цепочки: INPUT, OUTPUT, FORWARD.