FreeBSD policy based routing или 2 провайдера.

К сожалению, даже в текущем 2022 году, особенно ничего не изменилось в лучшую сторону для FreeBSD, хотя, привезли nat global и setfib. Подробнее об этом можно прочитать в документации. Но, даже там, не будет полной информации о том, как это на самом деле работает. Как бы не было печально, но до сих пор BSD не имеет метрик маршрутизации для определения таблицы. Задача довольно распространенная, есть 2 провайдера, необходимо выпустить сети через разных провайдеров или дать доступ к ресурсам сети через разных провайдеров. Такое встречается довольно часто. Возможно, найдется читатель который сможет подсказать решение тех нюансов которые будут затронуты в этой статье. И так:

Для начала, нужно понимать что все маршруты которые проходят через какой либо интерфейс будут идти через шлюз по-умолчанию. Так называемый default gateway. Пусть у нас будет провайдер ISP1 который выдал нам белый адрес 1.1.1.1 со шлюзом 1.1.1.254, а так же второй ISP2 который выдал адрес 2.2.2.2 и шлюз 2.2.2.254. Обычно в файле /etc/rc.conf указана строка default_gateway=»» в которой содержиться шлюз по-умолчанию для всех маршрутов. Но тогда, как быть с трафиком от второго провайдера? Вот тут нам на помощь и приходят setfib, мы должны убрать default_gateway, так как каждый провайдер, должен ходить через свой шлюз. Скажем, у нас есть локальная сеть 192.168.0.1/24, мы хотим чтобы клиенты локальной сети выходили в сеть через оба провайдера. Приводим наш /etc/rc.conf к такому виду, отредактировав нужные строки:

ifconfig_vmx0="inet 1.1.1.1 netmask 255.255.255.0 fib 0"
ifconfig_vmx1="inet 2.2.2.2 netmask 255.255.255.0 fib 1"
ifconfig_vmx2="inet 192.168.0.1 netmask 255.255.255.0"

static_routes="isp1 isp2"
route_isp1="-fib 0 default 1.1.1.254"
route_isp2="-fib 1 default 2.2.2.254"

gateway_enable="YES"

Таким образом, мы говорим что нам необходимо разделить трафик на 2 канала и для каждого канала должен быть свой маршрут по-умолчанию, после перезагрузки, можно проверить маршруты, следующим образом:

# setfib 0 netstat -r
Routing tables

Internet:
Destination        Gateway            Flags     Netif Expire
default            1.1.1.254          UGS        vmx0
192.168.0.0/24     link#3             U          vmx2
192.168.0.1        link#3             UHS         lo0
1.1.1.0/24         link#1             U          vmx0
1.1.1.1            link#1             UHS         lo0
localhost          link#4             UH          lo0

# setfib 1 netstat -r
Routing tables

Internet:
Destination        Gateway            Flags     Netif Expire
default            2.2.2.254          UGS        vmx1
192.168.0.0/24     link#3             U          vmx2
192.168.0.1        link#3             UHS         lo0
2.2.2.0/24         link#1             U          vmx0
2.2.2.2            link#1             UHS         lo0
localhost          link#4             UH          lo0

Теперь у нас верные маршруты, но, если мы выполним команду netstat -r без указания канала, то мы получим в ответ тоже самое что было бы при выполнении команды setfib 0 netstat -r, то есть первая таблица всегда будет 0. Далее, нам необходимо обеспечить доступность сервера с обоих адресов, для этого нам потребуется ipfw и его модули. Добавляем следующие модули в загрузку, редактируем файл /boot/loader.conf

# nano /boot/loader.conf

ipfw_load="YES"
ipfw_nat_load="YES"
net.fibs=2

Таким образом мы подключаем firewall для управления трафиком, nat и говорим что в системе будет более 1 таблицы маршрутизации. После добавления этих строк необходимо разрешить загрузку правил фаервола в /etc/rc.conf а так же создать или отредактировать файл /etc/rc.firewall

# nano /etc/rc.conf

firewall_enable="YES"
firewall_script="/etc/rc.firewall"
firewall_logging="YES"

Теперь создаем список правил (я дополнил его комментариями, что бы было понятно что мы делаем):

# nano /etc/rc.firewall

#!/bin/sh

fwcmd="/sbin/ipfw -q"

${fwcmd} -f flush
${fwcmd} disable one_pass

# Разрешаем основной канал и все что находиться в первой таблице маршрутизации
${fwcmd} add setfib 0 all from any to any in via vmx2

# Направляем пакеты первого канала именно в его шлюз.
${fwcmd} add fwd 1.1.1.254 all from 1.1.1.1 to not 192.168.0.0/24

# Включаем NAT и разрешаем выходить в сеть всей локальной сети кроме одного адреса
# выделенный локальный адрес будет выходить через второго провайдера.
${fwcmd} nat 1 config if vmx0
${fwcmd} add nat 1 all from 192.168.0.0/24 to any fib 0 out via vmx0
${fwcmd} add nat 1 all from any to 1.1.1.1 fib 0 in via vmx0
${fwcmd} add allow all from not 192.168.0.2/32 to any via vmx2

# Те же действия производим со вторым каналом
${fwcmd} add setfib 1 all from any to any in via vmx2
${fwcmd} add fwd 2.2.2.254 all from 2.2.2.2 to not 192.168.0.0/24
${fwcmd} nat 2 config if vmx1
${fwcmd} add nat 2 all from 192.168.0.2/32 to any fib 1 out via vmx1
${fwcmd} add nat 2 all from any to 2.2.2.2 fib 1 in via vmx1
${fwcmd} add allow all from any to any via vmx2

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


${fwcmd} add setfib 0 all from any to any in via vmx2
${fwcmd} add fwd 1.1.1.254 all from 1.1.1.1 to not 192.168.0.0/24
${fwcmd} nat 1 config if vmx0 redirect_port tcp 192.168.0.5:80 80
${fwcmd} add nat 1 all from 192.168.0.0/24 to any fib 0 out via vmx0
${fwcmd} add nat 1 all from any to 1.1.1.1 fib 0 in via vmx0
${fwcmd} add allow all from not 192.168.0.2/32 to any via vmx2

${fwcmd} add setfib 1 all from any to any in via vmx2
${fwcmd} add fwd 2.2.2.254 all from 2.2.2.2 to not 192.168.0.0/24
${fwcmd} nat 2 config if vmx1 redirect_port tcp 192.168.0.5:80 80
${fwcmd} add nat 2 all from 192.168.0.2/32 to any fib 1 out via vmx1
${fwcmd} add nat 2 all from any to 2.2.2.2 fib 1 in via vmx1
${fwcmd} add allow all from any to any via vmx2

Вы так-же можете выпускать определенных клиентов с определенных внешних адресов создавая таблицы для удобства, чтобы не прописывать адреса непосредственно в правилах.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *