Enable forwarding of IPv4 network packets
|Debian (Etch, Lenny, Squeeze)|
|Ubuntu (Hardy, Intrepid, Jaunty, Karmic, Lucid, Maverick, Natty, Precise, Trusty)|
To enable forwarding of IPv4 network packets, so that a machine can act as a router.
A router is a machine that is connected to two or more networks and which forwards packets between those networks. The ability to act as a router is built into the Linux kernel, but for reasons of safety and security it is usually disabled by default.
Suppose that a machine is to act as a boundary router between a local area network (connected to interface
eth0) and the public Internet (accessed through interface
ppp0). All machines have public IP addresses, therefore there is no need for any form of NAT.
These instructions assume that the network interfaces and routing table have been configured to the point that the router can communicate with any machine on the local area network or the public Internet.
If you wish to perform any firewalling on the router then this should be done before you enable forwarding: afterwards may be too late.
Add the following line to the file
Ensure that there are no other lines in the file that refer to
net.ipv4.ip_forward. (You may find that there is a commented-out line of the required form already in the file. If so then all you need do is uncomment it.)
Load the new setting into the kernel using the
(This should happen automatically whenever the machine is rebooted.)
ping to check end-to-end connectivity from a machine on one side of the router to a machine on the other side. This should preferably be done using a numeric IP address as opposed to a domain name so that the outcome of the test does not depend on whether name resolution has been configured correctly.
Check that forwarding is switched on.
Read back the setting from the kernel using the
This should give the answer:
net.ipv4.ip_forward = 1
A result of 0 probably indicates an error in
/etc/sysctl.conf. Failure to return a result probably indicates that
/proc has not been mounted (see below).
Check connectivity from each router interface
ping to check connectivity between the router and each of the machines used for the end-to-end test.
Monitor the packet flow
tcpdump or a similar tool to answer the following questions, stopping at the first one for which the answer is no:
- Does the outbound connection request reach the router?
- Does the router forward the request onto the other network?
- Does the reply reach the router?
- Does the router forward the reply back onto the original network?
A negative answer to questions 1 or 3 indicates a networking problem that is not associated with forwarding.
A negative answer to 2 or 4 could indicate that:
- forwarding has not been switched on;
- the output interface has not been correctly configured;
- there is an error in the routing table; or
- the traffic is being dropped by a firewall,
The first two of these explanations should already have been excluded by prior tests. The third should have been partially excluded, unless you have a complicated configuration with multiple routing tables, but it is worth checking to make sure. For most users, a firewall rule is the most likely explanation.
Suppose that the internal interface of the router is
eth0 with the address 192.168.0.1, the external interface is
eth1 with the address 203.0.113.1, the default route is 203.0.113.2, and the internal and external addresses between which you are testing connectivity are 192.168.0.2 and 198.51.100.1 respectively.
Check how outbound packets are routed with the command:
ip route get to 198.51.100.1 from 192.168.0.2 iif eth0
This should give a response of the form:
198.51.100.1 from 192.168.0.2 via 203.0.113.2 dev eth1 src 192.168.0.1 cache <src-direct> mtu 1500 advmss 1460 hoplimit 64 iif eth0
The main points to verify are that the IP address of the next hop is correct (203.0.113.2 in this case) and that the packet is being sent onwards through the appropriate interface (
Similarly, check how inbound packets are routed with the command:
ip route get to 192.168.0.2 from 198.51.100.1 iif eth1
which should give a response of the form:
192.168.0.2 from 198.51.100.1 dev eth0 src 203.0.113.1 cache mtu 1500 advmss 1460 hoplimit 64 iif eth1
For more guidance about troubleshooting the routing table see here.
The correct place to perform packet filtering of routed traffic would be in the
FORWARD chain of the
iptables -t filter -L FORWARD -n
but packets could also go missing in the
mangle tables so it is worth checking them too:
iptables -t nat -L -n iptables -t mangle -L -n
You can obtain more detailed visibility of how packets are traversing
iptables by inspecting the packet counter associated with each rule. First zero the counters:
iptables -t filter -Z FORWARD
then perform the
ping test and inspect the counter:
iptables -t filter -L FORWARD -nv
If you had explicitly blocked traffic from the machine you were attempting to
ping then you might see output similar to:
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 6 504 DROP all -- any any 198.51.100.1 anywhere
This shows that 6 packets were dropped by the first (and only) rule in this chain. No packets reached the end of the chain.
The counts may become difficult to interpret if the router is carrying more than just your test traffic. In that case it may be necessary add extra rules (or chains) purely for the purpose of gathering statistics.
Cannot find /proc/version
An error from
sysctl of the form:
Cannot find /proc/version - is /proc mounted?
probably indicates, as it suggests, that
/proc has not been mounted. The simplest way to check is to list the content of that directory. See here for further guidance.