Форум русскоязычного сообщества Ubuntu
Страница сгенерирована за 0.046 секунд. Запросов: 25.
- Сайт
- Об Ubuntu
- Скачать Ubuntu
- Семейство Ubuntu
- Новости
- Форум
- Помощь
- Правила
- Документация
- Пользовательская документация
- Официальная документация
- Семейство Ubuntu
- Материалы для загрузки
- Совместимость с оборудованием
- RSS лента
- Сообщество
- Наши проекты
- Местные сообщества
- Перевод Ubuntu
- Тестирование
- RSS лента
© 2012 Ubuntu-ru — Русскоязычное сообщество Ubuntu Linux.
© 2012 Canonical Ltd. Ubuntu и Canonical являются зарегистрированными торговыми знаками Canonical Ltd.
Роутинг и policy-routing в Linux при помощи iproute2
Речь в статье пойдет о роутинге сетевых пакетов в Linux. А конкретно – о типе роутинга под названием policy-routing (роутинг на основании политик). Этот тип роутинга позволяет маршрутизировать пакеты на основании ряда достаточно гибких правил, в отличие от классического механизма маршрутизации destination-routing (роутинг на основании адреса назначения). Policy-routing применяется в случае наличия нескольких сетевых интерфейсов и необходимости отправлять определенные пакеты на определенный интерфейс, причем пакеты определяются не по адресу назначения или не только по адресу назначения. Например, policy-routing может использоваться для: балансировки трафика между несколькими внешними каналами (аплинками), обеспечения доступа к серверу в случае нескольких аплинков, при необходимости отправлять пакеты с разных внутренних адресов через разные внешние интерфейсы, даже для отправки пакетов на разные TCP-порты через разные интерфейсы и т.д.
Для управления сетевыми интерфейсами, маршрутизацией и шейпированием в Linux служит пакет утилит iproute2.
Этот набор утилит лишь задает настройки, реально вся работа выполняется ядром Linux. Для поддержки ядром policy-routing оно должно быть собрано с включенными опциями IP: advanced router (CONFIG_IP_ADVANCED_ROUTER) и IP: policy routing (CONFIG_IP_MULTIPLE_TABLES), находящимися в разделе Networking support -> Networking options -> TCP/IP networking.
ip route
Для настройки роутинга служит команда ip route. Выполненная без параметров, она покажет список текущих правил маршрутизации (не все правила, об этом чуть позже):
# ip route 192.168.12.0/24 dev eth0 proto kernel scope link src 192.168.12.101 default via 192.168.12.1 dev eth0
Так будет выглядеть роутинг при использовании на интерфейсе eth0 IP-адреса 192.168.12.101 с маской подсети 255.255.255.0 и шлюзом по умолчанию 192.168.12.1.
Мы видим, что трафик на подсеть 192.168.12.0/24 уходит через интерфейс eth0. proto kernel означает, что роутинг был задан ядром автоматически при задании IP интерфейса. scope link означает, что эта запись является действительной только для этого интерфейса (eth0). src 192.168.12.101 задает IP-адрес отправителя для пакетов, попадающих под это правило роутинга.
Трафик на любые другие хосты, не попадающие в подсеть 192.168.12.0/24 будет уходить на шлюз 192.168.12.1 через интерфейс eth0 ( default via 192.168.12.1 dev eth0 ). Кстати, при отправке пакетов на шлюз, IP-адрес назначения не изменяется, просто в Ethernet-фрейме в качестве MAC-адреса получателя будет указан MAC-адрес шлюза (часто даже специалисты со стажем путаются в этом моменте). Шлюз в свою очередь меняет IP-адрес отправителя, если используется NAT, либо просто отправляет пакет дальше. В данном случае используются приватный адрес (192.168.12.101), так что шлюз скорее всего делает NAT.
А теперь залезем в роутинг поглубже. На самом деле, таблиц маршрутизации несколько, а также можно создавать свои таблицы маршрутизации. Изначально предопределены таблицы local, main и default. В таблицу local ядро заносит записи для локальных IP адресов (чтобы трафик на эти IP-адреса оставался локальным и не пытался уходить во внешнюю сеть), а также для бродкастов. Таблица main является основной и именно она используется, если в команде не указано какую таблицу использовать (т.е. выше мы видели именно таблицу main). Таблица default изначально пуста. Давайте бегло взглянем на содержимое таблицы local:
# ip route show table local broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1 broadcast 192.168.12.255 dev eth0 proto kernel scope link src 192.168.12.101 broadcast 192.168.12.0 dev eth0 proto kernel scope link src 192.168.12.101 local 192.168.12.101 dev eth0 proto kernel scope host src 192.168.12.101 broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1 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
broadcast и local определяют типы записей (выше мы рассматривали тип default ). Тип broadcast означает, что пакеты соответствующие этой записи будут отправлены как broadcast-пакеты, в соответствии с настройками интерфейса. local – пакеты будут отправлены локально. scope host указывает, что эта запись действительная только для этого хоста.
Для просмотра содержимого конкретной таблицы используется команда ip route show table TABLE_NAME . Для просмотра содержимого всех таблиц в качестве TABLE_NAME следует указывать all , unspec или 0 . Все таблицы на самом деле имеют цифровые идентификаторы, их символьные имена задаются в файле /etc/iproute2/rt_tables и используются лишь для удобства.
ip rule
Как же ядро выбирает, в какую таблицу отправлять пакеты? Все логично – для этого есть правила. В нашем случае:
# ip rule 0: from all lookup local 32766: from all lookup main 32767: from all lookup default
- from – мы уже рассматривали выше, это проверка отправителя пакета.
- to – получатель пакета.
- iif – имя интерфейса, на который пришел пакет.
- oif – имя интерфейса, с которого уходит пакет. Это условие действует только для пакетов, исходящих из локальных сокетов, привязанных к конкретному интерфейсу.
- tos – значение поля TOS IP-пакета.
- fwmark – проверка значения FWMARK пакета. Это условие дает потрясающую гибкость правил. При помощи правил iptables можно отфильтровать пакеты по огромному количеству признаков и установить определенные значения FWMARK. А затем эти значения учитывать при роутинге.
Простой пример
Теперь рассмотрим простой пример. У нас есть некий шлюз, на него приходят пакеты с IP 192.168.1.20. Пакеты с этого IP нужно отправлять на шлюз 10.1.0.1. Чтобы это реализовать делаем следующее:
Создаем таблицу с единственным правилом:
# ip route add default via 10.1.0.1 table 120
Создаем правило, отправляющее нужные пакеты в нужную таблицу:
# ip rule add from 192.168.1.20 table 120
Как видите, все просто.
Доступность сервера через несколько аплинков

