Freebsd маршрут по умолчанию. Динамическая маршрутизация в FreeBSD, BIRD

Дистрибутив фрюхи часто называют самым подходящим для решения прикладных сетевых задач в локальной сети. Сегодня мы займемся решением одной из сетевых задач — настройкой шлюза на Freebsd 10 для доступа в интернет из локалки. Это простой, популярный и востребованный функционал сервера, который можно расширять дополнительными возможностями.

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

# uname -v FreeBSD 10.2-RELEASE-p8 #0 r292756M: Sat Dec 26 22:49:34 MSK 2015 root@freebsd:/usr/obj/usr/src/sys/GENERIC

На сервере установлены 2 сетевые карты:

  • hn0 — внешний интерфейс, получает интернет от провайдера, настройки по dhcp
  • hn1 локальная сеть, адрес 10.20.30.1, установлен вручную

В нашу задачу по настройке программного freebsd роутера будет входить настройка маршрутизации на сервере, установка и настройка ipfw, включение nat, настройка локального dhcp и dns сервера.

Подготовка сервера к настройке шлюза

Информацию о выданных leases dhcp сервера dnsmasq можно посмотреть в файле /var/db/dnsmasq.leases .

Анализ сетевой активности в freebsd с помощью iftop

Иногда хочется посмотреть, что происходит на роутере и кто использует интернет в данный момент. По-умолчанию, в системе нет готового средства для получения этой информации. На помощь нам придет простая программа iftop, которая позволяет в режиме реального времени посмотреть активность на сетевом интерфейсе.

Устанавливаем iftop на настроенный Freebsd шлюз:

# pkg install iftop

Запускаем iftop с указанием интерфейса и отображением используемых портов:

# iftop -i hn1 -P

Видим любопытную картину — кто, куда, по какому порту и с какой скоростью лезет.

Я для примера на одном из компьютеров запустил генератор трафика интернета. Он занял почти весь канал и это стало отлично видно на роутере с помощью iftop. Конечно, эта простая утилита не решает всех вопросов по мониторингу сетевой активности, но для представления текущей картины подходит, если вам не нужно что-то большее.

Заключение

Подведем итог того, что сделали. За короткое время настроили полноценный шлюз (по сути программный роутер) на базе Freebsd 10 для обеспечения выхода в интернет клиентов за сервером. При этом обеспечили автоматическое получение настроек. Даже на скромном виртуальном сервере такой шлюз способен переварить достаточно большой траффик.

Вся настройка занимает буквально 10-15 минут. Основное время уходит на сборку ядра. Чем выше версия Freebsd, тем дольше оно собирается, несмотря на то, что скорости железа существенно возрастают.

Пройдемся по пунктам и разберемся с тем, что конкретно мы сделали:

  1. Подготовили сервер к настройке шлюза.
  2. Пересобрали ядро с необходимыми параметрами.
  3. Настроили ipfw и nat, включили маршрутизацию.
  4. Установили и настроили dnsmasq для раздачи сетевых настроек по dhcp и dns сервера.
  5. Установили iftop для простейшего анализа сетевой активности на внешнем интерфейсе.

Этого достаточно для полноценной работы шлюза на Freebsd 10. Если есть необходимость подсчета пользовательского траффика или ограничения доступа к определенным ресурсам, можно к нему.

last updated August 30, 2017 H ow do I modify or set a default route for my FreeBSD server? How do I make default route configuration persistent?

You need to use the route command on a FreeBSD to manually manipulate the network routing tables. It provides six commands as follows:
Adblock detected 😱

My website is made possible by displaying online advertisements to my visitors. I get it! Ads are annoying but they help keep this website running. It is hard to keep the site running and producing new content when so many people block ads. Please consider donating money to the nixCraft via PayPal /, or become a supporter using Patreon .

  1. add : Add a route.
  2. flush :Remove all routes.
  3. delete : Delete a specific route.
  4. change : Change aspects of a route (such as its gateway).
  5. get : Lookup and display the route for a destination.
  6. monitor : Continuously report any changes to the routing information base, routing lookup misses, or suspected network partitionings.

Task: View / Display FreeBSD Routing Table

Use the netstat command with -r option as follows:
$ netstat -r
$ netstat -rn
Sample outputs:

Routing tables Internet: Destination Gateway Flags Refs Use Netif Expire default 61.221 .xx.yy UGS 0 247 em1 10 10.10.110.5 UGS 0 50 em0 10.10.110/26 link#1 UC 0 0 em0 10.10.110.5 00:1b:0d:e6:58 :40 UHLW 2 0 em0 1145 61.221 .xx.yy/29 link#2 UC 0 0 em1 61.221 .xx.yy 00:1b:0d:e6:57 :c0 UHLW 2 0 em1 1055 61.221 .xx/24 link#2 UC 0 0 em1 127.0.0.1 127.0.0.1 UH 0 0 lo0

Routing tables Internet: Destination Gateway Flags Refs Use Netif Expire default 61.221.xx.yy UGS 0 247 em1 10 10.10.110.5 UGS 0 50 em0 10.10.110/26 link#1 UC 0 0 em0 10.10.110.5 00:1b:0d:e6:58:40 UHLW 2 0 em0 1145 61.221.xx.yy/29 link#2 UC 0 0 em1 61.221.xx.yy 00:1b:0d:e6:57:c0 UHLW 2 0 em1 1055 61.221.xx/24 link#2 UC 0 0 em1 127.0.0.1 127.0.0.1 UH 0 0 lo0

The first two line displays default routes. To just print IPv4 routing table, enter:
# netstat -4 -r -n
Sample outputs:

To just print IPv6 routing table, enter:
# netstat -6 -r -n

Task: FreeBSD Set a default route

All network packets that cannot be sent according to the previous entries of the routing table are sent through the following default gateway:
# route add default 192.168.1.254

How do I save routing information to a configuration file?

If you reboot FreeBSD box, the routing configuration will be lost i.e. the routing information will not persist. You need to edit /etc/rc.conf file to set defaultroute:
# vi /etc/rc.conf
Set default route by editing defaultrouter variable:
defaultrouter="192.168.1.254"
Save and close the file.

Рано или поздно в сети с несколькими маршрутизаторами возникает потребность в динамической маршрутизации. Что такое динамическая маршрутизация, и зачем она нужна - рассказывать не буду, ибо это основы о которых можно почитать и в Интернет, эта тема будет о программном обеспечении для обеспечения динамический маршрутизации.
Одной из самой из известных программ для обеспечения динамической маршрутизации безусловно является знаменитая quagga. cisco-style (фу мля, убогость то какая) интерфейс консоли, поддержка RIP, OSPF, BGP, ISIS,… Да, продукт известен. Но он имеет ряд своих недостатков, например:
- не поддерживает множественные таблицы маршрутизации (пародия вида table - это просто издевательство);
- под столь мной любимой FreeBSD есть ряд серьезных косяков. Например с версии 0.99.16 разломан протокол OSPF. При наличии в системе нескольких таблиц маршрутизации - квага просматривает все, из-за чего возникают неприятные косяки с ее прямым назначением;
- единственный способ из рантайма управлять квагой - это пользоваться ее консолью;
- практически отсутствующее API для разработчиков.
Под Linux она конечно работает получше, но все равно отсутствует поддержка множественных таблиц маршрутизации…

Итак, поговорим мы сегодня о таком проекте, как BIRD .
И сразу же анонс продукта с главной страницы проекта:
What do we support: - Both IPv4 and IPv6 (use --enable-ipv6 when configuring) - Multiple routing tables - BGP - RIP - OSPF - Static routes - Inter-table protocol - Command-line interface (using the `birdc" client; to get some help, just press `?") - Soft reconfiguration -- no online commands for changing the configuration in very limited ways, just edit the configuration file and issue a `configure" command or send SIGHUP and BIRD will start using the new configuration, possibly restarting protocols affected by the configuration changes Powerful language for route filtering
Недурно - «Multiple routing tables», «Inter-table protocol»?

Сразу лирическое отступление, в FreeBSD множественные таблицы маршрутизации появились с версии 7.1 аж в 2008 году, что очень поздно. Для примера, в Linux они появились аж в 1999 году. К сожалению BIRD не умеет работать с таблицами маршрутизации FreeBSD, в связи с чем пришлось его немного допиливать. Допилилось легко. Код легко читаем и прекрасно рассмотрен API.
Таким образом, мы имеем BIRD с поддержкой множественных таблиц маршрутизации в FreeBSD.

Теперь поговорим немного об такой возможности BIRD как «Inter-table protocol». Что же это такое? В BIRD существует понятие «таблица маршрутизации», нет, это не таблица маршрутизации системы, это внутренняя таблица BIRD в которой хранятся маршруты каким либо способом доставленные в BIRD. А доставить их можно так: статическое объявление маршрутов, импорт из таблицы маршрутизации системы, маршруты приехавшие по OSPF/BFP/RIP/…
Все эти маршруты живут внутри таблицы BIRD, которая и называется «таблицей маршрутизации».
Как можно объявить таблицу? Легко:
table fib0; table fib2;
Это создаст внутри BIRD две таблицы маршрутизации, «fib0» и «fib2».

Но пустые таблицы нам мало интересны, заполним их статическими маршрутами. Делается это очень легко (это примеры рабочего файла конфигурации):
protocol static { table fib0; route 10.0.0.0/8 via 10.2.2.1; route 193.33.62.0/23 via 10.2.2.1; route 91.202.20.0/22 via 10.2.2.1; route 93.186.96.0/20 via "ng0"; route 193.203.60.0/22 via "ng0"; route 78.132.128.0/17 via "ng0"; route 213.135.128.0/19 via "ng0"; route 82.179.144.0/20 via "ng0"; route 195.19.96.0/19 via "ng0"; } protocol static { table fib2; route 0.0.0.0/0 via 192.168.130.2; }
Как видно, мы населили таблицы определенными маршрутами. Причем видно, что шлюз можно задавать как IP-адрес, а можно и как интерфейс (в случае с «ng0»). Так же ничего не мешает указывать default-маршруты.

Итак, мы заселили наши таблички маршрутами. Резонный вопрос: а как из этих табличек маршруты объединить с тем, что есть в системе? Для этого существует протокол kernel, пример:
protocol kernel { table fib0; scan time 20; import none; export all; kernel table 0; } protocol kernel { table fib2; scan time 20; import none; export all; kernel table 2; }
Здесь мы привязываем fib0 к системной таблице маршрутизации 0 (это таблица по умолчанию для FreeBSD) и fib2 к системной таблице 2.
import - говорит, что мы будем импортировать из системной таблицы 0 в fib0 (в данном случае - ничего импортировать не будем), а export - указывает, что мы будем записывать из fib0 в системную таблицу маршрутизации 0 (в этом примере - мы будем записывать весь fib2 в системную таблицу маршрутизации).
Для fib2 все аналогично. Думаю здесь больше вопросов никаких не должно возникнуть.
scan time - как часто мы будем синхронизировать эти таблицы. 20 секунд. Что означает эти 20 секунд? Дело в том, что возможна ситуация когда BIRD не смог получить событие от системы об изменении системной таблицы маршрутизации. Для избежания такой ситуации таблица перечитывается раз в 20 секунд. Да, это можно отключить.

Теперь поговорим о «Inter-table protocol», что это такое, и зачем оно собственно нужно.
Пока мы остановились на том - что к системной таблице маршрутизации 0 привязывается fib0, а к таблице 2 - fib2. А вдруг нам потребуется отдать часть маршрутов из fib0 в fib2? это операция повлечет за собой не только передачу маршрутов из fib0 в fib2, но и как следствие попадание маршрутов из fib0 в системную таблицу маршрутизации 2. Достигается это так же легко, протокол pipe, пример:
protocol pipe { table fib2; peer table fib0; export none; import all; }
Таблица fib2 подключается к fib0, при этом она ничего не экспортирует в fib0, зато импортирует из fib0 все маршруты. Такой вот хитрый протокол.

Но все это было бы скучно и решалось спокойно и без BIRD, если бы не одно «но». Но существует два соседних маршрутизатора, с которыми мы обмениваемся маршрутами:) С соседями мы общаемся с помощью BGP. Пример:
protocol bgp { table fib0; local as 64602; neighbor 192.168.135.2 as 64603; export filter rfc1918_reject; import filter rfc1918_reject; } protocol bgp { table fib0; local as 64602; neighbor 192.168.135.10 as 64604; export filter rfc1918_reject; import filter rfc1918_reject; }
Итак, что это значит все? Наша AS имеет номер 64602, соседи 64603 и 64604. На каждого соседа объявляется свой протокол bgp. Каждый из этих протоколов привязан к таблице fib0 - т.е. из все маршруты пришедшие/отправленные по bgp будут записывать/отправляться в/из fib0. Думаю с этим вопросов нет. Итого, у нас таблица fib0 уже содержит как статические маршруты так и bgp.
Так же в параметрах export/import появилось изменение - filter rfc1918_reject. Как пишутся фильтры - рассмотрим ниже, пока скажу - что это фильтр запрещает экспорт/импорт маршрутов из сетей, объявленных в RFC1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).

