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 /etc/sysctl.conf:
net.ipv4.ip_forward=1
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 sysctl command:
sysctl -p
(This should happen automatically whenever the machine is rebooted.)
Use 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.
Read back the setting from the kernel using the sysctl command:
sysctl net.ipv4.ip_forward
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).
Use ping to check connectivity between the router and each of the machines used for the end-to-end test.
Use tcpdump or a similar tool to answer the following questions, stopping at the first one for which the answer is no:
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:
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 (eth1).
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 Troubleshooting the routing table.
The correct place to perform packet filtering of routed traffic would be in the FORWARD chain of the filter table:
iptables -t filter -L FORWARD -n
but packets could also go missing in the nat or 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.
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 Mounting /proc for further guidance.