Теперь более реалистичный пример. Имеется два аплинка до двух провайдеров, необходимо обеспечить доступность сервера с обоих каналов:
В качестве маршрута по умолчанию используется один из провайдеров, не важно какой. При этом веб-сервер будет доступен только через сеть этого провайдера. Запросы через сеть другого провайдера приходить будут, но ответные пакеты будут уходить на шлюз по умолчанию и ничего из этого не выйдет.
Решается это весьма просто:
Определяем таблицы:
# ip route add default via 11.22.33.1 table 101 # ip route add default via 55.66.77.1 table 102
Определяем правила:
# ip rule add from 11.22.33.44 table 101 # ip rule add from 55.66.77.88 table 102
Думаю теперь уже объяснять смысл этих строк не надо. Аналогичным образом можно сделать доступность сервера по более чем двум аплинкам.
Балансировка трафика между аплинками
Делается одной элегантной командой:
# ip route replace default scope global \ nexthop via 11.22.33.1 dev eth0 weight 1 \ nexthop via 55.66.77.1 dev eth1 weight 1
Эта запись заменит существующий default-роутинг в таблице main. При этом маршрут будет выбираться в зависимости от веса шлюза ( weight ). Например, при указании весов 7 и 3, через первый шлюз будет уходить 70% соединений, а через второй – 30%. Есть один момент, который при этом надо учитывать: ядро кэширует маршруты, и маршрут для какого-либо хоста через определенный шлюз будет висеть в таблице еще некоторое время после последнего обращения к этой записи. А маршрут до часто используемых хостов может не успевать сбрасываться и будет все время обновляться в кэше, оставаясь на одном и том же шлюзе. Если это проблема, то можно иногда очищать кэш вручную командой ip route flush cache .
Использование маркировки пакетов при помощи iptables
Допустим нам нужно, чтобы пакеты на 80 порт уходили только через 11.22.33.1. Для этого делаем следующее:
# iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 80 -j MARK --set-mark 0x2 # ip route add default via 11.22.33.1 dev eth0 table 102 # ip rule add fwmark 0x2/0x2 lookup 102
Первой командой маркируем все пакеты, идущие на 80 порт. Второй командой создаем таблицу маршрутизации. Третьей командой заворачиваем все пакеты с указанной маркировкой в нужную таблицу.
Опять же все просто. Рассмотрим также использование модуля iptables CONNMARK. Он позволяет отслеживать и маркировать все пакеты, относящиеся к определенному соединению. Например, можно маркировать пакеты по определенному признаку еще в цепочке INPUT, а затем автоматически маркировать пакеты, относящиеся к этим соединениям и в цепочке OUTPUT. Используется он так:
# iptables -t mangle -A INPUT -i eth0 -j CONNMARK --set-mark 0x2 # iptables -t mangle -A INPUT -i eth1 -j CONNMARK --set-mark 0x4 # iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
Пакеты, приходящие с eth0 маркируются 2, а с eth1 – 4 (строки 1 и 2). Правило на третьей строке проверяет принадлежность пакета к тому или иному соединению и восстанавливает маркировки (которые были заданы для входящих) для исходящих пакетов.
Надеюсь изложенный материал поможет вам оценить всю гибкость роутинга в Linux. Спасибо за внимание 🙂
Статическая маршрутизация
Маршрут — это правило, устанавливаемое в ядре, чтобы определить, какой физический сетевой интерфейс или какой шлюз использовать, чтобы достичь определённой сети (или отдельного компьютера). Существует множество типов маршрутизируемых протоколов; данная статья описывает маршрутизацию протокола IP в ядре Linux.
Хотя маршруты IP хранятся в ядре, их можно модифицировать с помощью пользовательских инструментов, как это описано в следующих примерах.
- 1 Отображение маршрутов
- 2 Добавление статического маршрута
- 3 Добавление постоянного статического маршрута
- 4 Смотрите также
- 5 Внешние ресурсы
Отображение маршрутов
Показать таблицу маршрутизации с помощью iproute2:
user $ ip route
default via 192.168.1.1 dev wlan1 metric 1 192.168.50.0/24 dev lan proto kernel scope link src 192.168.50.1 127.0.0.0/8 via 127.0.0.1 dev lo 192.168.1.0/24 dev wlan1 proto kernel scope link src 192.168.1.1
Или показать таблицу маршрутизации с использованием sys-apps/net-tools :
user $ netstat -rn
Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.50.0 0.0.0.0 255.255.255.0 U 0 0 0 lan 192.168.1.0 0.0.0.0 255.255.255.0 U 2000 0 0 wlan1 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo 0.0.0.0 192.168.1.1 0.0.0.0 UG 2000 0 0 wlan1
Добавление статического маршрута
Для добавления статического маршрута необходимо знать адрес IP, маску подсети (CIDR) и шлюз.
В этом примере мы прокладываем маршрут к сети 10.10.10.0 с сетевой маской 255.255.255.0 через шлюз 192.168.1.50 . Для команд из sys-apps/iproute2 ( ip ) требуется использование синтаксиса подсетей в стиле CIDR. Следующий пример команды добавляет маршрут 10.10.10.0/24 :
root # ip route add 10.10.10.0/24 via 192.168.1.50
Показать таблицу маршрутизации с помощью команды ip route :
user $ ip route
default via 192.168.1.1 dev wlan1 metric 1 10.10.10.0/24 dev wlan1 via 192.168.1.50 src 10.10.10.1 192.168.50.0/24 dev lan proto kernel scope link src 192.168.50.1 127.0.0.0/8 via 127.0.0.1 dev lo 192.168.1.0/24 dev wlan1 proto kernel scope link src 192.168.1.1
В старых системах вместо использованного в примере ip , возможно, единственно доступными командами могут быть netstat или route (из пакета sys-apps/net-tools ).
С помощью команды route статический маршрут добавляется следующим образом:
root # route add -net 10.10.10.0 netmask 255.255.255.0 gw 192.168.1.50
Показать таблицу маршрутизации с помощью netstat ( sys-apps/net-tools ):
user $ netstat -rn
Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 10.10.10.0 192.168.1.50 255.255.255.0 UG 0 0 0 wlan1 192.168.50.0 0.0.0.0 255.255.255.0 U 0 0 0 lan 192.168.1.0 0.0.0.0 255.255.255.0 U 2000 0 0 wlan1 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo 0.0.0.0 192.168.1.1 0.0.0.0 UG 2000 0 0 wlan1
Таблица маршрутизации отсортирована от наиболее конкретных маршрутов к наиболее общим. Так она прочитывается в процессе маршрутизации. Совпадение с наибольшим префиксом означает самую маленькую сеть, или сеть с самой длинной сетевой маской, или самый конкретный маршрут, например 255.255.255.255 находится на первой позиции в таблице маршрутизации
Добавление постоянного статического маршрута
Пользователям netifrc (стандартный инструмент управления сетью в OpenRC) для добавления постоянного статического маршрута нужно открыть /etc/conf.d/net в любимом текстовом редакторе и изменить его соответствующим образом.
Посмотрите свою текущую таблицу маршрутизации для справки.
ФАЙЛ /etc/conf.d/net
routes_wlan1="10.10.10.0/24 via 192.168.1.50 default via 192.168.1.1"
Если в качестве сетевого менеджера используется dhcpcd, статический маршрут вместо этого должен быть записан в /etc/dhcpcd.conf .
Оба указанные выше конструкции означают:
- IP-пакеты, предназначенные для сети 10.10.10.0/24 , будут отправлены в 192.168.1.50 .
- IP-пакеты, предназначенные для всех остальных сетей 0.0.0.0/0 , будут отправлены в 192.168.1.1 .
Заметка
0.0.0.0/0 означает все другие сети без префикса (маски подсети), то есть маршрут по умолчанию.
Маршрут по умолчанию 0.0.0.0/0 будет использован, если:
- Узел не имеет физического или логического интерфейса IP в целевом сегменте сети.
- Узел вынужден отправлять IP-пакеты за пределы своего сегмента IP-сети, и в таблице маршрутизации явно не указан маршрут к целевой сети IP.
Смотрите также
- iproute2 — a tool developed to unify network interface configuration, routing, and tunneling for Linux systems.
- Network management — describes possibilities for managing the network stack.
Внешние ресурсы
- Совпадение с наибольшим префиксом (Википедия)
- Gentoo Bug 5409326
Глава 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.
[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.
| Назад | В начало документа | Вперед |
| ARP | Маршрутизация через несколько каналов/провайдеров. |