Firewall Using Iptables


FIREWALL: A firewall is a hardware or software solution to enforce security policies. In the physical security analogy, a firewall is equivalent to a door lock on a perimeter door or on a door to a room inside of the building - it permits only authorized users such as those with a key or access card to enter. A firewall has built-in filters that can disallow unauthorized or potentially dangerous material from entering the system. It also logs attempted intrusions.

IPTABLES: In computer networking, "netfilter", along with its companion "iptables", are collectively a software extension to the Linux operating system that implements a stateful firewall framework. It also enables other networking features such as network address translation (NAT). Although netfilter is an extension to Linux, it is included in all major Linux distributions that use the 2.4 or 2.6 kernel. Netfilter does not work with Linux kernels older than version 2.4

About the script: The script below is used to make an effective and strong firewall for the Gateway machines. The script is commented to make it self explanatory. This script is completely done using Iptables.

# iptables, by SysAdmin, 
# description: Script for setting IPTABLES rules for Gateway
# processname: iptables

The below options will make us adjust the script parameters in one shot. If there requires a situation like if we want to swap the eth0 and eth1 for some reason, we can adjust that in the below option rather than adjusting that for the whole script manually. I am using my network configuration in here. So modify this according to your requirements.

INTERNALIF="eth1"                # Internal Ethernet card identifier
INTERNALNET=""         # Internet network address range
INTERNALBCAST=""    # Internal Broadcast address
EXTERNALIF="eth0"                    # External Ethernet card identifier

# Pathnames
DMESG="/bin/dmesg"                        # Location of Dmesg
IPTABLES="/sbin/iptables"                 # Location of Iptables

The section below is used to control the script using “Start” or “Stop” or “Restart” functions just like controlling services of a Linux machine. The script has to be called like in example below

# sh / start
if [ "$1" = "" ]     # this will make the script to exit if no argument is present
        echo "Usage: sh / (start|stop|restart)"
    case "$1" in
            action "Shutting down firewall:" echo
            $IPTABLES -F
            exit 0
            echo "The status command is not supported for iptables"
            exit 0
            $0 stop
            exec $0 start
            echo "Starting Firewall:"
                        echo "Usage: firewall (start|stop|restart)"
                        exit 1

To avoid any conflicts that may arise in the implementation of the Firewall, its better to flush every rules that were actually present in the chains and then to start over.


The below are some tweaks that can be done to SysCtl to avoid make kinds of attacks. They are pretty simple yet effective.

Disabling IP Spoofing attacks:

IP spoofing is one of the most common forms of on-line camouflage. In IP spoofing, an attacker gains unauthorized access to a computer or a network by making it appear that a malicious message has come from a trusted machine by “spoofing” the IP address of that machine.

echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter

The below change will stop the Gateway from responding to broadcast pings.

echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

Block Source Routing:

Source routing allows the sender of the packet to specify the route that a packet must take in traveling to the destination. If the selected route is not available for any reason, the packet would not be delivered. If the recipient replied to the packets, the response would follow the same route. it can be used to discover the IP addresses of routers within a network. However, it also has the potential for misuse. A malicious user could use source routing to learn more about a network that he or she is targeting for attack. Data packets contain information about where they have been and what machines they have transited. A malicious user might send data into a network in order to collect information about the network's topology. Its better to block source routing from the Gateway itself

echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route

Kill timestamps.

echo 0 > /proc/sys/net/ipv4/tcp_timestamps

Trying to prevent SYN flood attacks:

A SYN flood is a form of denial-of-service attack in which an attacker sends a succession of SYN requests to a target's system. One of most important steps is to enable the operating system's built-in protection mechanisms like SYN cookies. In Linux, we can set the SYN Cookies in the following manner.

echo 1 > /proc/sys/net/ipv4/tcp_syncookies

Disable all redirection requests in Gateway machine:

echo 0 >/proc/sys/net/ipv4/conf/all/accept_redirects

The below command enables bad error message protection

echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

#Allow dynamic ip addresses

echo "1" > /proc/sys/net/ipv4/ip_dynaddr

Its recommend to log packets with impossible addresses. This can be done by giving a positive parameter to the following sysctl parameter.

echo 1 > /proc/sys/net/ipv4/conf/all/log_martians

Set a local port range:

By default, the local port range is 32768 to 61000 for all new 2.6 kernel based systems. Its explicitly mentioned in the Firewall script because if we need to increase that further, we can adjust the port range throug the Firewall script itself.

echo "32768 61000" > /proc/sys/net/ipv4/ip_local_port_range

Denial of Service (DoS) attacks: Denial of Service attack is an attempt by a malicious (or unwitting) user, process, or system to prevent legitimate users from accessing a resource (usually a network service) by exploiting a weakness or design limitation in an information system. Examples of DoS attacks include flooding network connections, filling disk storage, disabling ports, or removing power. This can be limited by setting timeouts.

echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 1 > /proc/sys/net/ipv4/tcp_window_scaling
echo 0 > /proc/sys/net/ipv4/tcp_sack
echo 1280 > /proc/sys/net/ipv4/tcp_max_syn_backlog

Basic Rules of a typical Firewall:

Kill INVALID packets with illegal combination flags.

$IPTABLES -A INPUT -m state --state INVALID -j DROP

No restrictions to connections from localhost


Reject connections from Outside world to Internal loop back device.


No restrictions for traffic generating from legit internal addresses


Incase we have to use IPv6 addresses in your environment uncomment the below line:


Kill all packets from Outside world claiming to be packets generated from Internal network.


Block ICMP requests.

$IPTABLES -A FORWARD -p icmp --icmp-type echo-request -o $INTERNALIF -j REJECT

Prevent Ping flood attacks:

$IPTABLES -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
$IPTABLES -A INPUT -p icmp --icmp-type echo-request -j DROP

Deny pings to local broadcast address:


#Allow all other icmp


No restrictions to established connections:


Dont forward SMB related traffic. Samba Services are one of the most aimed targets by hackers.

$IPTABLES -A FORWARD -o $EXTERNALIF -p tcp --dport 137 -j REJECT 
$IPTABLES -A FORWARD -o $EXTERNALIF -p tcp --dport 138 -j REJECT 
$IPTABLES -A FORWARD -o $EXTERNALIF -p tcp --dport 139 -j REJECT 
$IPTABLES -A FORWARD -o $EXTERNALIF -p udp --dport 137 -j REJECT 
$IPTABLES -A FORWARD -o $EXTERNALIF -p udp --dport 138 -j REJECT 
$IPTABLES -A FORWARD -o $EXTERNALIF -p udp --dport 139 -j REJECT 
$IPTABLES -A INPUT -i $EXTERNALIF -p udp --dport 137 -j REJECT
  1. Disable Samba Share
#$IPTABLES -A INPUT -p tcp --dport 137 -j ACCEPT
#$IPTABLES -A INPUT -p udp --dport 137 -j ACCEPT
#$IPTABLES -A INPUT -p tcp --dport 138 -j ACCEPT
#$IPTABLES -A INPUT -p udp --dport 138 -j ACCEPT
#$IPTABLES -A INPUT -p tcp --dport 139 -j ACCEPT
#$IPTABLES -A INPUT -p udp --dport 139 -j ACCEPT

Allow all other connections to be forwarded


Allow replies from established connections :


#Allow yourself to be a DHCP server for your inside network
#Necessary because the default rule allowing valid addresses ignores broadcast

$IPTABLES -A INPUT -i $INTERNALIF -p tcp --sport 68 --dport 67 -j ACCEPT
$IPTABLES -A INPUT -i $INTERNALIF -p udp --sport 68 --dport 67 -j ACCEPT
  1. This section is to allow nameserver packets.
cat /etc/resolv.conf | \
awk '/^nameserver/ {print $2}' | \
xargs -n1 $IPTABLES -A INPUT -p udp --sport 53 -j ACCEPT -s

#From here on, we are dealing with connection attempts. These services are not needed for our Gateway. But just incase we happen to have them up and running, just uncomment and restart the firewall script.

# ftp-data
#$IPTABLES -A INPUT -p tcp  --dport 20 -j ACCEPT

# ftp
#$IPTABLES -A INPUT -p tcp  --dport 21 -j ACCEPT
# ssh 

#$IPTABLES -A INPUT -p tcp --dport 22 -j ACCEPT

#$IPTABLES -A INPUT -p tcp --dport 23 -j ACCEPT

# smtp  One per second limt -burst rate of ten
#$IPTABLES -A INPUT -p tcp --dport 25 --syn -m limit --limit 1/s \
#        --limit-burst 10 -j ACCEPT 
#$IPTABLES -A INPUT -p tcp --dport 25 --syn -j DROP 
#$IPTABLES -A INPUT -p tcp --dport 25 -j ACCEPT

# DNS   
#$IPTABLES -A INPUT -p tcp --dport 53 -j ACCEPT
#$IPTABLES -A INPUT -p udp --dport 53 -j ACCEPT

# http 
$IPTABLES -A INPUT -p tcp --dport 80 -j ACCEPT

# POP-3
#$IPTABLES -A INPUT -p tcp --dport 110 -j ACCEPT

# identd
#$IPTABLES -A INPUT -p tcp --dport 113 -j ACCEPT

# https
#$IPTABLES -A INPUT -p tcp --dport 443 -j ACCEPT

