Description
With IP forwarding on, the kernel routes packets received on one interface to another, like a
router. It is controlled by net.ipv4.ip_forward (an alias of net.ipv4.conf.all.forwarding),
net.ipv4.conf.default.forwarding for interfaces created later, and
net.ipv6.conf.all.forwarding / net.ipv6.conf.default.forwarding for IPv6. Debian ships
forwarding off. This control checks all five values against the ip_forward parameter.
Writing net.ipv4.ip_forward also resets several per-interface settings (the kernel documentation
calls it special), so the fix writes it first. IPv6 checks only run when the IPv6 stack is
present.
Rationale
A host that is not meant to route should never relay traffic: forwarding lets an attacker who controls one of its networks reach the others through it, bypassing network filtering.
Impact
Hosts that legitimately route need forwarding: routers, VPN gateways, and hosts running
containers or virtual machines with NAT (Docker, libvirt, LXC turn it on at start). On those,
set the ip_forward parameter to 1 in the tailoring file, and filter forwarded traffic in
the firewall (CB-DEB-NET-006).
Setting
| Location | sysctl `net.ipv4.ip_forward`, `net.ipv4.conf.{all,default}.forwarding`, `net.ipv6.conf.{all,default}.forwarding`, persisted in `/etc/sysctl.d/` |
| Default | 0 |
| Recommended | {{ ip_forward }} (0 except on routers) |
Parameters
| Parameter | Core | Server | Server hardened | Desktop | Desktop hardened | Bounds |
|---|---|---|---|---|---|---|
ip_forwardinteger. Expected forwarding state, 0 for a host, 1 for a router or container host. | 0 | 0 | 0 | 0 | 0 | 0 to 1 |
The value used is your override (tailoring file), else the profile's, else the one of the profile it extends, else the default. Bounds limit what an override may set.
Audit
Run sysctl net.ipv4.ip_forward net.ipv4.conf.all.forwarding net.ipv4.conf.default.forwarding net.ipv6.conf.all.forwarding net.ipv6.conf.default.forwarding.
Every value must be {{ ip_forward }}. Then check that no file in /etc/sysctl.d/,
/run/sysctl.d/, /usr/lib/sysctl.d/ or /etc/sysctl.conf sets another value.
Automated: every check must pass. Scanners report each check by its id.
ipv4-ip-forward
net.ipv4.ip_forward.
key: net.ipv4.ip_forward
value: '{{ ip_forward }}'
ipv4-all
net.ipv4.conf.all.forwarding.
key: net.ipv4.conf.all.forwarding
value: '{{ ip_forward }}'
ipv4-default
net.ipv4.conf.default.forwarding.
key: net.ipv4.conf.default.forwarding
value: '{{ ip_forward }}'
ipv6-all
net.ipv6.conf.all.forwarding.
key: net.ipv6.conf.all.forwarding
value: '{{ ip_forward }}'
ipv6-default
net.ipv6.conf.default.forwarding.
key: net.ipv6.conf.default.forwarding
value: '{{ ip_forward }}'
Remediation
Add to /etc/sysctl.d/60-cirsec.conf, net.ipv4.ip_forward first:
net.ipv4.ip_forward = {{ ip_forward }}
net.ipv4.conf.all.forwarding = {{ ip_forward }}
net.ipv4.conf.default.forwarding = {{ ip_forward }}
net.ipv6.conf.all.forwarding = {{ ip_forward }}
net.ipv6.conf.default.forwarding = {{ ip_forward }}
Remove other assignments of these keys, then run sysctl --system.
| Restart | none |
| Disruption | low |
Rollback
Remove the lines from /etc/sysctl.d/60-cirsec.conf and set the previous values with sysctl -w.
ipv4-ip-forward
Generated from check ipv4-ip-forward: the engine writes the fix for every output, it sets the expected value and the check runs again after.
ipv4-all
Generated from check ipv4-all: the engine writes the fix for every output, it sets the expected value and the check runs again after.
ipv4-default
Generated from check ipv4-default: the engine writes the fix for every output, it sets the expected value and the check runs again after.
ipv6-all
Generated from check ipv6-all: the engine writes the fix for every output, it sets the expected value and the check runs again after.
ipv6-default
Generated from check ipv6-default: the engine writes the fix for every output, it sets the expected value and the check runs again after.
Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.
References
- Linux kernel documentation - IP Sysctl The Linux Kernel Organization, vendor-doc, accessed 2026-10-18
- sysctl.d(5), Debian manual pages Debian, vendor-doc, accessed 2026-10-18
- ANSSI-BP-028 v2.0 - Recommandations de configuration d'un système GNU/Linux (R12) ANSSI, guide, accessed 2026-10-18
Mappings
| Framework | ID | Relation | Note |
|---|---|---|---|
| ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0 | R12 | partial | R12 lists many IPv4 settings; this control covers forwarding. |
| NIST SP 800-53 Rev. 55.1.1 | CM-7 | related |
How this control relates to the other framework's: equivalent, stricter, looser, partial or related.
Threats mitigated
People and lifecycle
| Authors |
|
| Verified | 2026-10-18 by Sn0wAlice on 12, Proxmox VM 921, Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64. Debian defaults pass; checks for IPv4 and IPv6 run, values kept after reboot. |
| Verified | 2026-10-18 by Sn0wAlice on 13, Proxmox VM 931, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64. Debian defaults pass; checks for IPv4 and IPv6 run, values kept after reboot. |
| Introduced in | v0.1.0 |
| Created, updated | 2026-10-18, 2026-10-18 |
| Translations | fr |