# IP forwarding - превратить хост в роутер _Сеть: L2 / L3 · LinuxLab Knowledge Base_ **TL;DR:** Linux по умолчанию НЕ пересылает пакеты между интерфейсами. Включается через `sysctl net.ipv4.ip_forward=1`. Без этого не работают NAT, VPN-роутер, любой forwarding. ## Что это Когда пакет приходит на интерфейс A, а его destination не для нас - ядро смотрит [routing-table](/kb/routing-table.md) и решает: переслать через B или дропнуть. Решение «пересылать чужой трафик» по умолчанию **выключено**, потому что обычный хост - не роутер. Включается одним sysctl: ```bash # На лету (до ребута) sudo sysctl -w net.ipv4.ip_forward=1 # Прямой путь (то же самое) echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward # Постоянно (после ребута тоже работает) echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-router.conf sudo sysctl --system ``` Аналогично для IPv6: `net.ipv6.conf.all.forwarding`. ## Когда нужен - **Своя машина как роутер** - несколько интерфейсов, надо передавать пакеты между подсетями - **NAT/masquerade** - без forwarding'а [nat](/kb/nat.md) не сработает: пакеты в обратку не пройдут - **VPN-сервер** - клиенты в туннеле должны попасть в локальную сеть и наоборот - **Контейнерные сети** - Docker/k8s включают forwarding на хосте - **Network namespaces** - между netns пакеты идут через kernel, нужен forwarding ## Per-interface vs global Кроме глобального `net.ipv4.ip_forward` есть и **на каждый интерфейс**: ```bash cat /proc/sys/net/ipv4/conf/eth0/forwarding cat /proc/sys/net/ipv4/conf/all/forwarding cat /proc/sys/net/ipv4/conf/default/forwarding ``` - `all/forwarding` совпадает с глобальным - `default/forwarding` - для НОВЫХ интерфейсов - per-iface = действует только для этого интерфейса Точечно включить только для одной пары: ```bash sudo sysctl -w net.ipv4.conf.eth0.forwarding=1 sudo sysctl -w net.ipv4.conf.eth1.forwarding=1 ``` ## Что ещё нужно Сам по себе `ip_forward=1` - только разрешение. Чтобы пакеты реально ходили в обе стороны, нужно: 1. **Маршруты** на нашей машине ко всем подсетям, между которыми передаём (или default route) 2. **Возвратные маршруты** на хостах - иначе ответы не вернутся 3. **NAT** ([nat](/kb/nat.md)), если внутренние IP не маршрутизируемые в большей сети 4. **Файрвол** не должен дропать FORWARD-цепочку (по умолчанию nftables/iptables часто блокирует FORWARD) Минимальный пример - двух-интерфейсный роутер: ```bash sudo sysctl -w net.ipv4.ip_forward=1 # Если есть NAT-сценарий (приватная сеть → публичная): sudo nft 'add table inet nat' sudo nft 'add chain inet nat postrouting { type nat hook postrouting priority 100; }' sudo nft 'add rule inet nat postrouting oifname "eth1" masquerade' # Разрешить FORWARD в файрволе (пример простой policy) sudo nft 'add chain inet filter forward { type filter hook forward priority 0; policy accept; }' ``` ## Reverse path filtering Связанная sysctl - `net.ipv4.conf.*.rp_filter`. Когда **включён**, ядро дропает входящие пакеты, если ответ на них **не пошёл бы** обратно через тот же интерфейс. Защита от spoofing'а, но ломает асимметричный routing. На роутере с несколькими uplink'ами часто отключают: ```bash sudo sysctl -w net.ipv4.conf.all.rp_filter=0 ``` ## Дебаг: пакеты ушли но не пришли Когда «forwarding включён, маршруты есть, NAT настроен, но не работает»: 1. `tcpdump` на каждом из интерфейсов - видим ли мы пакет? 2. `nft list ruleset` / `iptables -L FORWARD` - не дропает ли FORWARD? 3. `ip route get ` - какой маршрут выберется? 4. `cat /proc/sys/net/ipv4/conf//forwarding` - на конкретном интерфейсе включено? 5. `conntrack -L` - есть ли запись для этого соединения? ## В контейнере В Docker контейнерах `/proc/sys` по умолчанию read-only. Чтобы менять forwarding изнутри контейнера, нужен `--cap-add=NET_ADMIN` + `SYS_ADMIN` и remount `/proc/sys` rw. Обычно лучше включать на хосте. ## Команды ```bash sudo sysctl -w net.ipv4.ip_forward=1 ``` Включить IP-форвардинг до ребута ```bash sysctl net.ipv4.ip_forward ``` Проверить текущее состояние (0 = выкл, 1 = вкл) ```bash echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-router.conf ``` Постоянная фиксация на следующие ребуты ```bash ip route get 10.20.0.5 ``` Куда уйдёт пакет к этому адресу - главный дебаг forwarding'а ```bash sudo sysctl -w net.ipv4.conf.all.rp_filter=0 ``` Отключить reverse path filter - нужно при асимметричном routing'е ## См. также - [Routing table](/kb/routing-table.md) - [NAT и masquerade](/kb/nat.md) - [sysctl - крутилки ядра](/kb/cmd-sysctl.md) - [iptables - правила netfilter (legacy)](/kb/cmd-iptables.md)