Пример фильтра для написанного выше:
# reject rfc1918 filter filter rfc1918_reject { if net ~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+ ] then reject; else accept; }
Для написания фильтров и функций в BIRD используется свой язык описания. Синтаксис можно посмотреть в официальной документации. В данном случае, если маршрут принадлежит одной из подсетей, объявленных в квадратных скобках - то он будет отвергаться. 10.0.0.0/8+ - означает, что любой маршрут принадлежащий 10.0.0.0/8 и так же субсетям этой сети будет отвергаться.

Ну и теперь приведу полный пример файл конфигурации:
log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug }; log stderr all; # Override router ID router id 0.0.0.10; # Define another routing table table fib0; table fib2; # reject rfc1918 filter filter rfc1918_reject { if net ~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+ ] then reject; else accept; } # Turn on global debugging of all protocols debug protocols all; protocol kernel { table fib0; scan time 20; import none; export all; kernel table 0; } protocol kernel { table fib2; scan time 20; import none; export all; kernel table 2; } protocol static { table fib0; route 10.0.0.0/8 via 10.2.2.1; route 193.33.62.0/23 via 10.2.2.1; route 91.202.20.0/22 via 10.2.2.1; route 93.186.96.0/20 via "ng0"; route 193.203.60.0/22 via "ng0"; route 78.132.128.0/17 via "ng0"; route 213.135.128.0/19 via "ng0"; route 82.179.144.0/20 via "ng0"; route 195.19.96.0/19 via "ng0"; } protocol static { table fib2; route 0.0.0.0/0 via 192.168.130.2; } protocol pipe { table fib2; peer table fib0; export none; import all; } protocol bgp { table fib0; local as 64602; neighbor 192.168.135.6 as 64601; export filter rfc1918_reject; import filter rfc1918_reject; } protocol bgp { table fib0; local as 64602; neighbor 192.168.135.2 as 64603; export filter rfc1918_reject; import filter rfc1918_reject; } protocol bgp { table fib0; local as 64602; neighbor 192.168.135.10 as 64604; export filter rfc1918_reject; import filter rfc1918_reject; } # This pseudo-protocol watches all interface up/down events. protocol device { scan time 10; # Scan interfaces every 10 seconds }

Все кусочки были рассмотрены выше, только подытожу - что делает такой конфиг:
1. Создаются две таблицы маршутизации BIRD (fib0 и fib2);
2. Таблицы из п.1 привязываются к системным таблицам маршрутизации 0 и 2 соответственно;
3. Разрешается подкачка маршрутов из fib0 в fib2;
4. Таблица fib0 так же заселяется маршрутами, попавшими по bgp.

В итоге - в двух системных таблицах маршрутизации находятся общие маршруты:)

PS: Ну и на последок - что творится на текущий момент в BIRD:
mira# uname FreeBSD mira# birdc show protocols all BIRD 1.2.5 ready. name proto table state since info kernel1 Kernel fib0 up 22:01 Preference: 10 Input filter: REJECT Output filter: ACCEPT Routes: 0 imported, 13 exported, 0 preferred Route change stats: received rejected filtered ignored accepted Import updates: 0 0 0 0 0 Import withdraws: 0 0 --- 0 0 Export updates: 16 0 0 --- 16 Export withdraws: 2 --- --- --- 2 kernel2 Kernel fib2 up 22:01 Preference: 10 Input filter: REJECT Output filter: ACCEPT Routes: 0 imported, 14 exported, 0 preferred Route change stats: received rejected filtered ignored accepted Import updates: 0 0 0 0 0 Import withdraws: 0 0 --- 0 0 Export updates: 17 0 0 --- 17 Export withdraws: 2 --- --- --- 2 static1 Static fib0 up 22:01 Preference: 200 Input filter: ACCEPT Output filter: REJECT Routes: 9 imported, 0 exported, 18 preferred Route change stats: received rejected filtered ignored accepted Import updates: 9 0 0 0 9 Import withdraws: 0 0 --- 0 0 Export updates: 0 0 0 --- 0 Export withdraws: 0 --- --- --- 0 static2 Static fib2 up 22:01 Preference: 200 Input filter: ACCEPT Output filter: REJECT Routes: 1 imported, 0 exported, 1 preferred Route change stats: received rejected filtered ignored accepted Import updates: 1 0 0 0 1 Import withdraws: 0 0 --- 0 0 Export updates: 0 0 0 --- 0 Export withdraws: 0 --- --- --- 0 pipe1 Pipe fib2 up 22:01 => fib0 Preference: 70 Input filter: ACCEPT Output filter: REJECT Routes: 16 imported, 0 exported Route change stats: received rejected filtered ignored accepted Import updates: 28 0 0 9 19 Import withdraws: 3 0 --- 0 3 Export updates: 20 19 1 0 0 Export withdraws: 3 0 --- 0 0 bgp1 BGP fib0 up 22:01 Established Preference: 100 Input filter: rfc1918_reject Output filter: rfc1918_reject Routes: 5 imported, 9 exported, 6 preferred Route change stats: received rejected filtered ignored accepted Import updates: 5 0 0 0 5 Import withdraws: 0 0 --- 0 0 Export updates: 16 3 1 --- 12 Export withdraws: 2 --- --- --- 3 BGP state: Established Session: external AS4 Neighbor AS: 64601 Neighbor ID: 192.168.135.6 Neighbor address: 192.168.135.6 Nexthop address: 192.168.135.6 Source address: 192.168.135.5 Neighbor caps: refresh AS4 Hold timer: 102/180 Keepalive timer: 10/60 bgp2 BGP fib0 up 22:01 Established Preference: 100 Input filter: rfc1918_reject Output filter: rfc1918_reject Routes: 2 imported, 11 exported, 2 preferred Route change stats: received rejected filtered ignored accepted Import updates: 5 0 0 0 5 Import withdraws: 3 0 --- 0 3 Export updates: 16 4 1 --- 11 Export withdraws: 2 --- --- --- 0 BGP state: Established Session: external AS4 Neighbor AS: 64603 Neighbor ID: 0.0.0.50 Neighbor address: 192.168.135.2 Nexthop address: 192.168.135.2 Source address: 192.168.135.1 Neighbor caps: refresh AS4 Hold timer: 87/180 Keepalive timer: 45/60 bgp3 BGP fib0 start 22:01 Idle BGP Error: Bad BGP identifier Preference: 100 Input filter: rfc1918_reject Output filter: rfc1918_reject Routes: 0 imported, 0 exported, 0 preferred Route change stats: received rejected filtered ignored accepted Import updates: 0 0 0 0 0 Import withdraws: 0 0 --- 0 0 Export updates: 0 0 0 --- 0 Export withdraws: 0 --- --- --- 0 BGP state: Idle Error wait: 43/60 Last error: BGP Error: Bad BGP identifier device1 Device master up 22:01 Preference: 240 Input filter: ACCEPT Output filter: REJECT Routes: 0 imported, 0 exported, 0 preferred Route change stats: received rejected filtered ignored accepted Import updates: 0 0 0 0 0 Import withdraws: 0 0 --- 0 0 Export updates: 0 0 0 --- 0 Export withdraws: 0 --- --- --- 0