Simple iptables firewall script with NAT and SFQ sceduling

I have been working with firewalls and security for quite many years at this point. Therefore friends and people I know ask me every now and then to write a firewall script for them. So instead of basically writing the same script over and over again I decided to write this article that explains how you can set up a basic iptables box by yourself.

If you do not know what iptables is the best way to start is to do some reading:

Wikipedia about iptables
Home of iptables/netfilter

In its most basic form iptables has three (3) built in tables. These tables are INPUT, OUTPUT and FORWARD

INPUT: Packets that are destined to a interface and/or address of your host
OUTPUT: Packets that origin from a interface and/or address of your host
FORWARD: Packets that pass through your hosts interfaces and/or addresses

To set up a linux router/firewall/NAT box you need a computer with at least two network interfaces. One interface for the internal network and one for the external network (usually the internet). You also need to install linux on that computer ;)

There are many networking features besides firewall and NAT in Linux. There are things like TC. With the tc command your can configure the packet queuing mechanism of your network interfaces. The default mechanism is FIFO which stands for FirstInFirstOut.  I recommend that you change the queuing mechanism of your external network interface from FIFO to SFQ.

Stochastic Fairness Queueing reorders  queued  traffic  so  each ’session’ gets to send a packet in turn.

You can enable SFQ by entering the following into a terminal as root: tc qdisc add dev <your external NIC here> root sfq perturb 10

You can put the example above into your /etc/rc.local or some other start up file in order for it to be run at each boot.

Now you just need a small shell script which configures iptables for you. It is a good idea to execute this script on boot via the init procedure of your Linux distribution.

I hope that the script is somewhat self explaining. If you have questions about it please feel free to comment this post.

#!/bin/bash
 
#Setting up some Variables #####################################################
EXTIP="<your external ip goes here>"          # Example 1.2.3.4
INTNET="<your internal network goes here>"    # Example 192.168.1.0/24
EXTIF="<your external NIC>"                   # Example eth0
INTIF="<your internal NIX>"                   # Example eth1
 
#Disabling ipforwarding aka routing ############################################
echo 0 > /proc/sys/net/ipv4/ip_forward
 
#Flushing tables and setting policys ###########################################
iptables -F
iptables -t nat -F PREROUTING
iptables -t nat -F POSTROUTING
iptables -t mangle -F
iptables -P FORWARD DROP
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT  -i lo -j ACCEPT
 
# INPUT from local network #####################################################
iptables -A INPUT -i $INTIF -s $INTNET -j ACCEPT
iptables -A INPUT -i $INTIF -p udp --dport 67 --sport 68 -j ACCEPT
 
# Dropping private addresses on the external interface ########################
iptables -A INPUT -i $EXTIF -s 10.0.0.0/8 -j DROP
iptables -A INPUT -i $EXTIF -s 172.16.0.0/12 -j DROP
iptables -A INPUT -i $EXTIF -s 192.168.0.0/16 -j DROP
iptables -A INPUT -i $EXTIF -s 169.254.0.0/16 -j DROP
iptables -A INPUT -i ! lo -s 127.0.0.0/8 -j DROP
 
# INPUT from external networks #################################################
# The example below allows traffic to a webserver that runs on your NAT box
# iptables -A INPUT -d $EXTIP -p tcp --dport 80 --sport 1024:65535 -j ACCEPT
 
# ICMP from external networks ##################################################
iptables -A INPUT -i $EXTIF -d $EXTIP -p icmp --icmp-type \
destination-unreachable -j ACCEPT
iptables -A INPUT -i $EXTIF -d $EXTIP -p icmp --icmp-type \
source-quench -j ACCEPT
iptables -A INPUT -i $EXTIF -d $EXTIP -p icmp --icmp-type \
time-exceeded -j ACCEPT
iptables -A INPUT -i $EXTIF -d $EXTIP -p icmp --icmp-type \
parameter-problem -j ACCEPT
iptables -A INPUT -i $EXTIF -d $EXTIP -p icmp --icmp-type \
echo-request -m limit --limit 2/second --limit-burst 5 -j ACCEPT
 
# Allowing all traffic that is related to our traffic :) aka STATEFUL ##########
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
 
# FORWARD between internal and external network ################################
iptables -A FORWARD -i $INTIF -o $EXTIF -s $INTNET -d ! $INTNET -j ACCEPT
iptables -A FORWARD -i $EXTIF -s ! $INTNET -d $INTNET \
-m state --state RELATED,ESTABLISHED -j ACCEPT
 
# MASQUERADING aka NAT #########################################################
iptables -t nat -A POSTROUTING -o $EXTIF -s $INTNET -d ! $INTNET -j MASQUERADE
 
# Enabling stuff in /proc ######################################################
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo 1 > /proc/sys/net/ipv4/conf/$EXTIF/log_martians
echo 0 > /proc/sys/net/ipv4/conf/$EXTIF/accept_redirects
echo 0 > /proc/sys/net/ipv4/conf/$EXTIF/accept_source_route
 
# Enabling anti Spoofing #######################################################
if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ]; then
  for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
    echo 1 > $f
  done
else
  echo
  echo "PROBLEMS SETTING UP IP SPOOFING PROTECTION.  BE WORRIED."
  echo
fi
 
# Enabling ipforwarding aka routing ############################################
echo 1 > /proc/sys/net/ipv4/ip_forward
 
# Linsing rules ################################################################
iptables -L -n -v
iptables -t nat -L -n -v
Feb 10th, 2009 | Posted in Computers
No comments yet.

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">