Обзор
Сетевой стек FreeBSD исторически считается одной из лучших реализаций TCP/IP в open-source мире — ранние версии BSD содержали эталонную реализацию, на которой базировались многие коммерческие ОС. Это наследие определяет и сегодняшнее положение: FreeBSD активно используется в сетевом оборудовании (Juniper JunOS основан на FreeBSD), firewall-решениях (pfSense/OPNsense), CDN и высоконагруженных сетевых сервисах (Netflix).
Статья покрывает полный цикл: от конфигурации интерфейсов и маршрутизации до пакетной фильтрации через pf, с акцентом на архитектурные решения и отличия от Linux-подхода.
Конфигурация интерфейсов
ifconfig и rc.conf
В FreeBSD нет ip (iproute2) — основной инструмент конфигурации интерфейсов это ifconfig(8). В отличие от Linux, где ifconfig считается устаревшим, во FreeBSD это актуальный и полнофункциональный инструмент.
Просмотр всех интерфейсов:
ifconfig # все интерфейсы
ifconfig vtnet0 # конкретный интерфейс
ifconfig -a # то же, что и без аргументов: все интерфейсы
ifconfig -u # только поднятые; -d — только опущенные
ifconfig -C # какие клонеры интерфейсов доступны в системе
Типичные имена интерфейсов привязаны к драйверу: vtnet0 (VirtIO), em0 (Intel e1000), igb0 (Intel Gigabit), bge0 (Broadcom), re0 (Realtek), wlan0 (WiFi). В Linux используются обобщённые имена (eth0, ens3), во FreeBSD — имя драйвера + номер экземпляра. Это архитектурное решение: по имени интерфейса сразу видно, какой драйвер его обслуживает.
Временная конфигурация (до перезагрузки):
ifconfig vtnet0 inet 10.0.0.1 netmask 255.255.255.0
ifconfig vtnet0 inet 10.0.0.2/24 alias # добавить дополнительный IP (alias)
ifconfig vtnet0 up # поднять интерфейс
ifconfig vtnet0 down # опустить
Постоянная конфигурация — через /etc/rc.conf:
hostname="myserver.example.org"
ifconfig_vtnet0="inet 10.0.0.1 netmask 255.255.255.0"
ifconfig_vtnet0_alias0="inet 10.0.0.2 netmask 255.255.255.255"
defaultrouter="10.0.0.254"
Для DHCP:
ifconfig_vtnet0="DHCP"
IPv6:
ifconfig_vtnet0_ipv6="inet6 accept_rtadv" # автоконфигурация через RA
ifconfig_vtnet0_ipv6="inet6 2001:db8::1 prefixlen 64" # статический адрес
ipv6_defaultrouter="2001:db8::fffe"
Клонируемые интерфейсы
FreeBSD поддерживает виртуальные интерфейсы, которые создаются на лету:
cloned_interfaces="lo1 bridge0 vlan100"
ifconfig_vlan100="inet 10.100.0.1/24 vlan 100 vlandev vtnet0"
ifconfig_bridge0="addm vtnet0 addm vtnet1 up"
Типы клонируемых интерфейсов: lo (loopback), bridge (L2-мост), vlan (802.1Q), lagg (агрегация/LACP), gif (IP-in-IP туннель), gre (GRE-туннель), tap/tun (виртуальные интерфейсы для VPN и bhyve), epair (пара связанных интерфейсов, используется в jails с VNET), wg (WireGuard), ovpn (data-channel offload для OpenVPN). Что именно доступно в конкретной системе, показывает ifconfig -C.
WireGuard во FreeBSD целиком лежит в базе: ядерный драйвер wg(4) появился в 13.2, вместе с ним в base приехала и утилита wg(8) из wireguard-tools. Интерфейс создаётся как обычный клон (ifconfig wg0 create), ключи и пиры настраиваются через wg(8).
VLAN
VLAN в FreeBSD реализованы через клонирование интерфейсов. Конфигурация в rc.conf:
cloned_interfaces="vlan10 vlan20"
ifconfig_vlan10="inet 10.10.0.1/24 vlan 10 vlandev igb0"
ifconfig_vlan20="inet 10.20.0.1/24 vlan 20 vlandev igb0"
Физический интерфейс igb0 при этом обычно настраивается без IP (ifconfig_igb0="up"), выполняя роль trunk-порта.
LAGG (Link Aggregation)
Объединение интерфейсов для повышения пропускной способности или отказоустойчивости:
cloned_interfaces="lagg0"
ifconfig_igb0="up"
ifconfig_igb1="up"
ifconfig_lagg0="laggproto lacp laggport igb0 laggport igb1 inet 10.0.0.1/24"
Поддерживаемые протоколы: lacp (802.3ad, требует поддержки на коммутаторе), failover (active-backup), loadbalance, roundrobin, broadcast, none.
Маршрутизация
Основы
Управление таблицей маршрутизации — через route(8):
route -n get default # информация о дефолтном маршруте
netstat -rn # полная таблица маршрутизации
netstat -rn -f inet6 # только IPv6
route add -net 192.168.2.0/24 10.0.0.254 # добавить статический маршрут
route delete -net 192.168.2.0/24 # удалить
route change default 10.0.0.1 # изменить шлюз по умолчанию
Флаги в таблице маршрутизации: U (маршрут активен), G (gateway — через шлюз), H (host — маршрут к конкретному хосту), S (static, добавлен вручную), D (создан динамически по ICMP redirect), R (reject — пакеты отбрасываются как недостижимые). Флага C (клонирование маршрутов), который встречается в старых руководствах, в современном FreeBSD уже нет: RTF_CLONING и RTF_WASCLONED помечены в исходниках как неиспользуемые. Полный список букв даёт netstat(1).
Маршруты, добавленные вручную, не переживают перезагрузку. Постоянные статические маршруты — через rc.conf:
static_routes="internal dmz"
route_internal="-net 192.168.2.0/24 10.0.0.254"
route_dmz="-net 172.16.0.0/24 10.0.0.253"
IP Forwarding
По умолчанию FreeBSD не пересылает пакеты между интерфейсами. Для роутера или firewall:
# /etc/rc.conf
gateway_enable="YES" # IPv4 forwarding
ipv6_gateway_enable="YES" # IPv6 forwarding
Или в runtime через sysctl:
sysctl net.inet.ip.forwarding=1
sysctl net.inet6.ip6.forwarding=1
FIB (Forward Information Base)
FreeBSD поддерживает несколько таблиц маршрутизации (multiple FIB) — аналог policy routing в Linux. Каждый процесс или jail может быть привязан к конкретному FIB:
sysctl net.fibs=4 # число FIB; увеличить можно на ходу, уменьшить нельзя
setfib 1 route add default 10.0.1.254 # маршрут по умолчанию в FIB 1
setfib 1 ping 8.8.8.8 # использовать FIB 1 для пинга
В rc.conf для сервисов: foo_fib="1".
Пакетная фильтрация: PF
Архитектура
В FreeBSD доступны три firewall'а из коробки: PF (Packet Filter, портирован из OpenBSD), IPFW (FreeBSD-native) и IPF (IP Filter, исторический). PF — наиболее широко используемый и рекомендуемый для большинства задач.
PF — stateful пакетный фильтр с BSD-лицензией. Изначально создан для OpenBSD (2001), портирован во FreeBSD начиная с 5.3-RELEASE (2004). Текущая кодовая база FreeBSD PF основана на версии OpenBSD 4.5 с адаптациями для FreeBSD-ядра и SMP-оптимизациями. Отдельные возможности продолжают переносить из более поздних OpenBSD: в 14.0 приехали OpenBSD-семантика scrub (с глобальным set reassemble) и полноценные правила match, в 15.0 — синтаксис трансляции nat-to/rdr-to/binat-to.
PF выполняет фильтрацию, NAT и управление трафиком (через ALTQ или dummynet) из единого конфигурационного файла. Конфигурация читается из /etc/pf.conf.
Включение PF
# /etc/rc.conf
pf_enable="YES"
pflog_enable="YES"
Если за firewall'ом есть LAN и нужен NAT/forwarding:
gateway_enable="YES"
Управление через pfctl(8):
pfctl -e # включить PF
pfctl -d # выключить PF
pfctl -f /etc/pf.conf # загрузить (перезагрузить) набор правил
pfctl -nf /etc/pf.conf # проверить синтаксис без применения
pfctl -sr # показать текущие правила фильтрации
pfctl -sn # показать правила NAT
pfctl -ss # показать таблицу состояний
pfctl -si # статистика
pfctl -sa # показать всё
pfctl -t bruteforce -T show # содержимое таблицы
pfctl -k 10.0.0.5 # убить состояния для хоста
pfctl -k label -k www # убить состояния, созданные правилом с меткой www
Структура pf.conf
Порядок секций в файле строго определён: макросы и таблицы → options → Ethernet-фильтрация → normalization → queueing → translation (NAT) → filtering; pfctl по умолчанию следит за этим порядком (отключается через set require-order). Правила фильтрации — last match wins (последнее совпавшее правило применяется), если не указано ключевое слово quick, которое прекращает обработку при совпадении.
Минимальный pf.conf для VPS-сервера:
# Макросы
ext_if = "vtnet0"
tcp_services = "{ ssh, http, https }"
# Таблицы
table <bruteforce> persist
# Нормализация
scrub in all
# Фильтрация
# По умолчанию — блокировать всё входящее, разрешить исходящее
block in all
pass out all keep state
# Разрешить loopback
pass quick on lo0 all
# Защита от спуфинга
antispoof quick for $ext_if
# Разрешить входящие TCP-сервисы
pass in on $ext_if proto tcp to port $tcp_services keep state
# Защита SSH от брутфорса
pass in on $ext_if proto tcp to port ssh \
flags S/SA keep state \
(max-src-conn 5, max-src-conn-rate 3/30, \
overload <bruteforce> flush global)
block quick from <bruteforce>
# Разрешить ICMP (ping)
pass in on $ext_if inet proto icmp icmp-type { echoreq, unreach }
Ключевые концепции:
keep state — отслеживать состояние соединения. PF по умолчанию stateful — ответные пакеты на разрешённое исходящее соединение автоматически пропускаются.
scrub — нормализация пакетов: пересборка фрагментов, очистка аномальных флагов. Защита от ряда атак, связанных с фрагментацией и неоднозначной интерпретацией пакетов.
antispoof — генерирует правила, блокирующие пакеты с подменённым source-адресом.
table — именованные структуры для хранения наборов IP-адресов. Эффективно обновляются в runtime без перезагрузки правил: pfctl -t bruteforce -T add 10.0.0.5.
overload — механизм автоматического добавления в таблицу адресов, превысивших лимиты соединений. В примере выше — не более 5 одновременных соединений и 3 новых за 30 секунд на один source IP.
NAT
# NAT для внутренней сети через внешний интерфейс
nat on $ext_if from 192.168.1.0/24 to any -> ($ext_if)
# Проброс порта
rdr on $ext_if proto tcp to port 80 -> 192.168.1.10
# То же самое в OpenBSD-синтаксисе (FreeBSD 15.0+) — вместо двух правил выше
pass out on $ext_if from 192.168.1.0/24 to any nat-to ($ext_if)
match in on $ext_if proto tcp to port 80 rdr-to 192.168.1.10
Скобки вокруг ($ext_if) означают: использовать текущий IP интерфейса (важно для DHCP, где IP может меняться).
С FreeBSD 15.0 pf понимает трансляцию в OpenBSD-стиле: nat-to, rdr-to и binat-to записываются прямо в правилах pass и match, так что отдельная секция трансляции перестаёт быть обязательной. Старые правила nat on ... и rdr on ... продолжают работать, так что переписывать существующие конфиги не нужно.
Логирование
pflog_enable="YES" # в rc.conf
pflog_logfile="/var/log/pflog"
Просмотр логов в реальном времени:
tcpdump -n -e -ttt -i pflog0 # live
tcpdump -n -e -ttt -r /var/log/pflog # из файла
Для мониторинга активных соединений — pftop (из пакетов: pkg install pftop).
PF vs IPFW
PF — портирован из OpenBSD, декларативный синтаксис, last-match (или quick). Сильнее в stateful-фильтрации, антиспуфинге, таблицах. Рекомендован для firewall/NAT-сценариев.
IPFW — native FreeBSD, императивный синтаксис, first-match, dummynet для traffic shaping. Сильнее в интеграции с FreeBSD-специфичными возможностями (fwd, divert, netgraph). Часто выбирается для traffic shaping и pipe-based QoS.
Шейпинг больше не разводит их по разные стороны. ALTQ исторически ближе к PF, но во FreeBSD его нет ни в GENERIC, ни в виде модуля — ради очередей ALTQ придётся пересобирать ядро. Зато PF умеет отправлять трафик в пайпы и очереди dummynet ключевыми словами dnpipe и dnqueue, а сами пайпы создаются через dnctl(8) — тот же механизм, что у IPFW.
Для типичного серверного firewall'а PF — более удобный выбор. IPFW предпочтителен для сложных сценариев traffic engineering.
Диагностические инструменты
Состояние и статистика
ifconfig vtnet0 # состояние интерфейса, MTU, MAC, IP, счётчики
netstat -i # статистика по интерфейсам (пакеты, ошибки, коллизии)
netstat -s # статистика по протоколам (TCP, UDP, IP, ICMP)
netstat -an # все активные соединения и слушающие сокеты
sockstat -l # какие процессы слушают какие порты
sockstat -4l # только IPv4
sockstat — аналог ss -tlnp в Linux. Показывает привязку процесс → сокет → порт.
Маршрутизация и доступность
ping -c 3 10.0.0.254 # базовая проверка доступности
traceroute 8.8.8.8 # трассировка маршрута
traceroute6 2001:4860:4860::8888 # IPv6
arp -a # ARP-таблица
ndp -a # NDP-таблица (IPv6-аналог ARP)
route -n get 10.0.0.0 # через какой интерфейс и шлюз идёт маршрут
Захват трафика
tcpdump -i vtnet0 -n port 80 # захват HTTP-трафика
tcpdump -i vtnet0 -n host 10.0.0.5 # трафик конкретного хоста
tcpdump -w /tmp/capture.pcap -i vtnet0 # запись в файл для анализа в Wireshark
Мониторинг в реальном времени
systat -ifstat 1 # пропускная способность интерфейсов (обновление 1 сек)
systat -netstat # активные соединения
netstat -w 1 # статистика пакетов с интервалом 1 сек
systat — интерактивный curses-монитор из base system. Поддерживает режимы: ifstat (сеть), iostat (I/O), vmstat (VM), tcp, ip.
DNS-резолвер
Конфигурация DNS-резолвера — /etc/resolv.conf. В FreeBSD есть local-unbound — кэширующий DNS-резолвер из base system, интегрированный с DNSSEC:
local_unbound_enable="YES" # в rc.conf
При включении local-unbound /etc/resolv.conf управляется автоматически через resolvconf(8). Upstream DNS-серверы настраиваются в /etc/resolvconf.conf.
Netgraph
Netgraph — уникальная для FreeBSD подсистема графового моделирования сетевых операций. Позволяет строить произвольные графы из модульных узлов обработки пакетов. Каждый узел (node) выполняет одну функцию (Ethernet-фрейминг, PPP, шифрование, bridging), узлы соединяются рёбрами (hooks), образуя pipeline обработки.
Это механизм низкого уровня, не для повседневного администрирования. Но он лежит в основе ряда возможностей: ng_bridge (kernel-level bridging), ng_nat (in-kernel NAT), ng_ipfw (интеграция с IPFW), PPPoE. Для большинства задач достаточно высокоуровневых инструментов — но полезно знать, что netgraph существует и является одной из архитектурных особенностей FreeBSD.
Тюнинг сетевого стека
Ключевые sysctl-параметры для серверных нагрузок (краткий обзор, детали заслуживают отдельной статьи):
# Увеличить буферы приёма/отправки
sysctl net.inet.tcp.recvspace=65536
sysctl net.inet.tcp.sendspace=65536
# Размер очереди backlog для входящих соединений
sysctl kern.ipc.somaxconn=4096
# Алгоритм борьбы с перегрузкой: с FreeBSD 14.0 по умолчанию cubic, до этого был newreno
sysctl net.inet.tcp.cc.available # какие алгоритмы загружены
sysctl net.inet.tcp.cc.algorithm=cubic
# RACK и BBR — не алгоритмы congestion control, а альтернативные стеки TCP
# (модули tcp_rack и tcp_bbr), выбираются отдельным sysctl
sysctl net.inet.tcp.functions_default=rack
# Ускорить освобождение TIME_WAIT сокетов
sysctl net.inet.tcp.fast_finwait2_recycle=1
Для высоконагруженных сценариев (10GbE+): отключение net.inet.tcp.delayed_ack, настройка net.isr.maxthreads, привязка прерываний к CPU (cpuset), RSS (Receive Side Scaling).
Отличия от Linux-сетевого стека
Нет ip (iproute2) — ifconfig, route, arp являются основными инструментами и не deprecated. При этом сам протокол netlink в ядре есть: netlink(4) появился в FreeBSD 13.2, а в 14.0 включён по умолчанию, и часть утилит конфигурации сети переведена на него. Изменилась внутренняя механика, а не пользовательский интерфейс — команды остались BSD-шными.
Нет iptables/nftables — вместо них PF, IPFW, IPF. PF ближе всего по модели к nftables.
Нет network namespaces — вместо них VNET jails (виртуализация сетевого стека на уровне jail). Каждый VNET jail получает полную копию сетевого стека с собственными интерфейсами, таблицей маршрутизации и firewall-правилами.
Нет NetworkManager/systemd-networkd — вся конфигурация через rc.conf + ifconfig.
Имена интерфейсов — по драйверу (vtnet0, igb0), а не обобщённые (eth0, ens3).
Multiple routing tables — через FIB (аналог policy routing / VRF в Linux), но с другой моделью: в FreeBSD FIB привязывается к процессу, а не к правилу маршрутизации.
Источники
- FreeBSD Handbook, Chapter 7 "Network": docs.freebsd.org/en/books/handbook/network/
- FreeBSD Handbook, Chapter 34 "Firewalls": docs.freebsd.org/en/books/handbook/firewalls/
- FreeBSD Handbook, Chapter 35 "Advanced Networking": docs.freebsd.org/en/books/handbook/advanced-networking/
- An Introduction to Packet Filter (PF), FreeBSD Foundation: freebsdfoundation.org/resource/an-introduction-to-packet-filter-pf/
pf.conf(5): man.freebsd.org/cgi/man.cgi?query=pf.conf&sektion=5pfctl(8): man.freebsd.org/cgi/man.cgi?query=pfctl&sektion=8ifconfig(8): man.freebsd.org/cgi/man.cgi?query=ifconfig&sektion=8route(8): man.freebsd.org/cgi/man.cgi?query=route&sektion=8netgraph(4): man.freebsd.org/cgi/man.cgi?query=netgraph&sektion=4
Связанные заметки
- FreeBSD — rc-система — где задаётся постоянная конфигурация интерфейсов
- FreeBSD — безопасность — PF как инструмент защиты от брутфорса
- FreeBSD — Jails — сетевые модели jail: shared IP и VNET
- Linux — сеть: стек, конфигурация, firewall — nftables и iproute2, для сравнения с PF
- FreeBSD — сводный cheatsheet — быстрая справка по сетевым командам
- Обратный прокси и TLS: nginx vs Caddy — PF-правила для 80/443 и терминация TLS
- FreeBSD — bhyve: виртуализация после jails — мост и tap-интерфейсы на практике: сеть виртуальных машин
Из библиотеки института уносят только знания. Читателей здесь не считают: посещение не регистрируется, отметок в издании не остаётся, счётчиков нет ни у одного издания фонда.
Издание пополняется и пересверяется. Текст доступен на условиях CC BY-SA 4.0 — унесённое можно передавать дальше на тех же условиях.