Policy routing with linux

Маршрутизация на основе политик. Часть первая

Так будет выглядеть роутинг при использовании на интерфейсе enp0s3 ip-адреса 192.168.110.50 с маской подсети 255.255.255.0 и шлюзом по умолчанию 192.168.110.1 :

Вторая запись означает:

  • пакеты в подсеть 192.168.110.0/24 уходят через интерфейс enp0s3
  • proto kernel — маршрут был добавлен ядром при назначении интерфейсу ip-адреса
  • scope link — запись действительна только для интерфейса enp0s3
  • src 192.168.110.50 — задает ip-адрес отправителя пакетов для этого правила

Первая запись означает, что пакеты на любые хосты, не попадающие в подсеть 192.168.110.0/24 будут уходить в шлюз 192.168.110.1 через интерфейс enp0s3 . Шлюз, в свою очередь, меняет ip-адрес отправителя, если используется NAT, либо просто отправляет пакет дальше.

Маршрутизация на основе политик

Существуют два механизма маршрутизации: классический destination-routing (на основе адреса назначения) и сравнительно новый policy-routing (на основе политик). Маршрутизация на основе политик применяется в случае наличия нескольких сетевых интерфейсов и необходимости отправлять определенные пакеты через определенный интерфейс. Маршрут пакета определяется не только на основе адреса назначения — есть возможность анализа практически любых полей пакета.

В основе маршрутизации с использованием политик лежат четыре понятия:

  • Адрес ( address ) определяет ip-адрес места назначения пакета
  • Маршрут ( route ) задает путь пакета, как в традиционной маршрутизации
  • Таблица маршрутизации ( routing table ) состоит из набора нескольких маршрутов
  • Правила ( rule ) позволяют отбирать нужные пакеты и направлять по заданному маршруту

Таблицы маршрутизации

Изначально предопределены таблицы мартшрутизации local , main и default :

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

Давайте посмотрим на содержимое таблицы local :

Выше мы уже сталкивались с типом записи default , но здесь мы видим еще local и broadcast :

  • broadcast — для этой записи пакеты будут отправлены как широковещательное сообщение
  • local — для этой записи пакеты будут отправлены локально, без выхода во внешнюю сеть

Кроме того, типы записи могут быть unicast , unreachable , blackhole , prohibit и так далее:

  • unicast — обычный маршрут: исходящий интерфейс + адрес следующего хопа до пункта назначения
  • unreachable — пакет выбрасывается и посылается ICMP сообщение «host unreachable»
  • blackhole — пакет просто выбрасывается без возвращения какого-либо сообщения
  • prohibit — пакет выбрасывается и посылается ICMP сообщение «administratively prohibited»

Что такое scope link мы уже знаем, но здесь еще встречается scope host :

  • scope host — эта запись действительна только для этого хоста
  • scope link — эта запись действительна только для этого интерфейса

Для просмотра содержимого всех таблиц в качестве имени таблицы следует указывать all , unspec или ноль. Все таблицы на самом деле имеют цифровые идентификаторы от 1 до 255, их символьные имена задаются в файле /etc/iproute2/rt_tables и используются лишь для удобства.

Таблица unspec — это псевдо-таблица, которая содержит в себе правила всех таблиц маршрутизации системы. Именно поэтому у нее номер ноль, который не входит в диапазон с 1 по 255.

Правила маршрутизации

Как же ядро выбирает, в какую таблицу отправлять пакеты? Мы уже знаем — для этого есть правила:

Число в начале строки — идентификатор правила, from all — условие, означает пакеты с любых адресов, lookup указывает, в какую таблицу направлять пакет. Если пакет подпадает под несколько правил, то он проходит их все по порядку возрастания идентификатора. Конечно, если пакет подпадет под какую-либо запись маршрутизации, то последующие записи маршрутизации и последующие правила он уже проходить не будет.

  • from — отправитель пакета.
  • to — получатель пакета.
  • iif — имя интерфейса, на который пришел пакет.
  • oif — имя интерфейса, с которого уходит пакет. Это условие действует только для пакетов, исходящих из локальных сокетов, привязанных к конкретному интерфейсу.
  • tos — значение поля TOS ip-пакета.
  • fwmark — проверка значения FWMARK пакета. При помощи правил iptables можно отфильтровать пакеты по огромному количеству признаков и установить определенные значения FWMARK . А затем эти значения учитывать при роутинге.

