My first firewall seemed to work well but it did not. The reason for this was that I did not understand the concept of the iptables completely. I had opened the OUTPUT chain completely and inserted a lot of INPUT rules. For the FORWARD I had very few lines. For the POSTROUTING I used SNAT.
When I activated this firewall for the first time I was unable to go to the outside world. In the SYSLOG I found out that it was blocked in the FORWARD chain. The solution was simple: Open the ports in the FORWARD chain. But I was puzzeled. I decided to ask some questions to Henk van de Kamer. He is a Dutch guy who writes about his work with computers (Het Lab). His answers made me change (and as a result simplify) my firewall.
On the INPUT, OUTPUT, and FORWARD chains I accept all traffic that is already in an 'active' state. I also allow some ICMP protocol traffics.
The INPUT chain handles the traffic that comes into the firewall (=the router). Since I only need to access the firewall from my LAN and DMZ I only need to check these interfaces. On the firewall there is only SSH and HTTP available so only traffic to those ports is accepted.
The OUTPUT chain handles the traffic that goes out of the firewall. I need to be able to mount a directory through shfs (port 22), upgrade the software (port 80), synchronise the internal clock (port 123), and log to an external SYSLOG server (port 514) I open only those ports.
The FORWARD chain handles all traffic that passes the firewall. I will open it port by port. The SYSLOG is a great help for this. At this moment I have only the ports 53 (DNS), 80 (HTTP), and 123 (NTP) open between the DMZ and the outside world. At this moment my LAN is protected by another firewall. Once my DMZ is operational this will change.
The PREROUTING chain changes packet envelopes. I use it to re-route the HTTP and HTTPS traffic to the Squid server and to re-route the HTTP traffic to the intranet server to the 8080 port.
The POSTROUTING chain changes packet envelopes. I use it to 'MASQUERADE' the internal IP-addresses. For the outside world all packets come from the same IP-address. If you want/need to use multiple IP-addresses then you must use SNAT instead of MASQUERADE.
#!/bin/sh . /etc/functions.sh ### Activate the LOG option for iptables. insmod ipt_LOG insmod ipt_REDIRECT ### Get the broadcast. getBC() { IP=`echo $1 | sed -re 's/.[0-9]*$/.255/'` echo $IP } ### Find the IP Address for a server. getIP() { IP=`ping -c 1 $1 2>&1 | grep -E '^PING' | sed -re 's/^[^(]*.([^)]*).*/\1/'` if [ -z "$IP" ]; then IP="127.0.0.1"; fi echo $IP } ### Get the net. getNW() { IP=`echo $1 | sed -re 's:.[0-9]*$:.0/24:'` echo $IP } ### Find the interface per sub-domain. DMZ=$(nvram get dmz_ifname) DMZ_IP=$(nvram get dmz_ipaddr) FREE=$(nvram get free_ifname) FREE_IP=$(nvram get free_ipaddr) LAN=$(nvram get lan_ifname) LAN_IP=$(nvram get lan_ipaddr) VOIP=$(nvram get voip_ifname) VOIP_IP=$(nvram get voip_ipaddr) WAN=$(nvram get wan_ifname) WAN_IP=$(nvram get wan_ipaddr) ### Preset servers DNS=`getIP dns.debooy.eu` MODEM=`getIP modem.debooy.eu` TOMCAT=`getIP intra.debooy.eu` PROXY=`getIP proxy.debooy.eu` SAMBA=`getIP samba.debooy.eu` TELCEN=`getIP aput.debooy.eu` ### Broadcasts DMZ_BC=`getBC $DMZ_IP` FREE_BC=`getBC $FREE_IP` GEN_BC=255.255.255.255 LAN_BC=`getBC $LAN_IP` VOIP_BC=`getBC $VOIP_IP` WAN_BC=`getBC $WAN_IP` ### Networks DMZ_NW=`getNW $DMZ_IP` FREE_NW=`getNW $FREE_IP` GEN_NW=0/0 LAN_NW=`getNW $LAN_IP` VOIP_NW=`getNW $VOIP_IP` WAN_NW=`getNW $WAN_IP` ### Allow forwarding of packets. echo 1 > /proc/sys/net/ipv4/ip_forward iptables --flush iptables --table filter --flush iptables --table nat --flush iptables --delete-chain iptables --table nat --delete-chain ### Allow self access by loopback interface iptables -A INPUT -i lo -j ACCEPT iptables -A FORWARD -i lo -j ACCEPT ### Create separate chains iptables -N allowed iptables -N bad_tcp_packets iptables -N blacklist iptables -N icmp_packets iptables -N whitelist iptables -N ${DMZ}_FW iptables -N ${DMZ}_IN iptables -N ${DMZ}_OU iptables -N ${FREE}_IN iptables -N ${LAN}_FW iptables -N ${LAN}_IN iptables -N ${LAN}_OU iptables -N ${VOIP}_IN iptables -N ${WAN}_IN ### allowed chain iptables -A allowed -p tcp --syn -j ACCEPT iptables -A allowed -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A allowed -p tcp -j DROP ### bad_tcp_packets chain iptables -A bad_tcp_packets -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j REJECT --reject-with tcp-reset iptables -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "FIREWALL:NEW!SYN - " iptables -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP ### ICMP rules iptables -A icmp_packets -p icmp --fragment -j LOG --log-prefix "FIREWALL:ICMP!FR - " iptables -A icmp_packets -p icmp --fragment -j DROP iptables -A icmp_packets -p icmp -s $GEN_NW --icmp-type 0 -j ACCEPT iptables -A icmp_packets -p icmp -s $GEN_NW --icmp-type 8 -j ACCEPT iptables -A icmp_packets -p icmp -s $GEN_NW --icmp-type 11 -j ACCEPT ### Blacklist if [ -f /etc/iptables/blacklist ]; then for HOST in `cat /etc/iptables/blacklist` do iptables -A blacklist -s $HOST -j DROP done fi ### Whitelist if [ -f /etc/iptables/whitelist ]; then for HOST in `cat /etc/iptables/whitelist` do iptables -A whitelist -s $HOST -j ACCEPT done fi ### DMZ FW rules iptables -A ${DMZ}_FW -p tcp --dport 22 -j ACCEPT iptables -A ${DMZ}_FW -p udp --dport 22 -j ACCEPT iptables -A ${DMZ}_FW -p tcp --dport 25 -j ACCEPT iptables -A ${DMZ}_FW -p udp --dport 53 -j ACCEPT iptables -A ${DMZ}_FW -p udp --dport 67:68 --sport 67:68 -j ACCEPT iptables -A ${DMZ}_FW -p tcp --dport 80 -j ACCEPT iptables -A ${DMZ}_FW -p udp --dport 123 -j ACCEPT iptables -A ${DMZ}_FW -p tcp --dport 139 -j ACCEPT iptables -A ${DMZ}_FW -p tcp --dport 445 -j ACCEPT iptables -A ${DMZ}_FW -p tcp --dport 8080 -j ACCEPT iptables -A ${DMZ}_FW -p tcp -d $MODEM --dport 23 -j ACCEPT iptables -A ${DMZ}_FW -p tcp -d $TELCEN --dport 23 -j ACCEPT ### DMZ IN rules iptables -A ${DMZ}_IN -p all -d $DMZ_IP -j ACCEPT iptables -A ${DMZ}_IN -p tcp --dport 22 -j ACCEPT iptables -A ${DMZ}_IN -p udp --dport 22 -j ACCEPT iptables -A ${DMZ}_IN -p udp --dport 53 -j ACCEPT iptables -A ${DMZ}_IN -p udp --dport 67:68 --sport 67:68 -j ACCEPT iptables -A ${DMZ}_IN -p udp -d $DMZ_BC --dport 135:139 -j DROP iptables -A ${DMZ}_IN -p udp -d $GEN_BC --dport 135:139 -j DROP iptables -A ${DMZ}_IN -p tcp --dport 137:139 -j ACCEPT iptables -A ${DMZ}_IN -p udp --dport 137:139 -j ACCEPT ### DMZ OU rules iptables -A ${DMZ}_OU -p udp --dport 53 -j ACCEPT iptables -A ${DMZ}_OU -p udp --dport 123 -j ACCEPT iptables -A ${DMZ}_OU -p udp --dport 514 -j ACCEPT ### FREE IN rules iptables -A ${FREE}_IN -p all -d $FREE_IP -j ACCEPT iptables -A ${FREE}_IN -p tcp --dport 22 -j ACCEPT iptables -A ${FREE}_IN -p udp --dport 22 -j ACCEPT iptables -A ${FREE}_IN -p udp --dport 67:68 --sport 67:68 -j ACCEPT ### LAN FW rules iptables -A ${LAN}_FW -p tcp --dport 21 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 22 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 22 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 25 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 53 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 67:68 --sport 67:68 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 110 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 123 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 389 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 389 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 443 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 500 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 554 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 3128 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 3306 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 4500 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 8085 -j ACCEPT iptables -A ${LAN}_FW -p tcp -d $MODEM --dport 23 -j ACCEPT iptables -A ${LAN}_FW -p tcp -d $MODEM --dport 80 -j ACCEPT ## Facebook spelletjes iptables -A ${LAN}_FW -p tcp -o ${WAN} --dport 843 -j ACCEPT iptables -A ${LAN}_FW -p tcp -o ${WAN} --dport 8080 -j ACCEPT iptables -A ${LAN}_FW -p tcp -o ${WAN} --dport 9339 -j ACCEPT ## Samba iptables -A ${LAN}_FW -p tcp --dport 135 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 137 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 138 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 139 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 445 -j ACCEPT ## NFS iptables -A ${LAN}_FW -p tcp --dport 111 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 111 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 2049 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 2049 -j ACCEPT iptables -A ${LAN}_FW -p tcp --dport 32765:32769 -j ACCEPT iptables -A ${LAN}_FW -p udp --dport 32765:32769 -j ACCEPT ### LAN IN rules iptables -A ${LAN}_IN -p all -d $LAN_IP -j ACCEPT iptables -A ${LAN}_IN -p tcp --dport 22 -j ACCEPT iptables -A ${LAN}_IN -p udp --dport 22 -j ACCEPT iptables -A ${LAN}_IN -p tcp --dport 42 -j ACCEPT iptables -A ${LAN}_IN -p udp --dport 67:68 --sport 67:68 -j ACCEPT iptables -A ${LAN}_IN -p tcp --dport 80 -j ACCEPT iptables -A ${LAN}_IN -p udp -d $LAN_BC --dport 135:139 -j DROP iptables -A ${LAN}_IN -p udp -d $GEN_BC --dport 135:139 -j DROP iptables -A ${LAN}_IN -p tcp --dport 137:139 -j ACCEPT iptables -A ${LAN}_IN -p udp --dport 137:139 -j ACCEPT iptables -A ${LAN}_IN -p udp -s $LAN_IP --dport 514 -j ACCEPT ### LAN OU rules iptables -A ${LAN}_OU -p udp --dport 514 -j ACCEPT ### VOIP FW rules iptables -A ${VOIP}_FW -p udp --dport 53 -j ACCEPT iptables -A ${VOIP}_FW -p udp --dport 67:68 --sport 67:68 -j ACCEPT iptables -A ${VOIP}_FW -p udp --dport 123 -j ACCEPT iptables -A ${VOIP}_FW -p udp --dport 5060 -j ACCEPT ### VOIP IN rules iptables -A ${VOIP}_IN -p all -d $VOIP_IP -j ACCEPT iptables -A ${VOIP}_IN -p tcp --dport 22 -j ACCEPT iptables -A ${VOIP}_IN -p udp --dport 22 -j ACCEPT iptables -A ${VOIP}_IN -p udp --dport 67:68 --sport 67:68 -j ACCEPT ### FORWARD rules iptables -A FORWARD -j blacklist iptables -A FORWARD -j whitelist iptables -A FORWARD -p tcp -j bad_tcp_packets iptables -A FORWARD -p icmp -j icmp_packets iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # Where does it come from? iptables -A FORWARD -p all -i $DMZ -j ${DMZ}_FW iptables -A FORWARD -p all -i $LAN -j ${LAN}_FW iptables -A FORWARD -p all -i $VOIP -j ${VOIP}_FW iptables -A FORWARD -p all -i $WAN -j ${WAN}_FW ### INPUT rules iptables -A INPUT -j blacklist iptables -A INPUT -j whitelist iptables -A INPUT -p tcp -j bad_tcp_packets iptables -A INPUT -p icmp -j icmp_packets iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Where does it come from? iptables -A INPUT -p all -i $DMZ -j ${DMZ}_IN iptables -A INPUT -p all -i $FREE -j ${FREE}_IN iptables -A INPUT -p all -i $LAN -j ${LAN}_IN iptables -A INPUT -p all -i $VOIP -j ${VOIP}_IN iptables -A INPUT -p all -i $WAN -j ${WAN}_IN ### From Localhost interface to Localhost IP's iptables -A INPUT -p all -i lo -s $DMZ_IP -j ACCEPT iptables -A INPUT -p all -i lo -s $FREE_IP -j ACCEPT iptables -A INPUT -p all -i lo -s $LAN_IP -j ACCEPT iptables -A INPUT -p all -i lo -s $VOIP_IP -j ACCEPT iptables -A INPUT -p all -i lo -s $WAN_IP -j ACCEPT ### OUTPUT rules iptables -A OUTPUT -j blacklist iptables -A OUTPUT -j whitelist iptables -A OUTPUT -p tcp -j bad_tcp_packets iptables -A OUTPUT -p icmp -j icmp_packets iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Where does it come from? iptables -A OUTPUT -p all -o $DMZ -j ${DMZ}_OU iptables -A OUTPUT -p all -o $LAN -j ${LAN}_OU ### PREROUTING rules iptables -t nat -A PREROUTING -i $LAN -p tcp -d $LAN_IP --dport 80 -j ACCEPT iptables -t nat -A PREROUTING -i $LAN -p tcp -d $MODEM --dport 80 -j ACCEPT iptables -t nat -A PREROUTING -i $LAN -p tcp --dport 80 -j DNAT --to $PROXY:3128 ### POSTROUTING rules ## Enable simple IP Forwarding and Network Address Translation #iptables -t nat -A POSTROUTING -o $WAN -j LOG --log-prefix "FIREWALL:P.ROUTE - " iptables -t nat -A POSTROUTING -o $WAN -s $DMZ_NW -j MASQUERADE iptables -t nat -A POSTROUTING -o $WAN -s $FREE_NW -j MASQUERADE iptables -t nat -A POSTROUTING -o $WAN -s $LAN_NW -j MASQUERADE iptables -t nat -A POSTROUTING -o $WAN -s $VOIP_NW -j MASQUERADE iptables -t nat -A POSTROUTING -o $WAN -s $WIFI_NW -j MASQUERADE ### Log the packages that passed iptables -A INPUT -j LOG --log-prefix "FIREWALL:INPUT - " iptables -A FORWARD -j LOG --log-prefix "FIREWALL:FORWARD - " iptables -A OUTPUT -j LOG --log-prefix "FIREWALL:OUTPUT - " ### Block all the rest iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT