The Pre-Routing Chain and Routing Decision
When a network packet arrives at a Linux system, it enters the Netfilter framework via thePREROUTING chain. This is the earliest point where the kernel can inspect incoming traffic. At this stage, the kernel must determine the fate of the packet: does it belong to a local application, or should it be routed elsewhere?
This decision is governed by the kernel's routing table. The kernel examines the destination IP address of the packet and consults the routing policy database. If the destination matches an IP address assigned to one of the local interfaces, the packet is marked for local delivery. If the destination belongs to a different network and the system is configured to route traffic (either as a gateway or through manual rules), the packet is marked for forwarding.
It is important to note that this check happens before any filtering rules in the FORWARD chain are applied. Therefore, understanding the initial classification helps in placing firewall rules correctly. For instance, if you want to block traffic destined for your own server, you must use the INPUT chain, not the FORWARD chain. Conversely, if you are acting as a router for other devices, your rules should target the FORWARD chain.
Local Delivery Mechanism
Local delivery occurs when the packet’s destination IP address is assigned to the receiving interface. Once the routing decision classifies the packet as local, it moves from thePREROUTING chain to the INPUT chain. Here, various filtering and manipulation rules can be applied before the packet is passed up the protocol stack to the appropriate socket.
For TCP connections, the packet eventually reaches the transport layer, where it is matched to a listening socket based on the destination port. For UDP or ICMP, similar mechanisms apply. If no process is listening on the specified port, the kernel typically generates an error response, such as an ICMP port unreachable message, unless explicitly suppressed.
This path is essential for services running on the machine itself, such as web servers, SSH daemons, or DNS resolvers. Misconfigurations here often manifest as connection refused errors or timeouts, even when the network path is clear. Debugging local delivery issues frequently involves checking netstat or ss to verify which processes are bound to which ports and ensuring that the iptables or nftables rules in the INPUT chain allow the traffic.
Packet Forwarding Mechanism
Forwarding applies when the packet is destined for a host other than the Linux system itself. After the routing decision marks the packet for forwarding, it proceeds to theFORWARD chain. This is where most stateful firewall rules operate, allowing administrators to control traffic flowing through the device.
If forwarding is enabled, the kernel decrements the Time To Live (TTL) field in the IP header and checks the routing table again to determine the outgoing interface. It then performs source NAT (Network Address Translation) if configured, updates checksums, and hands the packet to the output driver for transmission.
A common pitfall in setting up Linux as a router is forgetting to enable IP forwarding. By default, many distributions disable this feature for security reasons. You can check its status by reading the value of /proc/sys/net/ipv4/ip_forward. A value of 0 means forwarding is disabled, and all non-local traffic will be dropped. Setting this to 1 enables the kernel to act as a gateway.
For more details on how routers handle broadcasts and local network traffic, see Sending Packet: Machine-to-Machine Local Network Broadcasts with Routers.
Key Differences and Configuration
The primary difference lies in the final destination and the Netfilter chains involved. Local delivery ends at a local socket, while forwarding continues to another network interface. This distinction dictates where you must place your security policies. To manage these behaviors, administrators use several tools. Theip route command displays the current routing table, showing which destinations are considered local versus remote. The sysctl utility allows runtime modification of kernel parameters, such as enabling IP forwarding or adjusting TCP/IP stack behavior.
Firewall configuration is also distinct. In iptables, the -P INPUT ACCEPT rule controls local traffic, while -P FORWARD DROP controls transit traffic. Modern systems using nftables follow similar logic but with a more unified syntax. Always ensure that your firewall policies align with the intended role of the machine: is it an endpoint or a transit node?
Additionally, consider the impact of tunneling protocols if you are encapsulating traffic. See Understanding Tunneling Protocols for insights into how encapsulated packets are handled differently.
Troubleshooting Common Issues
One frequent issue is asymmetric routing, where packets arrive on one interface but are sent out another due to multiple default routes or complex policy routing. This can cause stateful firewalls to drop returning traffic because they do not recognize the established connection. Usingconntrack tools can help visualize these state mismatches.
Another issue arises when local delivery fails despite correct IP assignment. This might be due to strict rp_filter settings, which validate the reverse path of incoming packets. If the reverse path is not reachable via the same interface, the kernel drops the packet to prevent spoofing. Adjusting net.ipv4.conf.all.rp_filter may be necessary in multi-homed setups.
Finally, always verify that the service is actually listening. A common mistake is assuming that because the packet reached the local interface, the application is ready. Use ss -tuln to confirm active listeners and check logs for binding errors.
Frequently Asked Questions
How do I enable packet forwarding on Linux?
You can enable IP forwarding by writing 1 to the proc file /proc/sys/net/ipv4/ip_forward. For persistent changes across reboots, add net.ipv4.ip_forward=1 to /etc/sysctl.conf and run sysctl -p.
What is the difference between INPUT and FORWARD chains?
The INPUT chain handles packets destined for local processes on the host, while the FORWARD chain manages packets being routed through the system to other destinations. Rules placed in each chain only affect their respective traffic types.
Why are my forwarded packets being dropped?
Packets are often dropped because IP forwarding is disabled in the kernel, or because firewall rules in the FORWARD chain explicitly deny the traffic. Check the ip_forward sysctl value and review iptables/nftables logs for denied entries.
Can a single interface handle both local delivery and forwarding?
Yes, a single physical or virtual interface can receive packets for local delivery and forward others simultaneously. The kernel makes this decision per-packet based on the destination IP address and routing table entries.
What role does the PREROUTING chain play in this process?
The PREROUTING chain is the first stop for incoming packets where DNAT (Destination NAT) can be applied. It also precedes the routing decision, allowing the kernel to modify the destination address before determining if the packet is local or remote.