#VNC Server
#$IPTABLES -A INPUT -p tcp --dport 5801 -j ACCEPT
#$IPTABLES -A INPUT -p tcp --dport 5901 -j ACCEPT
#$IPTABLES -A INPUT -p tcp --dport 6001 -j ACCEPT

##Some ports should be denied and logged.

$IPTABLES -A INPUT -p tcp --dport 1433 -m limit -j LOG --log-prefix "Firewalled packet: MSSQL " 
$IPTABLES -A INPUT -p tcp --dport 1433 -j DROP
$IPTABLES -A INPUT -p tcp --dport 6670 -m limit -j LOG --log-prefix "Firewalled packet: Deepthrt " 
$IPTABLES -A INPUT -p tcp --dport 6670 -j DROP
$IPTABLES -A INPUT -p tcp --dport 6711 -m limit -j LOG --log-prefix "Firewalled packet: Sub7 " 
$IPTABLES -A INPUT -p tcp --dport 6711 -j DROP 
$IPTABLES -A INPUT -p tcp --dport 6712 -m limit -j LOG --log-prefix "Firewalled packet: Sub7 " 
$IPTABLES -A INPUT -p tcp --dport 6712 -j DROP
$IPTABLES -A INPUT -p tcp --dport 6713 -m limit -j LOG --log-prefix "Firewalled packet: Sub7 " 
$IPTABLES -A INPUT -p tcp --dport 6713 -j DROP
$IPTABLES -A INPUT -p tcp --dport 12345 -m limit -j LOG --log-prefix "Firewalled packet: Netbus " 
$IPTABLES -A INPUT -p tcp --dport 12345 -j DROP
$IPTABLES -A INPUT -p tcp --dport 12346 -m limit -j LOG --log-prefix "Firewalled packet: Netbus " 
$IPTABLES -A INPUT -p tcp --dport 12346 -j DROP
$IPTABLES -A INPUT -p tcp --dport 20034 -m limit -j LOG --log-prefix "Firewalled packet: Netbus " 
$IPTABLES -A INPUT -p tcp --dport 20034 -j DROP
$IPTABLES -A INPUT -p tcp --dport 31337 -m limit -j LOG --log-prefix "Firewalled packet: BO " 
$IPTABLES -A INPUT -p tcp --dport 31337 -j DROP
$IPTABLES -A INPUT -p tcp --dport 6000  -m limit -j LOG --log-prefix "Firewalled packet: XWin "
$IPTABLES -A INPUT -p tcp --dport 6000  -j DROP

#Traceroutes depend on finding a rejected port. DROP the ones it uses

$IPTABLES -A INPUT -p udp --dport 33434:33523 -j DROP

#Don't log web or ssl because people surfing for long times lose connection tracking and cause the system to create a new one, flooding logs.

$IPTABLES -A INPUT -p tcp --dport 80 -j REJECT
$IPTABLES -A INPUT -p tcp --dport 443 -j REJECT

The below rules will be effective it it doesnt match any of the above rules. A log for all connections will be “noise” and will give us a hard time to find something relevant from the flooded logs. So the rules below just logs connection requests.

$IPTABLES -A INPUT -p tcp --syn -m limit --limit 5/minute -j LOG  --log-prefix "Firewalled packet:"
$IPTABLES -A FORWARD -p tcp --syn -m limit --limit 5/minute -j LOG --log-prefix "Firewalled packet:"


$IPTABLES -A INPUT -p tcp -j REJECT --reject-with tcp-reset

$IPTABLES -A FORWARD -p tcp -j REJECT --reject-with tcp-reset

#Accept it anyway if it's only output


/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 21        # ftp
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 22        # ssh
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 23        # telnet
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 25        # smtp
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 53        # domain
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 79        # finger
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 80        # httpd
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 110       # pop3
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 111       # sunrpc
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 137       # netbios-ns
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 138       # netbios-dgm
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 139       # netbios
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 143       # imap
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 161       # snmp
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 162       # snmp trap
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 443       # https
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 515       # printer
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 1080      # socks
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 2049      # nfs
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 3128      # squid
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 3306      # mysql
/sbin/iptables -A INPUT -j DROP -i eth0 -p tcp --dport 5432      # postgres
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 21        # ftp
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 23        # telnet
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 25        # smtp
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 53        # domain
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 79        # finger
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 110       # pop3
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 111       # sunrpc
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 137       # netbios-ns
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 138       # netbios-dgm
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 139       # netbios
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 143       # imap
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 161       # snmp
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 162       # snmp trap
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 443       # https
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 515       # printer
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 1080      # socks
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 2049      # nfs
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 3128      # squid
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 3306      # mysql
/sbin/iptables -A INPUT -j DROP -i eth0 -p udp --dport 5432      # postgres
  1. this line will prevent people on the internet (or you) from pinging the gateway
/sbin/iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j DROP
exit 0
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.