0

Multirouting в FreeBSD

Настройка multirouting в FreeBSD.

На FreeBSD, выступающей в качестве шлюза, помимо всего прочего имеется интерфейс re1 (192.168.203.14/26) и интерфейс re3 (192.168.91.4/24). Оба эти интерфейса имеют доступ к сети 192.168.91.0/24, но у каждого интерфейса эта сеть своя, т.е. это две сети в разном VRF. Необходимо организовать доступ к этим сетям так, что бы каждый интерфейс видел свою сеть.

Реализация

На FreeBSD это можно реализвать с помощью утилиты setfib (доступна с версии FreeBSD7). Для того, что бы реализовать поддержку multirouting, нужно пересобрать ядро с «options ROUTETABLES=2». На данный момент максимально поддерживается до 16 независимых таблиц маршрутизации, поэтому есть смысл подумать про запас.

FIB — forwarding information base или forwarding table, проще говоря таблица маршрутизации.

Все маршруты, которые задавались командой
# route add ...
попадают в fib 0 (по-умолчанию).

Для того, чтобы прописать маршрут в другую таблицу необходимо выполнить
# setfib 1 route add

У меня имеется 2 интерфейса, с маршрутами которых надо разобраться:

re1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
    ether 52:54:00:66:9d:3d
    inet 192.168.203.14 netmask 0xfffffff0 broadcast 192.168.203.15
    media: Ethernet autoselect (100baseTX )
    status: active
re3: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=9b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM>
    ether 52:54:00:af:76:12
    inet 192.168.91.4 netmask 0xffffff00 broadcast 192.168.91.255
    media: Ethernet autoselect (100baseTX )
    status: active

Проверяю таблицы маршрутизации. Таблица большая, а меня интересует только то, что касается сети 192.168.91.0/24 и сам интерфейс.
# netstat -rn

Routing tables
 
Internet:
Destination		Gateway			Flags	Refs	Use	Netif Expire
...
192.168.91.4		lo0			UHS		0	0	lo0
192.168.91.0/24		52:54:00:af:76:12	US		0	0	re3
...

Теперь проверяю fib 1 маршруты
# setfib 1 netstat -rn

В нем по-умолчанию описаны все интерфейсы:

Routing tables
 
Internet:
Destination		Gateway		Flags	Refs	Use	Netif Expire
127.0.0.1		link#7		UH		0	0	lo0
192.168.0.0/16		192.168.203.1	UGS		0	3	re1
192.168.91.0/24		link#5		U		0	20	re3
192.168.203.0/28	link#3		U		0	0	re1

Теперь мне надо прояснить как все должно выглядеть в идеальном случае. Итак, fib 0 должна содержать все маршруты и интерфейсы, кроме re3. fib 1 наоборот должна содержать re1 (остальные, в том числе default — по необходимости)

При создании интерфейса re3 в fib 1 создается лишний маршрут — 192.168.91.0/24 (этот диапазон у меня описан в 192.168.0.0/16). Значит при описании статических маршрутов в rc.conf его нужно будет убивать.
Это можно сделать с помощью /etc/rc.local. Согласно /etc/rc.d/local, этот файл будет обрабатываться при загрузке.

Содержание /etc/rc.local:

#!/bin/sh
setfib 1 route add 192.168.0.0/16 192.168.203.1
setfib 1 route delete 192.168.91.0/24

Теперь мне надо разобраться с входящим трафиком.
Допустим, что трафик идет с 192.168.91.2 на 192.168.203.14 через интерфейс re1 и соответственно должен уходить через этот же интерфейс. Однако, в соответствии с release-notes:

«A packet received on an interface for forwarding uses FIB #0.»

И там же сказано:

ipfw setfib fibnum
will make the matched packet use the FIB specified in fibnum. The rule processing continues at the next rule.

Значит мне в правилах ipfw надо прописать:

${fwcmd} add 25 setfib 1 ip from { 192.168.0.0/16 } to 192.168.203.14 in recv re1

Эта запись говорит о том, что пакеты, которые пришли из сети 192.168.0.0/16 на адрес 192.168.203.14 через интерфейс re1 должны использовать fib1 По идее с исходящими пакетами нужно делать тоже самое, однако я не до конца вкурил каким образом это работает. Например udp пакеты от ntp сервера с адреса 192.168.203.14 на адрес 192.168.91.2 уходили через re3, а должны через re1. Помогла следующая запись, но нужно это сделать через setfib, иначе при изменении шлюза придется прописывать его и в маршрутах и в правилах ipfw. А это не правильно.

${fwcmd} add 3013 fwd 192.168.203.1 ip from 192.168.203.14 to 192.168.0.0/16

Итого

Добавить в ядро поддержку multirouting, прописав «options ROUTETABLES=2»
Внести все необходимые записи в таблицы маршрутизации с помощью «setfib 0 route add …» и «setfib 1 route add»
Для того, что бы изменения вступали в силу при перезагрузке можно использовать «/etc/rc.local»
В правила firewall внести изменения для привязки пакетов, попадающих под условие к определенной fib

Проверка

Фокус заключается в том, что теперь ping 192.168.91.2 может идти либо через re1, либо через re3:

# setfib 0 ping 192.168.91.2
пойдет через таблицу маршрутизации по умолчанию (0), и соответственно через интерфейс re3

# setfib 1 ping 192.168.91.2
пойдет через первую таблицу маршрутизации, и соответственно через интерфейс re1

# tcpdump -i [interface] icmp

Покажет как бегают пакеты
для того чтобы не набирать каждый раз
# setfib 1 telnet [host]
в /etc/profile добавляю новые alias

t() {
setfib 1 telnet $@
}
p() {
setfib 1 ping $@
}

Проверяю, что команды p и t работают как надо

sshd

Встала проблема в организации доступа по ssh через таблицу маршрутизации, отличной от 0 (по-умолчанию).
Попытка заставить работать это дело через ipfw с указанием setfib 1 на различные варианты пакетов ожидаемого результата не принесло. (возможно, плохо курил, ибо по идее это должно решаться именно там)
Решение заключается в том, что я запускаю два sshd демона на разных интерфейсах. Создаю два конфигурационных файла, например sshd_config, sshd_config_fib1, для sshd в одном указываю

ListenAddress [ip1]

Во втором

ListenAddress [ip2]

Первый демон будет запускаться по /etc/rc.d/sshd, а второй прописываю в rc.local

setfib 1 /usr/sbin/sshd -f /etc/ssh/sshd_config_fib1

в итоге получаю два сокета
root sshd 21183 3 tcp4 [ip1]:22 *:*
root sshd 14733 3 tcp4 [ip2]:22 *:*

каждый из них висит использую свою таблицу маршрутизации.

Alexey Egorychev

Alexey Egorychev

FreeBSD and Linux sysadmin. Know many systems like mailsystems, DB, WWW stack. Automation with salt, ansible. Monitoring with nagios, zabbix.