Условия можно комбинировать, например from 192.168.1.0/24 to 10.0.0.0/8 , а также можно использовать префикc not , который указывает, что пакет не должен соответствовать условию, чтобы подпадать под это правило.

Читайте также:  Команды яндекс диска linux

Источник

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

Немного усложним конфигурацию сети из третьей части. У нашего компьютера теперь не два, а три сетевых интерфейса. Первый интерфейс имеет выход в интернет через сеть первого интернет-провайдера, второй интерфейс — через сеть второго интернет-провайдера. А третий интерфейс подключен к локальной сети 192.168.250.0/24 . И наш компьютер должен обеспечивать выход в интернет для всех компьютеров этой сети.

Настройка сети

На компьютере gateway установлена ОС Ubuntu Server, настройка сети выполнена с использованием Netplan:

После загрузки системы смотрим маршруты таблицы main :

Здесь два маршрута по умолчанию, но с разными значениями метрики — один маршрут основной (метрика 100), другой резервный (метрика 200).

Таблицы маршрутизации

И есть два правила, которые предписывают просматривать таблицы primary и secondary , если пакеты отправляются с ip-адресов 192.168.50.2 и 192.168.150.2 соответственно.

Таблицы маршрутизации primary и secondary определены в файле /etc/iproute2/rt_tables :

Каждая из таблиц маршрутизации содержит маршрут по умолчанию:

Переключение каналов

За переключение каналов отвечает скрипт /root/swicth-channel/swicth-channel.sh :

Этот скрипт будем запускать каждую минуту:

Форвардинг пакетов

По умолчанию транзитный трафик отключен, так что редактируем файл /etc/sysctl.conf :

После этого настраиваем netfilter с помощью утилиты iptables :

И смотрим, что получилось:

Мы разрешили ходить транзитным пакетам для нашего диапазона ip адресов, а всё остальное запретили.

Сохранение правил

Созданные с помощью утилиты iptables правила пропадут при перезагрузке. Так что их нужно сохранить и восстанавливать при перезагрузке. В этом нам поможет пакет iptables-persistent :

При установке пакета будет предложено сохранить текущие правила iptables :

  • в файл /etc/iptables/rules.v4 для протокола IPv4
  • в файл /etc/iptables/rules.v6 для протокола IPv6

После установки пакета будет добавлена новая служба netfilter-persistent.service , которая при загрузке системы будет восстанавливать созданные нами правила:

Поднимаем web-сервер

Установим на машине web-server пакет apache2 :

С компьютера pc-1 проверим, что сервер работает:

Чтобы обеспечить доступ к web-серверу из интернета, выполняем на gateway1 команду (подробности здесь):

И сохраняем правила, чтобы они восстановилось после перезагрузки:

Проверяем, что web-сервер теперь доступен, набирая в адресной строке http://111.111.111.111/ :

Настройка pc-1 и pc-2

Настройка сети одинаковая для pc-1 и pc-2 , выполнена с использованием Netplan, им назначены ip-адреса 192.168.250.2 и 192.168.250.3 :

Служба NetworkManager отключена, вместо нее за сеть отвечает служба systemd-networkd :

Еще одна таблица маршрутизации

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

Теперь добавляем новое правило — какие таблицы просматривать при отправке пакета:

Смотрим список правил — какие таблицы будут просмотрены при отправке пакета:

Для таблицы pc2-via-gw2 зададим маршрут по умолчанию:

Убедимся, что маршрут по умолчанию для pc2-via-gw2 добавлен:

Проверка маршрута для pc-2

Проверим, что компьютер pc-2 выходит в интернет через резервный канал связи:

Удостоверимся, что компьютер pc-1 выходит в интернет через основной канал связи:

Файл конфигурации сети

Созданные нами правило и маршрут по умолчанию для таблицы pc2-via-gw2 пропадут при перезагрузке gateway , поэтому надо изменить файл конфигурации сети:

Читайте также:  Удалил панель задач linux mint

Источник

Роутинг и 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. Выполненная без параметров, она покажет список текущих правил маршрутизации (не все правила, об этом чуть позже):

Так будет выглядеть роутинг при использовании на интерфейсе 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:

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

