Как правильно настроить маршрутизацию на основе политик (policy-based routing) на роутере с операционной системой Linux?

Привет, сообщество! Нужна ваша помощь с настройкой policy based routing, или, возможно, поясните, что он мне не нужен. 

Вот моя ситуация: у меня роутер на базе Linux Debian 12, на котором работает несколько легковесных сервисов, плюс NAT на другой сервер с разными службами. У меня около 10 локальных подсетей (виланы по одному кабелю, если это имеет значение). Использую фаервол iptables, у меня довольно обширный список правил. Есть 1 WAN с pppoe, который пусть будет ppp0, подключенный через отдельный интерфейс. 

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

На мой взгляд, проблема в том, что входящие пакеты на 25-й порт через ppp0 NAT’ится на другой сервер, но при возвращении они проходят через различные маршруты и уходят в tun0. 

Я понимаю, что нужно изучить policy based routing и, вероятно, маркировать трафик в iptables и направить его в отдельную таблицу, чтобы он вернулся через ppp0, но не хочу затрагивать весь трафик. Прочитал около 10 статей на эту тему, но они в основном касаются исходящего трафика. 

Так какой же правильный подход к этой проблеме? Я не выкладываю свои скрипты и конфиги, так как хочу разобраться самостоятельно, но буду благодарен за примеры или соображения от вас. Если не удастся разобраться, поделюсь тем, что у меня получилось (было отмечено в iptables через connmark, обработано на выходе, и отправлено в таблицу с маршрутом по умолчанию через ppp0).
  • 15 сентября 2024 г. 20:23
Ответы на вопрос 2
Настройка маршрутизации на основе политик (policy-based routing, PBR) на роутере с Linux может показаться сложной задачей, но с правильным подходом и пониманием процесса вы можете успешно решить вашу проблему. Давайте разберемся, как это сделать пошагово, ориентируясь на вашу ситуацию.

### Шаг 1: Маркировка трафика

Первый шаг — это использование iptables для маркировки пакетов, которые вы хотите маршрутизировать определенным образом. В вашем случае это пакеты на порт 25 (SMTP). Вы можете использовать `CONNMARK` для маркировки пакетов на основе установленных соединений.

Пример команды для маркировки исходящих пакетов на порт 25:

```bash
iptables -t mangle -A OUTPUT -p tcp --dport 25 -j CONNMARK --set-mark 1
```

Этот пример устанавливает маркер `1` для всех исходящих соединений на порт 25.

### Шаг 2: Настройка таблицы маршрутизации

Далее вам нужно создать собственную таблицу маршрутизации. Для этого отредактируем файл `/etc/iproute2/rt_tables`, добавив строку с именем таблицы:

```
100     myppp
```

Теперь создадим маршруты для этой таблицы. Предположим, что у вас уже есть маршрут по умолчанию через ppp0.

```bash
ip route add default via <IP-адрес шлюза> dev ppp0 table myppp
```

### Шаг 3: Настройка правил маршрутизации

Теперь вам нужно добавить правило для того, чтобы маршрутизировать пакеты, маркированные выше, через вашу новую таблицу. Это делается с помощью `ip rule`:

```bash
ip rule add fwmark 1 table myppp
```

Эта команда говорит системе, что все пакеты с маркером 1 должны быть направлены в таблицу `myppp`.

### Шаг 4: Убедитесь, что NAT настроен правильно

Не забудьте, что если вы используете NAT для исходящего трафика, вам нужно убедиться, что пакеты, возвращающиеся через ppp0, также проходят через NAT. Если у вас уже есть правило NAT для ppp0, убедитесь, что оно сердечно охватывает все потоки, включая входящий с портом 25.

Пример правила NAT для ppp0:

```bash
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
```

### Шаг 5: Проверка и отладка

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

- Для проверки правил маршрутизации:

```bash
ip route show table myppp
```

- Для проверки правил:

```bash
ip rule show
```

- Для отслеживания состояния соединений можно использовать `conntrack` или `iptables -L -t mangle`.

### Финальная проверка

После настройки, протестируйте отправку и получение писем. Убедитесь, что трафик правильно маркируется и возвращается через ожидаемый интерфейс. Если возникнут проблемы, проверьте логи iptables, а также используйте `tcpdump`, чтобы увидеть, проходят ли пакеты ожидаемым образом.

### Заключение

Это базовый подход к настройке policy-based routing в Linux для вашей ситуации. Если у вас возникнут какие-либо трудности, смело делитесь конфигурациями и выводом команд для более детальной диагностики. Успехов в настройке вашей сети!
По поводу этого лучше всего начать с LARTC HOWTO . 

Если кратко, маршрутищация в iproute2 устроена так. Есть несколько таблиц маршрутизации, из которых 3 есть всегда (local, main, default), но можно создать ещё. По правилам (команда ip rule) перебираются таблицы, подходящие под условия, в соответствии с приоритетами (preference, первое число в выводе команды). И в каждой таблице есть свои маршруты. Таблицу local изменять нельзя и перед ней ничего маршрутизировать нельзя (это можно обойти через nat в PREROUTING, но это уже другой вопрос).

Самый простой вариант - это source routing. Впервые мне это понадобилось, когда я подключил дома второго провайдера с внешним IP, и мне потребовалось отвечать с обоих внешних адресов со всего интернета. Делается так:

1. В /etc/iproute/rt_tables описываем псевдонимы для новых таблиц (необязательно - можно использовать числовые идентификаторы - но так удобнее). Например, 10 - isp1, 20 - isp2.

2. Задаём правила, которые приведут к выбору таблицы в зависимости от source address:

ip rule add pref 10 from IP1 lookup isp1
ip rule add pref 20 from IP2 lookup isp2

3. В каждую таблицу добавим маршрут default через нужного оператора:

ip route add default via GATEWAY1 table isp1
ip route add default via GATEWAY2 table isp2

4. В таблице main (которая используется по умолчанию, если не указать таблицу в команде явно) описываем маршрут "по умолчанию" - через того оператора, через которого будет идти исходящий трафик (не ответный на входящий), в данном случае пусть будет isp1:

ip route add default via GATEWAY1

Всё это иногда можно в той или иной степени засунуть в конфиги сети (зависит от дистрибутива Linux весьма существенно), а иногда приходится делать скриптами, в том числе, возможно, вызываемыми через hook системы инициализации сети (я, например, обновлял маршрутизацию через postup-хук dhcp-клиента и из скрипта, который поднимал pptp-vpn).

В дальнейшем всё это обросло кучей других особенностей, например, ip rule fwmark по меткам, которые ставилилсиь в iptables по connmark и иногда другим условиям, но это уже следующий уровень сложности и более специфичне задачи. И LARTC HOWTO почитать всё равно рекомендую, ибо там основа основ и все гуру по нему учились.
Похожие вопросы