![](https://habrastorage.org/storage2/dcd/648/b7c/dcd648b7c7e3644ce3a2ea9e19348c92.jpg)
Небольшое вступление. Сегодня попросили помочь в одной дружеской сети. Имеем: небольшой ISP, достаточно распределенной структуры, некоторая часть на радиоканалах, авторизации нет, есть привязка к mac и ip адресам. На одном из направлений перестало хватать полосы радиоканала, встала необходимость поднять второй канал и перекинуть часть пользователей на него. Кажется все просто и тривиально, но адреса и все настройки у клиентов заданы статически (да дурость, но работаем с тем что дали) и необходимо чтоб сеть остались рабочей у всех абонентов, без каких-либо телодвижений с их стороны.
Вкратце структуру сети показал на блок-схеме.
![](https://habrastorage.org/storage2/247/840/1ff/2478401fffef1f4d01c70ae419dc30a3.png)
Попытки объединить каналы по LACP не увенчались успехом (радиосреда, промежуточное железо и т.п.), решено было извращаться, но поднять быстро (решение временное, через пару недель туда прийдет оптика и будет сделано по-нормальному, так что прошу коллег сетевиков сильно не пинать).
На сервере имеем: FreeBSD 9.0-RELEASE-p3 с пересобранным под свои нужды ядром, сетевая, смотрящая в сторону абонентов em0, радиоканал 1 идет по vlan2814, а радиоканал 2 по vlan2819.
Добавляем виланы
В /etc/rc.conf добавим
cloned_interfaces="vlan2814 vlan2819"
ifconfig_em0="up"
ifconfig_vlan2814="inet 172.16.1.254 netmask 255.255.255.0 vlan 2814 vlandev em0"
ifconfig_vlan2814_alias0="inet 172.16.52.254 netmask 255.255.255.0"
ifconfig_vlan2814_alias1="inet 172.16.3.254 netmask 255.255.255.0"
ifconfig_vlan2814_alias2="inet 10.55.1.1 netmask 255.255.255.0"
ifconfig_vlan2819="inet 172.16.1.254 netmask 255.255.255.0 vlan 2819 vlandev em0"
ifconfig_vlan2819_alias0="inet 172.16.52.254 netmask 255.255.255.0"
ifconfig_vlan2819_alias1="inet 172.16.3.254 netmask 255.255.255.0"
ifconfig_vlan2819_alias2="inet 10.55.1.1 netmask 255.255.255.0"
Как видим на 2х разных интерфейсах мы указываем использовать одинаковые ip адреса. Эта технология в терминах cisco зовется unnumbered, для FreeBSD я встречал такое название, как SuperVlan. Особенность работы под FreeBSD в том, что для первого поднявшегося интерфейса (в нашем случае vlan2814) все адреса смаршрутизируются автоматически и никаких дополнительных телодвижений не понадобится.
Перегружаемся.
Смотрим таблицу маршрутизации
netstat -rn
Routing tables
Internet:
Destination Gateway Flags Refs Use Netif Expire
172.16.1.0/24 link#14 U 0 17830227 vlan2814
172.16.1.254 link#14 UHS 1 0 lo0
172.16.3.0/24 link#14 U 0 2375127 vlan2814
172.16.3.254 link#14 UHS 1 0 lo0
172.16.52.0/24 link#14 U 0 231 vlan2814
172.16.52.254 link#14 UHS 1 0 lo0
10.55.1.0/24 link#14 U 0 36399 vlan2814
10.55.1.1 link#14 UHS 1 0 lo0
Смотрим поднявшиеся интерфейсы
vlan2814: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=3<RXCSUM,TXCSUM>
ether 00:1b:21:b8:хх:хх
inet 172.16.1.254 netmask 0xffffff00 broadcast 172.16.1.255
inet 172.16.52.254 netmask 0xffffff00 broadcast 172.16.52.255
inet 172.16.3.254 netmask 0xffffff00 broadcast 172.16.3.255
inet 10.55.1.1 netmask 0xffffff00 broadcast 10.55.1.255
media: Ethernet autoselect (1000baseT <full-duplex>)
status: active
vlan: 2814 parent interface: em0
vlan2819: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=3<RXCSUM,TXCSUM>
ether 00:1b:21:b8:хх:хх
inet 172.16.1.254 netmask 0xffffff00 broadcast 172.16.1.255
inet 172.16.52.254 netmask 0xffffff00 broadcast 172.16.52.255
inet 172.16.3.254 netmask 0xffffff00 broadcast 172.16.3.255
inet 10.55.1.1 netmask 0xffffff00 broadcast 10.55.1.255
media: Ethernet autoselect (1000baseT <full-duplex>)
status: active
vlan: 2819 parent interface: em0
Как мы и предполагали оба интерфейса работают на всех ip, но маршрутизация идет только через первый, как же быть с пользователями, которые пойдут через vlan2819?
И тут мы приходим к страшному костылю. Теория такая, те абоненты которые будут пытаться пойти через vlan2819 попадут в его арп-таблицу, но маршрутизироваться не будут. Пишем небольшой скрипт:
#!/bin/sh
FILE=`arp -an -ivlan2819 | grep seconds | awk '{print $2}'| sed 's/[/(,/)]//g'`
for I in $FILE
do
if [ -n "$I" ]
then
/sbin/route add $I -iface vlan2819 >/dev/null 2>&1
fi
done
Скрипт проверяет все арпы на интерфейсе vlan2819, отбирает из них только живые (incomplete не трогаем, если такие есть), парсит только список ip адресов и загоняет их в переменную FILE, затем цикл добавляет статический маршрут на каждый ip из списка и говорит маршрутизировать его через vlan2819. Скрипт добавляем в crontab на выполнение раз в минуту. В итоге при первом своем подключении пользователь подождет максимум минуту до срабатывания скрипта, после чего получит интернет.
В результате работы скрипта наша Routing tables изменилась так:
172.16.1.0/24 link#14 U 0 23476495 vlan2814
172.16.1.12 00:1b:21:b8:хх:хх UHS 0 378788 vlan2819
172.16.1.16 00:1b:21:b8:хх:хх UHS 0 223 vlan2819
172.16.1.17 00:1b:21:b8:хх:хх UHS 0 320660 vlan2819
172.16.1.18 00:1b:21:b8:хх:хх UHS 0 322459 vlan2819
{и так далее}
172.16.1.254 link#14 UHS 1 0 lo0
172.16.3.0/24 link#14 U 0 2561712 vlan2814
172.16.3.8 00:1b:21:b8:хх:хх UHS 0 22770 vlan2819
172.16.3.13 00:1b:21:b8:хх:хх UHS 0 60442 vlan2819
{и так далее}
172.16.3.254 link#14 UHS 1 0 lo0
10.55.1.0/24 link#14 U 0 55592 vlan2814
10.55.1.1 link#14 UHS 1 0 lo0
{и так далее}
10.55.1.102 00:1b:21:b8:хх:хх UHS 0 43619 vlan2819
10.55.1.103 00:1b:21:b8:хх:хх UHS 0 18 vlan2819
Еще раз повторяюсь — решение временное, годится только если абонент получает каждый раз один и тот же IP (в принципе можно расширить скрипт и добавить проверки в каком из интерфейсов светится мак абонента и если интерфейс сменился перестраивать маршрут). Заметкой хотел показать, что использовать один и тот-же ip адрес на нескольких интерфейсах (не обязательно 2) вполне реально и в некоторых случаях может быть оправданно, например при нехватке белых адресов и большом количестве интерфейсов выдавать в интерфейс только необходимый 1 адрес, а не переводить 4 штуки маской /30