Re-edit: the IPSet wasn’t working the way it should’ve on further inspection, I’ve fixed that, plus, some of my rules were hastily copied and I’ve fixed that too.
Edit: I had the order of this incorrect in the beginning, for that I appologize, it is correct now. If you don’t have your IPSet list setup, IPTables won’t be able to create the rule using it. So, I re-ordered it to walk you through creating the blocklist first.
For me, this guide and scripts have been a work in progress and at its current iteration, version 2.6.1, it has features that I’ve tested, features I’ve modified due to causing issues with hosted services, and the newest feature that I’ve just begun testing, the blocklist via ipset. The ipset tool is great, allows you to make lists of IPv4 or IPv6 addresses and work with them in iptables or another program.
This started as a way for me to maintain a safe hosting environment and operate a hardened server. Turns out many firewall configurations don’t enable egress filtering, mine does. This is actually a massive security improvement and the value cannot be overstated.
If you are running Ubuntu like me, this is basically written for you. There are a couple commands and some configuration locations that are Ubuntu specific, to anyone running something else, you will have to figure out how to change the install and scripting process to meet your needs on your own. Best wishes and best of luck!
Let’s get to the details.
Blocklist Automatic Update
This ruleset uses ipset, and you will need to install it to use it.
sudo apt-get install ipset
You will need to make the list now, here is how that works: (thank you: http://adityamukho.com)
sudo ipset create blacklist hash:ip hashsize 4096 maxelem 1048576
Here is the script that you can put in a cron folder (hourly or daily) or add to your crontab to auto grab a blacklist/blocklist/shunlist and import it into your list. It is important like all things in your /etc folder, you
sudo chown root:root $filename
and to make it executable
sudo chmod +x $filename
File: makeblocklist.sh
#!/bin/bash # Jim McKibben # AutoShun.org IPTables Blocklist Importer wget -O /tmp/shunlist.csv http://autoshun.org/files/shunlist.csv cat /tmp/shunlist.csv | egrep -o '^([0-9]{1,3}\.){3}[0-9]{1,3}' > /tmp/blocklist.txt while read IP; do sudo ipset add blacklist $IP done < /tmp/blocklist.txt
IPTables Config
File: iptablesconfv261.sh
#!/bin/sh # Jim McKibben # 2015-01-11 # Version 2.6.2 # Iptables Firewall configuration script # Allows HTTP, HTTPS, SSH, SMTP # SSH Port easy customization # 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 # Report logged HTTPs usage - HTTPs IPv6 disabled # DOS SSH # Logging # Admin IP / Monitoring Section # IPv6 support # IPSET Blocklist Support # Fixed SRC/DST Admin # Allowed blocklist response IPT=/sbin/iptables IP6T=/sbin/ip6tables ADMIN="0.0.0.0" ADMINSUBNET01="0.0.0.0/32" ADMINSUBNET02="0.0.0.0/32" ADMINSUBNET03="" SSHPORT="22" echo "Enabling Firewall" # IPv4 rules # Specialty IPs # These IPs will be allowed to ping # They won't have to worry about DDoS rulesets #$IPT -N ADMIN_IP #$IPT -A ADMIN_IP -p tcp -m multiport --sports $SSHPORT,25,80,443,10050,10051 -j ACCEPT #$IPT -A ADMIN_IP -p tcp -m multiport --dports $SSHPORT,25,80,443,10050,10051 -j ACCEPT #$IPT -A ADMIN_IP -i eth0 -p icmp --icmp-type destination-unreachable -m limit --limit 1/s --limit-burst 1 -j ACCEPT #$IPT -A ADMIN_IP -i eth0 -p icmp --icmp-type time-exceeded -m limit --limit 1/s --limit-burst 1 -j ACCEPT #$IPT -A ADMIN_IP -i eth0 -p icmp --icmp-type echo-reply -m limit --limit 1/s --limit-burst 1 -j ACCEPT #$IPT -A ADMIN_IP -i eth0 -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 1 -j ACCEPT #$IPT -A ADMIN_IP -i eth0 -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix "iptables: PING-DROP: " #$IPT -A ADMIN_IP -i eth0 -p icmp -j DROP # DUMP $IPT -N DUMP > /dev/null $IPT -F DUMP $IPT -A DUMP -p tcp -j LOG --log-prefix "iptables: tcp: " $IPT -A DUMP -p udp -j LOG --log-prefix "iptables: udp: " $IPT -A DUMP -p tcp -j REJECT --reject-with tcp-reset $IPT -A DUMP -p udp -j REJECT --reject-with icmp-port-unreachable $IPT -A DUMP -j DROP # Blocking excessive syn packet $IPT -N SYN_FLOOD $IPT -A INPUT -p tcp --syn -j SYN_FLOOD $IPT -A SYN_FLOOD -m limit --limit 1/s --limit-burst 3 -j RETURN $IPT -A SYN_FLOOD -j DROP # Stateful table #$IPT -N STATEFUL > /dev/null #$IPT -F STATEFUL #$IPT -I STATEFUL -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT #$IPT -A STATEFUL -m conntrack --ctstate NEW -i !eth0 -j ACCEPT #$IPT -A STATEFUL -j DUMP # Loopback rules $IPT -A INPUT -i lo -j ACCEPT $IPT -A INPUT -i !lo -d 127.0.0.0/8 -j REJECT $IPT -A OUTPUT -o lo -j ACCEPT $IPT -A OUTPUT -o !lo -d 127.0.0.0/8 -j REJECT # Admin IPs Version 2 $IPT -A INPUT -s $ADMIN -j ACCEPT $IPT -A OUTPUT -d $ADMIN -j ACCEPT $IPT -A INPUT -s $ADMINSUBNET01 -j ACCEPT $IPT -A OUTPUT -d $ADMINSUBNET01 -j ACCEPT $IPT -A INPUT -s $ADMINSUBNET02 -j ACCEPT $IPT -A OUTPUT -d $ADMINSUBNET02 -j ACCEPT # IPSET Input Blocklist - logs block and responds with port unreachable $IPT -A INPUT -m set --match-set blacklist src -j LOG --log-prefix "IP Blacklist: " $IPT -A INPUT -m set --match-set blacklist src -j REJECT --reject-with icmp-port-unreachable # IPSET Output Blocklist - allows reject packet to be sent with no log but no further communication $IPT -A OUTPUT -m set --match-set blacklist dst -p icmp --icmp-type port-unreachable -j ACCEPT $IPT -A OUTPUT -m set --match-set blacklist dst -j LOG --log-prefix "IP Blacklist: " $IPT -A OUTPUT -m set --match-set blacklist dst -j REJECT --reject-with icmp-port-unreachable # Block # drop reserved addresses incoming (these are reserved addresses) # but may change soon $IPT -A INPUT -i eth0 -s 0.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 1.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 2.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 5.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 7.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 10.0.0.0/8 -j DUMP # Mostly US Commercial IP space, Google Fiber, and Business ISPs #$IPT -A INPUT -i eth0 -s 23.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 27.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 31.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 36.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 39.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 41.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 42.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 58.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 59.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 60.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 127.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 169.254.0.0/16 -j DUMP $IPT -A INPUT -i eth0 -s 172.16.0.0/12 -j DUMP $IPT -A INPUT -i eth0 -s 192.168.0.0/16 -j DUMP $IPT -A INPUT -i eth0 -s 197.0.0.0/8 -j DUMP $IPT -A INPUT -i eth0 -s 224.0.0.0/3 -j DUMP $IPT -A INPUT -i eth0 -s 240.0.0.0/8 -j DUMP # drop reserved addresses incoming (these are reserved addresses) # but may change soon $IPT -A OUTPUT -o eth0 -d 0.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 1.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 2.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 5.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 7.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 10.0.0.0/8 -j DUMP # Mostly US Commercial IP space, Google Fiber, and Business ISPs #$IPT -A OUTPUT -o eth0 -d 23.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 27.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 31.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 36.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 39.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 41.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 42.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 58.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 59.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 60.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 127.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 169.254.0.0/16 -j DUMP $IPT -A OUTPUT -o eth0 -d 172.16.0.0/12 -j DUMP $IPT -A OUTPUT -o eth0 -d 192.168.0.0/16 -j DUMP $IPT -A OUTPUT -o eth0 -d 197.0.0.0/8 -j DUMP $IPT -A OUTPUT -o eth0 -d 224.0.0.0/3 -j DUMP $IPT -A OUTPUT -o eth0 -d 240.0.0.0/8 -j DUMP # Allow certain inbound ICMP types (ping, traceroute..) $IPT -A INPUT -i eth0 -p icmp --icmp-type destination-unreachable -m limit --limit 1/s --limit-burst 1 -j ACCEPT $IPT -A INPUT -i eth0 -p icmp --icmp-type time-exceeded -m limit --limit 1/s --limit-burst 1 -j ACCEPT $IPT -A INPUT -i eth0 -p icmp --icmp-type echo-reply -m limit --limit 1/s --limit-burst 1 -j ACCEPT $IPT -A INPUT -i eth0 -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 1 -j ACCEPT $IPT -A INPUT -i eth0 -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix "iptables: PING-DROP: " $IPT -A INPUT -i eth0 -p icmp -j DROP # Drop all packets to port 111 except those from localhost $IPT -A INPUT ! -s 127.0.0.0/8 -p tcp --dport 111 -j REJECT --reject-with tcp-reset # kill off identd quick $IPT -A INPUT -i eth0 -p tcp --dport 113 -j REJECT --reject-with tcp-reset # Allow all established, related in #$IPT -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 $IPT -A INPUT -i eth0 -p tcp -m tcp --dport $SSHPORT -m conntrack --ctstate NEW -m recent --set --name DEFAULT --rsource $IPT -A INPUT -i eth0 -p tcp -m tcp --dport $SSHPORT -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 $SSHPORT : " $IPT -A INPUT -i eth0 -p tcp -m tcp --dport $SSHPORT -m conntrack --ctstate NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j REJECT $IPT -A INPUT -i eth0 -p tcp -m tcp --dport $SSHPORT -m conntrack --ctstate NEW -j ACCEPT # Inbound ESTABLISHED SSH (out is in Multi-out) $IPT -A INPUT -i eth0 -p tcp --dport $SSHPORT -m conntrack --ctstate ESTABLISHED -j ACCEPT # DOS HTTP Attack prevention # Need re-evaluation, the current rates do not allow for WordPress image upload features # Plus, the timings reportedly slows down current site browsing to an unusable level - hence the commented out "DROP" $IPT -A INPUT -i eth0 -p tcp --dport 80 -m limit --limit 45/minute --limit-burst 300 -j ACCEPT $IPT -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 $IPT -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT $IPT -A INPUT -i eth0 -p tcp --dport 443 -m limit --limit 45/minute --limit-burst 300 -j ACCEPT $IPT -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 $IPT -A INPUT -i eth0 -p tcp --dport 443 -j ACCEPT # Allow Ping from Outside to Inside $IPT -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT # Multi-out for inbound SSH, HTTP, and HTTPS $IPT -A OUTPUT -o eth0 -p tcp -m multiport --sports $SSHPORT,80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Outbound SSH $IPT -A INPUT -i eth0 -p tcp --sport $SSHPORT -m conntrack --ctstate ESTABLISHED -j ACCEPT $IPT -A OUTPUT -o eth0 -p tcp --dport $SSHPORT -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Allow inbound DNS #$IPT -A INPUT -i eth0 -p udp --sport 1024:65535 --dport 53 -j ACCEPT #$IPT -A OUTPUT -p udp --sport 53 --dport 1024:65535 -j ACCEPT # Allow outbound DNS $IPT -A INPUT -i eth0 -p udp --dport 1024:65535 --sport 53 -j ACCEPT $IPT -A OUTPUT -p udp --dport 53 --sport 1024:65535 -j ACCEPT # Outbound HTTP, and HTTPS $IPT -A OUTPUT -o eth0 -p tcp --dport 80 --sport 1024:65535 -j ACCEPT $IPT -A INPUT -i eth0 -p tcp --dport 1024:65535 --sport 80 -j ACCEPT $IPT -A OUTPUT -o eth0 -p tcp --dport 443 --sport 1024:65535 -j ACCEPT $IPT -A INPUT -i eth0 -p tcp --dport 1024:65535 --sport 443 -j ACCEPT # Inbound SMTP #$IPT -A INPUT -i eth0 -p tcp --sport 1024:65535 --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT #$IPT -A OUPUT -o eth0 -p tcp --sport 25 --dport 1024:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Outbound SMTP #$IPT -A INPUT -i eth0 -p tcp --sport 25 --dport 1024:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT #$IPT -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Allow rsync from a specific network #$IPT -A INPUT -i eth0 -p tcp -s 192.168.101.0/24 --dport 873 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT #$IPT -A OUTPUT -o eth0 -p tcp --sport 873 -m conntrack --ctstate ESTABLISHED -j ACCEPT # Allow SVN #$IPT -A INPUT -i eth0 -p tcp --dport 3690 --sport 1024:65535 -j ACCEPT #$IPT -A OUTPUT -o eth0 -p tcp --sport 3690 --dport 1024:65535 -j ACCEPT #$IPT -A INPUT -i eth0 -p tcp --dport 3667 --sport 1024:65535 -j ACCEPT #$IPT -A OUTPUT -o eth0 -p tcp --sport 3667 --dport 1024:65535 -j ACCEPT # Allow all related #$IPT -A OUTPUT -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Don't log route packets coming from routers - too much logging $IPT -A INPUT -i eth0 -p udp --dport 520 -j REJECT # Don't log smb/windows sharing packets - too much logging $IPT -A INPUT -i eth0 -p tcp --dport 137:139 -j REJECT $IPT -A INPUT -i eth0 -p udp --dport 137:139 -j REJECT # All policies set to DROP $IPT --policy INPUT DROP $IPT --policy OUTPUT DROP $IPT --policy FORWARD DROP #$IPT --policy ADMIN_IP DROP # IPv6 rules # Specialty IPs # These IPs will be allowed to ping # They won't have to worry about DDoS rulesets $IP6T -N ADMIN_IP #$IP6T -A ADMIN_IP -p tcp -m multiport --sports $SSHPORT,25,80,443,10050,10051 -j ACCEPT #$IP6T -A ADMIN_IP -p tcp -m multiport --dports $SSHPORT,25,80,443,10050,10051 -j ACCEPT #$IP6T -A ADMIN_IP -i eth0 -p icmp --icmp-type destination-unreachable -m limit --limit 1/s --limit-burst 1 -j ACCEPT #$IP6T -A ADMIN_IP -i eth0 -p icmp --icmp-type time-exceeded -m limit --limit 1/s --limit-burst 1 -j ACCEPT #$IP6T -A ADMIN_IP -i eth0 -p icmp --icmp-type echo-reply -m limit --limit 1/s --limit-burst 1 -j ACCEPT #$IP6T -A ADMIN_IP -i eth0 -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 1 -j ACCEPT #$IP6T -A ADMIN_IP -i eth0 -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix "iptables: PING-DROP: " #$IP6T -A ADMIN_IP -i eth0 -p icmp -j DROP # DUMP $IP6T -N DUMP > /dev/null $IP6T -F DUMP $IP6T -A DUMP -p tcp -j LOG --log-prefix "ip6tables: tcp: " $IP6T -A DUMP -p udp -j LOG --log-prefix "ip6tables: udp: " $IP6T -A DUMP -p tcp -j REJECT --reject-with tcp-reset $IP6T -A DUMP -p udp -j REJECT --reject-with icmp-port-unreachable $IP6T -A DUMP -j DROP # Add Admin IPs to INPUT Chain #$IP6T -A INPUT -s $ADMINV6 -j ADMIN_IP #$IP6T -A OUTPUT -d $ADMINV6 -j ADMIN_IP # Blocking excessive syn packet $IP6T -N SYN_FLOOD $IP6T -A INPUT -p tcp --syn -j SYN_FLOOD $IP6T -A SYN_FLOOD -m limit --limit 1/s --limit-burst 3 -j RETURN $IP6T -A SYN_FLOOD -j DROP # Stateful table #$IP6T -N STATEFUL > /dev/null #$IP6T -F STATEFUL #$IP6T -I STATEFUL -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT #$IP6T -A STATEFUL -m conntrack --ctstate NEW -i !eth0 -j ACCEPT #$IP6T -A STATEFUL -j DUMP # Loopback rules $IP6T -A INPUT -i lo -j ACCEPT $IP6T -A INPUT -i !lo -d ::1 -j REJECT $IP6T -A OUTPUT -o lo -j ACCEPT $IP6T -A OUTPUT -o !lo -d ::1 -j REJECT # Block # Drop reserved addresses incoming (these are reserved addresses) # but may change soon #$IP6T -A INPUT -i eth0 -s ::1 -j DUMP # Drop reserved addresses outgoing (these are reserved addresses) # but may change soon #$IP6T -A OUTPUT -o eth0 -d ::1 -j DUMP # Allow certain inbound ICMP types (ping, traceroute..) $IP6T -A INPUT -i eth0 -p icmp --icmp-type destination-unreachable -m limit --limit 1/s --limit-burst 1 -j ACCEPT $IP6T -A INPUT -i eth0 -p icmp --icmp-type time-exceeded -m limit --limit 1/s --limit-burst 1 -j ACCEPT $IP6T -A INPUT -i eth0 -p icmp --icmp-type echo-reply -m limit --limit 1/s --limit-burst 1 -j ACCEPT $IP6T -A INPUT -i eth0 -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 1 -j ACCEPT $IP6T -A INPUT -i eth0 -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix "ip6tables: PING-DROP: " $IP6T -A INPUT -i eth0 -p icmp -j DROP # Drop all packets to port 111 except those from localhost $IP6T -A INPUT ! -s ::1 -p tcp --dport 111 -j REJECT --reject-with tcp-reset # kill off identd quick $IP6T -A INPUT -i eth0 -p tcp --dport 113 -j REJECT --reject-with tcp-reset # Allow all established, related in #$IP6T -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 $IP6T -A INPUT -i eth0 -p tcp -m tcp --dport $SSHPORT -m conntrack --ctstate NEW -m recent --set --name DEFAULT --rsource $IP6T -A INPUT -i eth0 -p tcp -m tcp --dport $SSHPORT -m conntrack --ctstate NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j LOG -m limit --limit 20/m --log-prefix "ip6tables: SSH Attempt on port $SSHPORT : " $IP6T -A INPUT -i eth0 -p tcp -m tcp --dport $SSHPORT -m conntrack --ctstate NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j REJECT $IP6T -A INPUT -i eth0 -p tcp -m tcp --dport $SSHPORT -m conntrack --ctstate NEW -j ACCEPT # Inbound ESTABLISHED SSH (out is in Multi-out) $IP6T -A INPUT -i eth0 -p tcp --dport $SSHPORT -m conntrack --ctstate ESTABLISHED -j ACCEPT # DOS HTTP Attack prevention # For this, no one seems to be using IPv6 for legitimet browsing, so, I've been disabling it #$IP6T -A INPUT -i eth0 -p tcp --dport 80 -m limit --limit 45/minute --limit-burst 300 -j ACCEPT #$IP6T -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 $IP6T -A INPUT -i eth0 -p tcp --dport 80 -j DROP #$IP6T -A INPUT -i eth0 -p tcp --dport 443 -m limit --limit 45/minute --limit-burst 300 -j ACCEPT #$IP6T -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 $IP6T -A INPUT -i eth0 -p tcp --dport 443 -j DROP # Allow Ping from Outside to Inside $IP6T -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT # Multi-out for inbound SSH, HTTP, and HTTPS $IP6T -A OUTPUT -o eth0 -p tcp -m multiport --sports $SSHPORT,80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Outbound SSH $IP6T -A INPUT -i eth0 -p tcp --sport $SSHPORT -m conntrack --ctstate ESTABLISHED -j ACCEPT $IP6T -A OUTPUT -o eth0 -p tcp --dport $SSHPORT -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Allow inbound DNS #$IP6T -A INPUT -i eth0 -p udp --sport 1024:65535 --dport 53 -j ACCEPT #$IP6T -A OUTPUT -p udp --sport 53 --dport 1024:65535 -j ACCEPT # Allow outbound DNS $IP6T -A INPUT -i eth0 -p udp --dport 1024:65535 --sport 53 -j ACCEPT $IP6T -A OUTPUT -p udp --dport 53 --sport 1024:65535 -j ACCEPT # Outbound HTTP, and HTTPS $IP6T -A OUTPUT -o eth0 -p tcp --dport 80 --sport 1024:65535 -j ACCEPT $IP6T -A INPUT -i eth0 -p tcp --dport 1024:65535 --sport 80 -j ACCEPT $IP6T -A OUTPUT -o eth0 -p tcp --dport 443 --sport 1024:65535 -j ACCEPT $IP6T -A INPUT -i eth0 -p tcp --dport 1024:65535 --sport 443 -j ACCEPT # Inbound SMTP #$IP6T -A INPUT -i eth0 -p tcp --sport 1024:65535 --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT #$IP6T -A OUPUT -o eth0 -p tcp --sport 25 --dport 1024:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Outbound SMTP #$IP6T -A INPUT -i eth0 -p tcp --sport 25 --dport 1024:65535 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT #$IP6T -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Allow rsync from a specific network #$IP6T -A INPUT -i eth0 -p tcp -s 192.168.101.0/24 --dport 873 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT #$IP6T -A OUTPUT -o eth0 -p tcp --sport 873 -m conntrack --ctstate ESTABLISHED -j ACCEPT # Allow SVN #$IP6T -A INPUT -i eth0 -p tcp --dport 3690 --sport 1024:65535 -j ACCEPT #$IP6T -A OUTPUT -o eth0 -p tcp --sport 3690 --dport 1024:65535 -j ACCEPT #$IP6T -A INPUT -i eth0 -p tcp --dport 3667 --sport 1024:65535 -j ACCEPT #$IP6T -A OUTPUT -o eth0 -p tcp --sport 3667 --dport 1024:65535 -j ACCEPT # Allow all related #$IP6T -A OUTPUT -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Don't log route packets coming from routers - too much logging $IP6T -A INPUT -i eth0 -p udp --dport 520 -j REJECT # Don't log smb/windows sharing packets - too much logging $IP6T -A INPUT -i eth0 -p tcp --dport 137:139 -j REJECT $IP6T -A INPUT -i eth0 -p udp --dport 137:139 -j REJECT # All policies set to DROP $IP6T --policy INPUT DROP $IP6T --policy OUTPUT DROP $IP6T --policy FORWARD DROP #$IP6T --policy ADMIN_IP DROP
You will need to
sudo chmod +x $filename
and then
sudo ./$filename
to install the IPTables configuration. It may show a few errors, and if it shows many and/or you
sudo iptables -L -v -n --line-numbers
and there aren't any results, you may need greater access to your kernel. I had to upgrade to a more "real" host from my provider to be able to enable the LOG options among others.
Credit for this next section goes directly to Ubuntu at https://help.ubuntu.com/community/IptablesHowTo, well done guys! I should mention that I have modified this a bit to allow for ipset lists and in that, you will have to install ipset to use them as already mentioned above.
Configuration on startup and shutdown
(keep your lists/config!)
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 # ipset load happens first #ipset restore < /etc/ipset/ipset.blacklist.list # ipset doesn't restore like iptables does, we've fixed that issue with this ipset create blacklist hash:ip hashsize 4096 maxelem 1048576 sed -i '1d' /etc/ipset/ipset.blacklist.list sed -i 's/add\sblacklist\s//' /etc/ipset/ipset.blacklist.list while read IP; do sudo ipset add blacklist $IP done < /etc/ipset/ipset.blacklist.list # then we can load the iptables rules iptables-restore < /etc/iptables.rules exit 0
and /etc/network/if-post-down.d/iptablessave will contain:
#!/bin/sh # ipset save happens first sh -c "ipset save blacklist > /etc/ipset/ipset.blacklist.list" # iptables save happens next sh -c "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
Now you've got a firewall that stays over reboot, and is strongly configured! Please comment and let me know how it works for you. I'm particularly interested if you changed anything to improve functionality of existing services levels, added any well typed/complete protocol/service listings, and/or hardened it any further.
This guide is offered for free, but if you require assistance, I'd be happy to do so but will require a reasonable donation (see above in the About section).
Running into trouble or just trouble shooting your firewall config
Here is a very helpful script to clear all firewall configurations back to square one.
File: fw.stop
#!/bin/sh echo "Stopping firewall and allowing everyone..." iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -t mangle -F iptables -t mangle -X iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT
René Tool
Pingback: Port forwarding from one public IP to another public IP | Nova-Labs
Stanislav Panayotov
Jonny5