How to set up a DMZ with a Linux router

To explain how to set up a DMZ with a a Linux router I will use the firewall in my own Raspberry Pi router as an example.

You want to route an incoming connection to a computer in the LAN. Let’s assume the connection is SSH, that is, of protocol TCP and port 22 type.

The first step is to re-route the incoming connection to the LAN IP. Let’s assume the LAN computer has IP The re-routing in done in the NAT table and PREROUTING chain.

Add to the NAT chain,

$IPTABLES -t nat -A PREROUTING -p TCP -i $INET_IFACE -d $INET_IP --dport 22 -j DNAT --to-destination

In this pre-routing rule, any connection arriving at the external network interface $INET_IFACE with IP $INET_IP, and protocol TCP and port 22, is routed to IP

This alone will not do the trick, because the connection needs to be forwarded to the LAN network interface.

Add to the LAN network interface’s FORWARD chain, before all external requests to the LAN are blocked,

$IPTABLES -A FORWARD -i $INET_IFACE -o $IFACE -p TCP -m state --state NEW --dport 22 -j ACCEPT

This rule forwards any connection of protocol TCP to port 22 arriving at the external interface $INET_IFACE to the LAN network interface $IFACE.

Needless to say, the LAN computer that receives all SSH connections from the exterior needs to be protected. I use a hit counter to limit the allowed number of connections from an IP,

$IPTABLES -A INPUT -i $IFACE -p TCP -m state --state NEW --dport 22 -m recent --set
$IPTABLES -A INPUT -i $IFACE -p TCP -m state --state NEW --dport 22 -m recent --update --seconds 120 --hitcount 2 -j DROP
$IPTABLES -A INPUT -i $IFACE -p TCP -m state --state NEW --dport 22 -j LOG --log-level debug --log-prefix "iptables ssh: "
$IPTABLES -A INPUT -i $IFACE -p TCP -m state --state NEW --dport 22 -j ACCEPT

These rules will set a counter of maximum 2 connections every 120 seconds for any IP attempting to connect with SSH. This effectively reduces the chance of hacking to practically zero.