Как же ядро выбирает, в какую таблицу отправлять пакеты? Все логично – для этого есть правила. В нашем случае:

Число в начале строки – идентификатор правила, from all – условие, означает пакеты с любых адресов, lookup указывает в какую таблицу направлять пакет. Если пакет подпадает под несколько правил, то он проходит их все по порядку возрастания идентификатора. Конечно, если пакет подпадет под какую-либо запись маршрутизации, то последующие записи маршрутизации и последующие правила он уже проходить не будет.
Возможные условия:

  • from – мы уже рассматривали выше, это проверка отправителя пакета.
  • to – получатель пакета.
  • iif – имя интерфейса, на который пришел пакет.
  • oif – имя интерфейса, с которого уходит пакет. Это условие действует только для пакетов, исходящих из локальных сокетов, привязанных к конкретному интерфейсу.
  • tos – значение поля TOS IP-пакета.
  • fwmark – проверка значения FWMARK пакета. Это условие дает потрясающую гибкость правил. При помощи правил iptables можно отфильтровать пакеты по огромному количеству признаков и установить определенные значения FWMARK. А затем эти значения учитывать при роутинге.
Читайте также:  Как через безопасный режиме установить windows

Условия можно комбинировать, например from 192.168.1.0/24 to 10.0.0.0/8 , а также можно использовать префикc not , который указывает, что пакет не должен соответствовать условию, чтобы подпадать под это правило.
Итак, мы разобрались что такое таблицы маршрутизации и правила маршрутизации. А создание собственных таблиц и правил маршрутизации это и есть policy-routing, он же PBR (policy based routing). Кстати SBR (source based routing) или source-routing в Linux является частным случаем policy-routing, это использование условия from в правиле маршрутизации.

Простой пример

Теперь рассмотрим простой пример. У нас есть некий шлюз, на него приходят пакеты с IP 192.168.1.20. Пакеты с этого IP нужно отправлять на шлюз 10.1.0.1. Чтобы это реализовать делаем следующее:
Создаем таблицу с единственным правилом:

Создаем правило, отправляющее нужные пакеты в нужную таблицу:

Как видите, все просто.

Доступность сервера через несколько аплинков

Теперь более реалистичный пример. Имеется два аплинка до двух провайдеров, необходимо обеспечить доступность сервера с обоих каналов:

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

Думаю теперь уже объяснять смысл этих строк не надо. Аналогичным образом можно сделать доступность сервера по более чем двум аплинкам.

Балансировка трафика между аплинками

Делается одной элегантной командой:

Эта запись заменит существующий default-роутинг в таблице main. При этом маршрут будет выбираться в зависимости от веса шлюза ( weight ). Например, при указании весов 7 и 3, через первый шлюз будет уходить 70% соединений, а через второй – 30%. Есть один момент, который при этом надо учитывать: ядро кэширует маршруты, и маршрут для какого-либо хоста через определенный шлюз будет висеть в таблице еще некоторое время после последнего обращения к этой записи. А маршрут до часто используемых хостов может не успевать сбрасываться и будет все время обновляться в кэше, оставаясь на одном и том же шлюзе. Если это проблема, то можно иногда очищать кэш вручную командой ip route flush cache .

Использование маркировки пакетов при помощи iptables

Допустим нам нужно, чтобы пакеты на 80 порт уходили только через 11.22.33.1. Для этого делаем следующее:

Первой командой маркируем все пакеты, идущие на 80 порт. Второй командой создаем таблицу маршрутизации. Третьей командой заворачиваем все пакеты с указанной маркировкой в нужную таблицу.
Опять же все просто. Рассмотрим также использование модуля iptables CONNMARK. Он позволяет отслеживать и маркировать все пакеты, относящиеся к определенному соединению. Например, можно маркировать пакеты по определенному признаку еще в цепочке INPUT, а затем автоматически маркировать пакеты, относящиеся к этим соединениям и в цепочке OUTPUT. Используется он так:

Пакеты, приходящие с eth0 маркируются 2, а с eth1 – 4 (строки 1 и 2). Правило на третьей строке проверяет принадлежность пакета к тому или иному соединению и восстанавливает маркировки (которые были заданы для входящих) для исходящих пакетов.
Надеюсь изложенный материал поможет вам оценить всю гибкость роутинга в Linux. Спасибо за внимание 🙂

Источник

Оцените статью