linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Simulator
  • Knowledge base
  • Interview prep
Index
Categories
All entries
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
home/linux/kb/Networking: L2 / L3/ip-forwarding

kb/network-l2-l3 ── Networking: L2 / L3 ── intermediate

IP Forwarding: Turn a Host into a Router

Linux does not forward packets between interfaces by default. Enable it with `sysctl net.ipv4.ip_forward=1`. Without this, NAT, VPN routing, and any forwarding will not work.

view as markdownaka: ip-forward, ipv4-forward, routing-host

What it is

When a packet arrives on interface A and its destination is not the local host, the kernel consults the routing-table and decides: forward it through B or drop it. The decision to forward traffic destined for others is off by default, because an ordinary host is not a router.

You enable it with one sysctl:

bash
# Runtime only (lost on reboot)
sudo sysctl -w net.ipv4.ip_forward=1
# Direct path (same effect)
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# Persistent (survives reboot)
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-router.conf
sudo sysctl --system

For IPv6 the equivalent is: net.ipv6.conf.all.forwarding.

When you need it

  • Your machine as a router - multiple interfaces, need to pass packets between subnets
  • NAT/masquerade - without forwarding, nat will not work: return packets cannot pass through
  • VPN server - tunnel clients must reach the local network and vice versa
  • Container networks - Docker and Kubernetes enable forwarding on the host
  • Network namespaces - packets between netns go through the kernel and require forwarding

Per-interface vs global

Beyond the global net.ipv4.ip_forward there is a per-interface knob:

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 mirrors the global setting
  • default/forwarding applies to NEW interfaces created after boot
  • per-interface value applies only to that interface

To enable forwarding only for a specific pair:

bash
sudo sysctl -w net.ipv4.conf.eth0.forwarding=1
sudo sysctl -w net.ipv4.conf.eth1.forwarding=1

What else you need

ip_forward=1 is a permission, not a complete solution. For packets to actually flow in both directions you also need:

  1. Routes on your machine to every subnet you are forwarding between (or a default route)
  2. Return routes on remote hosts, otherwise replies will not come back
  3. NAT (nat) if internal IPs are not routable in the wider network
  4. Firewall that does not drop the FORWARD chain (nftables/iptables often block FORWARD by default)

Minimal example for a two-interface router:

bash
sudo sysctl -w net.ipv4.ip_forward=1
# If NAT is needed (private network to public):
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'
# Allow FORWARD in the firewall (simple accept policy)
sudo nft 'add chain inet filter forward { type filter hook forward priority 0; policy accept; }'

Reverse path filtering

A related sysctl is net.ipv4.conf.*.rp_filter. When enabled, the kernel drops incoming packets if the reply to them would not go back out the same interface. This protects against spoofing but breaks asymmetric routing. On a router with multiple uplinks you often disable it:

bash
sudo sysctl -w net.ipv4.conf.all.rp_filter=0

Debug: packets leave but nothing comes back

When forwarding is on, routes are set, NAT is configured, but nothing works:

  1. tcpdump on each interface - do you see the packet?
  2. nft list ruleset / iptables -L FORWARD - is FORWARD being dropped?
  3. ip route get <dst> - which route will be selected?
  4. cat /proc/sys/net/ipv4/conf/<iface>/forwarding - is forwarding on for that specific interface?
  5. conntrack -L - is there a conntrack entry for this connection?

Inside a container

In Docker containers /proc/sys is read-only by default. To change forwarding from inside a container you need --cap-add=NET_ADMIN plus SYS_ADMIN and a remount of /proc/sys rw. It is usually better to enable forwarding on the host.

§ команды

bash
sudo sysctl -w net.ipv4.ip_forward=1

Enable IP forwarding until the next reboot

bash
sysctl net.ipv4.ip_forward

Check the current value (0 = disabled, 1 = enabled)

bash
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-router.conf

Persist the setting so it survives reboots

bash
ip route get 10.20.0.5

Show which route the kernel will use for this address - the primary forwarding debug tool

bash
sudo sysctl -w net.ipv4.conf.all.rp_filter=0

Disable reverse path filtering, needed for asymmetric routing

§ см. также

  • routing-tableRouting tableThe routing table lists where to send packets for each destination. The longest matching prefix wins.
  • natNAT: Network Address TranslationNAT rewrites the src or dst address of a packet at a router. Masquerade is the common case: the src IP is replaced with the router's outbound address so hosts on a private network can reach the public internet.
  • cmd-sysctlsysctl: kernel tunables`sysctl` reads and writes kernel parameters through the virtual filesystem `/proc/sys/`. Network, memory, and filesystem tuning all go through these knobs.
  • cmd-iptablesiptables: netfilter rules (legacy)iptables is the userland interface for netfilter. Five tables (filter/nat/mangle/raw/security), chains INPUT/OUTPUT/FORWARD/PRE/POSTROUTING, and jump targets ACCEPT/DROP/MASQUERADE. Legacy, but still widely deployed.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies