Again, working to harden Linux as much as possible. After much searching, reading, researching, comparison, and experimentation I developed this. I will update this post with new content when I revise the firewall configuration. If you scroll down towards the bottom of this post you will find the rest of the parts that make this really work well in Ubuntu 12.04 Server.
File: iptablesconfv22.sh
# Jim McKibben # 2013-02-12 # Version 2.2 # Iptables Firewall configuration script # Allows HTTP, HTTPS, SSH, SMTP # Allows Local Loopback # Allows specific ICMP # Allows DNS Query and Response # Blocks bad source # Blocks non local Loopback # DOS Protection and reporting # DOS SYN Flood # DOS ICMP # DOS HTTP - Now with hash table expiry # DOS SSH # Logging # DUMP /sbin/iptables -N DUMP > /dev/null /sbin/iptables -F DUMP /sbin/iptables -A DUMP -p tcp -j LOG --log-prefix "iptables: tcp: " /sbin/iptables -A DUMP -p udp -j LOG --log-prefix "iptables: udp: " /sbin/iptables -A DUMP -p tcp -j REJECT --reject-with tcp-reset /sbin/iptables -A DUMP -p udp -j REJECT --reject-with icmp-port-unreachable /sbin/iptables -A DUMP -j DROP # Blocking excessive syn packet /sbin/iptables -N SYN_FLOOD /sbin/iptables -A INPUT -p tcp --syn -j SYN_FLOOD /sbin/iptables -A SYN_FLOOD -m limit --limit 1/s --limit-burst 3 -j RETURN /sbin/iptables -A SYN_FLOOD -j DROP # Stateful table #/sbin/iptables -N STATEFUL > /dev/null #/sbin/iptables -F STATEFUL #/sbin/iptables -I STATEFUL -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT #/sbin/iptables -A STATEFUL -m conntrack --ctstate NEW -i !eth0 -j ACCEPT #/sbin/iptables -A STATEFUL -j DUMP # Loopback rules /sbin/iptables -A INPUT -i lo -j ACCEPT /sbin/iptables -A INPUT -i !lo -d 127.0.0.0/8 -j REJECT /sbin/iptables -A OUTPUT -o lo -j ACCEPT /sbin/iptables -A OUTPUT -o !lo -d 127.0.0.0/8 -j REJECT # drop reserved addresses incoming (these are reserved addresses) # but may change soon /sbin/iptables -A INPUT -i eth0 -s 0.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 1.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 2.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 5.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 7.0.0.0/8 -j DUMP # As it turns out my Dynamic Cloud Server uses 10.0.0.0/8 for local communication # so on my config I have this next line commented out /sbin/iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 23.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 27.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 31.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 36.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 39.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 41.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 42.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 58.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 59.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 60.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 169.254.0.0/16 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 197.0.0.0/8 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 224.0.0.0/3 -j DUMP /sbin/iptables -A INPUT -i eth0 -s 240.0.0.0/8 -j DUMP # Allow certain inbound ICMP types (ping, traceroute..) /sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type destination-unreachable -m limit --limit 1/s --limit-burst 1 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type time-exceeded -m limit --limit 1/s --limit-burst 1 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type echo-reply -m limit --limit 1/s --limit-burst 1 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 1 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix "iptables: PING-DROP: " /sbin/iptables -A INPUT -i eth0 -p icmp -j DROP # Drop all packets to port 111 except those from localhost /sbin/iptables -A INPUT ! -s 127.0.0.0/8 -p tcp --dport 111 -j REJECT --reject-with tcp-reset # kill off identd quick /sbin/iptables -A INPUT -i eth0 -p tcp --dport 113 -j REJECT --reject-with tcp-reset # Allow all established, related in #/sbin/iptables -A INPUT -i eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Allows Inbound NEW DOS SSH Attack prevention (only 4 attempts by an IP every 3 minutes, drop the rest) # The ACCEPT at the end is necessary or, it wouldn't accept any connection /sbin/iptables -A INPUT -i eth0 -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -m recent --set --name DEFAULT --rsource /sbin/iptables -A INPUT -i eth0 -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j LOG -m limit --limit 20/m --log-prefix "iptables: SSH Attempt on port 22 : " /sbin/iptables -A INPUT -i eth0 -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j REJECT /sbin/iptables -A INPUT -i eth0 -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT # Inbound ESTABLISHED SSH (out is in Multi-out) /sbin/iptables -A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT # DOS HTTP Attack prevention /sbin/iptables -A INPUT -i eth0 -p tcp --dport 80 -m limit --limit 45/minute --limit-burst 300 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p tcp --dport 80 -m hashlimit --hashlimit-upto 80/min --hashlimit-burst 800 --hashlimit-mode srcip --hashlimit-name http -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p tcp --dport 80 -m hashlimit --hashlimit-upto 120/min --hashlimit-burst 1200 --hashlimit-mode srcip --hashlimit-name http -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p tcp --dport 80 -j DROP /sbin/iptables -A INPUT -i eth0 -p tcp --dport 443 -m limit --limit 45/minute --limit-burst 300 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p tcp --dport 443 -m hashlimit --hashlimit-upto 80/min --hashlimit-burst 800 --hashlimit-mode srcip --hashlimit-name https -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p tcp --dport 443 -j DROP # Allow Ping from Outside to Inside /sbin/iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT # Multi-out for inbound SSH, HTTP, and HTTPS /sbin/iptables -A OUTPUT -o eth0 -p tcp -m multiport --sports 22,80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Outbound SSH /sbin/iptables -A INPUT -i eth0 -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT /sbin/iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Allow inbound DNS #/sbin/iptables -A INPUT -i eth0 -p udp --sport 1024:65535 --dport 53 -j ACCEPT #/sbin/iptables -A OUTPUT -p udp --sport 53 --dport 1024:65535 -j ACCEPT # Allow outbound DNS /sbin/iptables -A INPUT -i eth0 -p udp --dport 1024:65535 --sport 53 -j ACCEPT /sbin/iptables -A OUTPUT -p udp --dport 53 --sport 1024:65535 -j ACCEPT # Outbound HTTP, and HTTPS /sbin/iptables -A OUTPUT -o eth0 -p tcp --dport 80 --sport 1024:65535 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p tcp --dport 1024:65535 --sport 80 -j ACCEPT /sbin/iptables -A OUTPUT -o eth0 -p tcp --dport 443 --sport 1024:65535 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p tcp --dport 1024:65535 --sport 443 -j ACCEPT # Inbound SMTP /sbin/iptables -A INPUT -i eth0 -p tcp --sport 1024:65535 --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT /sbin/iptables -A OUPUT -o eth0 -p tcp --sport 25 --dport 1024:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Outbound SMTP /sbin/iptables -A INPUT -i eth0 -p tcp --sport 25 --dport 1024:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT /sbin/iptables -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Server to Server SMTP /sbin/iptables -A INPUT -i eth0 -p tcp --sport 25 --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT /sbin/iptables -A OUTPUT -o eth0 -p tcp --sport 25 --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Allow rsync from a specific network #/sbin/iptables -A INPUT -i eth0 -p tcp -s 192.168.101.0/24 --dport 873 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT #/sbin/iptables -A OUTPUT -o eth0 -p tcp --sport 873 -m conntrack --ctstate ESTABLISHED -j ACCEPT # Allow all related #/sbin/iptables -A OUTPUT -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Don't log route packets coming from routers - too much logging /sbin/iptables -A INPUT -i eth0 -p udp --dport 520 -j REJECT # Don't log smb/windows sharing packets - too much logging /sbin/iptables -A INPUT -i eth0 -p tcp --dport 137:139 -j REJECT /sbin/iptables -A INPUT -i eth0 -p udp --dport 137:139 -j REJECT # All policies set to DROP /sbin/iptables --policy INPUT DROP /sbin/iptables --policy OUTPUT DROP /sbin/iptables --policy FORWARD DROP
Credit for this next section goes directly to Ubuntu at https://help.ubuntu.com/community/IptablesHowTo, well done guys!
Configuration on startup
WARNING: Iptables and NetworkManager can conflict. Also if you are concerned enough about security to install a firewall you might not want to trust NetworkManager. Also note NetworkManager and iptables have opposite aims. Iptables aims to keep any questionable network traffic out. NetworkManager aims to keep you connected at all times. Therefore if you want security all the time, run iptables at boot time. If you want security some of the time then NetworkManager might be the right choice.
WARNING: If you use NetworkManager (installed by default on Feisty and later) these steps will leave you unable to use NetworkManager for the interfaces you modify. Please follow the steps in the next section instead.
NOTE: It appears on Hardy, NetworkManager has an issue with properly on saving and restoring the iptable rules when using the method in the next section. Using this first method appears to work. If you find otherwise, please update this note.
Save your firewall rules to a file
sudo sh -c "iptables-save > /etc/iptables.rules"
At this point you have several options. You can make changes to /etc/network/interfaces or add scripts to /etc/network/if-pre-up.d/ and /etc/network/if-post-down.d/ to achieve similar ends. The script solution allows for slightly more flexibility.
NOTE: This solution uses iptables-save -c to save the counters. Just remove the -c to only save the rules.
Alternatively you could add the iptables-restore and iptables-save to the if-pre-up.d and if-post-down.d directories in the /etc/network directory instead of modifying /etc/network/interface directly.
The script /etc/network/if-pre-up.d/iptablesload will contain:
#!/bin/sh iptables-restore < /etc/iptables.rules exit 0
and /etc/network/if-post-down.d/iptablessave will contain:
#!/bin/sh iptables-save -c > /etc/iptables.rules if [ -f /etc/iptables.downrules ]; then iptables-restore < /etc/iptables.downrules fi exit 0
Then be sure to give both scripts execute permissions:
sudo chmod +x /etc/network/if-post-down.d/iptablessave
sudo chmod +x /etc/network/if-pre-up.d/iptablesload
Pingback: IPTABLES firewall ruleset config file v2.5