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

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