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

 

4 Comments

  1. Pingback: Port forwarding from one public IP to another public IP | Nova-Labs

  2. I’m using this heavy duty bash script as root for some like 15 minutes:

    curl -s https://www.iblocklist.com/lists.php \
    | grep -A 2 Bluetack \
    | sed -n “s/.*value=’\(http:.*\)’.*/\1/p” \
    | xargs wget -O – \
    | gunzip \
    | egrep -v ‘^#’ > blacklist
    grep -Eo ‘[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}’ blacklist > blacklist-ip
    grep -Eo ‘[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}[-][0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}’ blacklist > blacklist-ip-range
    sed -i -E “s/[-][0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\./\//” blacklist-ip-range

    sort blacklist-ip | uniq -u > blacklist-ip-sorted
    sort blacklist-ip-range | uniq -u > blacklist-ip-range-sorted
    while read IPADDR
    do
    route add $IPADDR gw 127.0.0.1 lo &
    done < blacklist-ip-range-sorted

    while read IPADDR
    do
    route add $IPADDR gw 127.0.0.1 lo &
    done < blacklist-ip-sorted

    rm blacklist-ip
    rm blacklist-ip-sorted
    rm blacklist-ip-range
    rm blacklist-ip-range-sorted

  3. Jonny5

    Interesting using route to terminate outbound communication. What would happen if a packet from those IPs would come into this host? Would it be refused or rerouted the same way or would a packet just not get back to where it came from?

    Also like how you scrape their site and download the individual files and pipe it all to out put based on ranges and individuals. You could probably do this with ipset lists as well, can I use your grabber bit of code, also, great sed and grep use!

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.