---
tags: [freebsd, network]
verified: 2026-09-02
---

# FreeBSD — сеть: стек, конфигурация, фильтрация и маршрутизация

## Обзор

Сетевой стек 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 это актуальный и полнофункциональный инструмент.

Просмотр всех интерфейсов:

```sh
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 — имя драйвера + номер экземпляра. Это архитектурное решение: по имени интерфейса сразу видно, какой драйвер его обслуживает.

Временная конфигурация (до перезагрузки):

```sh
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`:

```sh
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:

```sh
ifconfig_vtnet0="DHCP"
```

IPv6:

```sh
ifconfig_vtnet0_ipv6="inet6 accept_rtadv"    # автоконфигурация через RA
ifconfig_vtnet0_ipv6="inet6 2001:db8::1 prefixlen 64"  # статический адрес
ipv6_defaultrouter="2001:db8::fffe"
```

### Клонируемые интерфейсы

FreeBSD поддерживает виртуальные интерфейсы, которые создаются на лету:

```sh
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:

```sh
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)

Объединение интерфейсов для повышения пропускной способности или отказоустойчивости:

```sh
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)`:

```sh
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:

```sh
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:

```sh
# /etc/rc.conf
gateway_enable="YES"        # IPv4 forwarding
ipv6_gateway_enable="YES"   # IPv6 forwarding
```

Или в runtime через sysctl:

```sh
sysctl net.inet.ip.forwarding=1
sysctl net.inet6.ip6.forwarding=1
```

### FIB (Forward Information Base)

FreeBSD поддерживает несколько таблиц маршрутизации (multiple FIB) — аналог policy routing в Linux. Каждый процесс или jail может быть привязан к конкретному FIB:

```sh
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

```sh
# /etc/rc.conf
pf_enable="YES"
pflog_enable="YES"
```

Если за firewall'ом есть LAN и нужен NAT/forwarding:

```sh
gateway_enable="YES"
```

Управление через `pfctl(8)`:

```sh
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-сервера:

```conf
# Макросы
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

```conf
# 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 ...` продолжают работать, так что переписывать существующие конфиги не нужно.

### Логирование

```sh
pflog_enable="YES"                          # в rc.conf
pflog_logfile="/var/log/pflog"
```

Просмотр логов в реальном времени:

```sh
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.

## Диагностические инструменты

### Состояние и статистика

```sh
ifconfig vtnet0                     # состояние интерфейса, MTU, MAC, IP, счётчики
netstat -i                          # статистика по интерфейсам (пакеты, ошибки, коллизии)
netstat -s                          # статистика по протоколам (TCP, UDP, IP, ICMP)
netstat -an                         # все активные соединения и слушающие сокеты
sockstat -l                         # какие процессы слушают какие порты
sockstat -4l                        # только IPv4
```

`sockstat` — аналог `ss -tlnp` в Linux. Показывает привязку процесс → сокет → порт.

### Маршрутизация и доступность

```sh
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              # через какой интерфейс и шлюз идёт маршрут
```

### Захват трафика

```sh
tcpdump -i vtnet0 -n port 80       # захват HTTP-трафика
tcpdump -i vtnet0 -n host 10.0.0.5 # трафик конкретного хоста
tcpdump -w /tmp/capture.pcap -i vtnet0   # запись в файл для анализа в Wireshark
```

### Мониторинг в реальном времени

```sh
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:

```sh
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-параметры для серверных нагрузок (краткий обзор, детали заслуживают отдельной статьи):

```sh
# Увеличить буферы приёма/отправки
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/](https://docs.freebsd.org/en/books/handbook/network/)
- FreeBSD Handbook, Chapter 34 "Firewalls": [docs.freebsd.org/en/books/handbook/firewalls/](https://docs.freebsd.org/en/books/handbook/firewalls/)
- FreeBSD Handbook, Chapter 35 "Advanced Networking": [docs.freebsd.org/en/books/handbook/advanced-networking/](https://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/](https://freebsdfoundation.org/resource/an-introduction-to-packet-filter-pf/)
- `pf.conf(5)`: [man.freebsd.org/cgi/man.cgi?query=pf.conf&sektion=5](https://man.freebsd.org/cgi/man.cgi?query=pf.conf&sektion=5)
- `pfctl(8)`: [man.freebsd.org/cgi/man.cgi?query=pfctl&sektion=8](https://man.freebsd.org/cgi/man.cgi?query=pfctl&sektion=8)
- `ifconfig(8)`: [man.freebsd.org/cgi/man.cgi?query=ifconfig&sektion=8](https://man.freebsd.org/cgi/man.cgi?query=ifconfig&sektion=8)
- `route(8)`: [man.freebsd.org/cgi/man.cgi?query=route&sektion=8](https://man.freebsd.org/cgi/man.cgi?query=route&sektion=8)
- `netgraph(4)`: [man.freebsd.org/cgi/man.cgi?query=netgraph&sektion=4](https://man.freebsd.org/cgi/man.cgi?query=netgraph&sektion=4)

---

## Связанные заметки

- [FreeBSD — rc-система](./freebsd-rc-system.md) — где задаётся постоянная конфигурация интерфейсов
- [FreeBSD — безопасность](./freebsd-security-hardening.md) — PF как инструмент защиты от брутфорса
- [FreeBSD — Jails](./freebsd-jails.md) — сетевые модели jail: shared IP и VNET
- [Linux — сеть: стек, конфигурация, firewall](./linux-networking.md) — nftables и iproute2, для сравнения с PF
- [FreeBSD — сводный cheatsheet](./freebsd-cheatsheet.md) — быстрая справка по сетевым командам
- [Обратный прокси и TLS: nginx vs Caddy](./reverse-proxy-tls.md) — PF-правила для 80/443 и терминация TLS
- [FreeBSD — bhyve: виртуализация после jails](./freebsd-bhyve.md) — мост и tap-интерфейсы на практике: сеть виртуальных машин
