Что это
Когда пакет приходит на интерфейс A, а его destination не для нас - ядро смотрит routing-table и решает: переслать через B или дропнуть. Решение «пересылать чужой трафик» по умолчанию выключено, потому что обычный хост - не роутер.
Включается одним sysctl:
# На лету (до ребута)
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 не сработает: пакеты в обратку не пройдут
- VPN-сервер - клиенты в туннеле должны попасть в локальную сеть и наоборот
- Контейнерные сети - Docker/k8s включают forwarding на хосте
- Network namespaces - между netns пакеты идут через kernel, нужен forwarding
Per-interface vs global
Кроме глобального net.ipv4.ip_forward есть и на каждый интерфейс:
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 = действует только для этого интерфейса
Точечно включить только для одной пары:
sudo sysctl -w net.ipv4.conf.eth0.forwarding=1
sudo sysctl -w net.ipv4.conf.eth1.forwarding=1
Что ещё нужно
Сам по себе ip_forward=1 - только разрешение. Чтобы пакеты реально
ходили в обе стороны, нужно:
- Маршруты на нашей машине ко всем подсетям, между которыми передаём (или default route)
- Возвратные маршруты на хостах - иначе ответы не вернутся
- NAT (nat), если внутренние IP не маршрутизируемые в большей сети
- Файрвол не должен дропать FORWARD-цепочку (по умолчанию nftables/iptables часто блокирует FORWARD)
Минимальный пример - двух-интерфейсный роутер:
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'ами часто отключают:
sudo sysctl -w net.ipv4.conf.all.rp_filter=0
Дебаг: пакеты ушли но не пришли
Когда «forwarding включён, маршруты есть, NAT настроен, но не работает»:
tcpdumpна каждом из интерфейсов - видим ли мы пакет?nft list ruleset/iptables -L FORWARD- не дропает ли FORWARD?ip route get <dst>- какой маршрут выберется?cat /proc/sys/net/ipv4/conf/<iface>/forwarding- на конкретном интерфейсе включено?conntrack -L- есть ли запись для этого соединения?
В контейнере
В Docker контейнерах /proc/sys по умолчанию read-only. Чтобы менять
forwarding изнутри контейнера, нужен --cap-add=NET_ADMIN + SYS_ADMIN
и remount /proc/sys rw. Обычно лучше включать на хосте.