Personal tools
You are here: Home firewall

firewall

by Administrator last modified 2008-06-19 15:26

Linux firewall designed by Dan Shearer

Click here to get the file

Size 9.9 kB - File type text/x-sh

File contents

#!/bin/sh
#
# Server firewall template
# (c) Dan Shearer 2002-2008 dan@shearer.org
# Latest version http://shearer.org/Linux_Firewall_Template
# Under the GPL version 3.0 or higher.
#
# Version 1.2

# Customised by Simon Faulkner
# http://dpnet.co.uk

#
# Too many servers have no firewall at all. There is no excuse for thinking that a network
# behind a firewall is safe: every client and server should be running a firewall.
#
# This is a template host firewall for Linux 2.4.x, x > 6 and 2.6.x kernels
# The intent is that the host should be free to do what it needs to do such
# as serve web pages, database requests or print requests and everything else should
# be blocked. There should be no loss in functionality: if you really know what your
# server is doing then you ought not to get nasty surprises when you block access to 
# unused ports. (But, assume that if you don't test this carefully then you will get
# nasty surprises!)
#
# You will certainly need to tweak this script for your server. It is a template, not
# a solution. If you have lots of servers, consider using the same script on each one with 
# environment variables or commandline parameters to determine which workload a particular
# server is running. 
#
# The concept of "defence in depth" means that this firewall is just part of a 
# multilayered approach to security. It should be much better than an unsecured server, but 
# if you put too much faith in it the result will actually be worse :-) It is better than 
# a firewall generated by an automated tool in the sense that there's a better chance you know 
# what is going on if you've worked through deploying this script.
#
# How to use:
#
#  1. Try to be reasonably sure that your host server is not already compromised. There
#     are many ways of doing this; do a lot of reading and/or pay a security consultant if 
#     you don't know them.
#
# 2. Consider how you are going to get back in to your server during testing of this script
#    when you accidentally lock yourself out. Maybe a cron job to disable firewalling,
#    maybe serial console access, whatever. It can be very frustrating to run this script and

# 3. Enable a few things in your kernel, or, run this script and see if you get errors about
#    missing kernel functionality. The things you want enabled are at least:
#
#       CONFIG_PACKET
#       CONFIG_NETFILTER
#       CONFIG_IP_NF_CONNTRACK
#       CONFIG_IP_NF_FTP
#       CONFIG_IP_NF_IRC
#       CONFIG_IP_NF_IPTABLES
#       CONFIG_IP_NF_FILTER
#       CONFIG_IP_NF_NAT
#       CONFIG_IP_NF_MATCH_STATE
#       CONFIG_IP_NF_TARGET_LOG
#       CONFIG_IP_NF_MATCH_LIMIT
#       CONFIG_IP_NF_TARGET_MASQUERADE 
#
# 4. Do lots of testing, running with 'sh -x'. Does it work after a reboot? A kernel or distribution refresh?
#
# 5. Consider putting this script in you /etc/init.d directory so it starts when your machine 
#    starts . In Debian or Ubuntu, copy it to /etc/init.d/filename, then run 
#    ''chmod 700 filename'' followed by ''update-rc.d filename defaults''
#
# 6. Add a test in your machine monitoring system (eg Nagios) that fails if you can get through on a port 
#    that should be blocked. There all sorts of silly reasons why perfectly good firewalls
#    get deactivated. Since everything continues to work nobody notices!
#
#
# What this script does:
#
#   * Locks down eth0, leaves eth1 wide open except for kernel protections. That's for the 
#     case where eth1 is on some special network etc.. not a good idea but a lot of people
#     do have multihomed servers and want different rules on different interfaces, so for
#     simplicity this template assumes the second network is completely trusted. If you only have
#     one ethernet card delete references to eth1. If you have completely different card ids you
#     can change them in the variable definitions at the top.
#
#   * Drops all traffic except whitelisted packets, in this case for web, email and ssh
#  
#   * Accepts incoming traffic unconditionally provided the traffic is related to a previously
#     accepted packet. This connection state tracking saves a lot of rule writing and debugging
#
#   * Drops certain packets at the Linux stack level (before iptables sees them) if they
#     are obviously bad (eg spoofed to appear as if they come from this host.)

PRIME=212.100.249.237
TIERCE=89.16.162.32/24
MPFH=81.187.157.70/25
SHEARER=210.10.97.33
VALLEYT=80.177.74.222

#Can replace with iptables6 
IPTABLES="/sbin/iptables"

#Clear everything
$IPTABLES -F
#Cut the cables!
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP

#### IP stack protections
#### One of the many holes in this firewall is that no actions is taken if
#### can't mount /proc, modprobe an iptables module etc. Fine for a template :-)

#### No icmp ratelimits -- worth adding but not quite the same syntax between 2.4 and 2.6.

# this is a multihomed machine and it isn't a router, so stop it forwarding packets
echo "0" > /proc/sys/net/ipv4/ip_forward 

# stops people mapping the network with trivial broadcast pings. Of course nmap has 
# other ways to do this!
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

# drop source routed packets
for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do
  echo 0 > $f
done

# synflood control
echo 1 > /proc/sys/net/ipv4/tcp_syncookies

# hosts shouldn't send icmp redirects (routers do that.) Hosts
# accept redirects though.
for f in /proc/sys/net/ipv4/conf/*/send_redirects; do
  echo 0 > $f
done

# drop spoofed packets
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
  echo 1 > $f
done

#### end IP stack protections

# Main public LAN address
#INET_IP="x.x.x.x"
# On Debian-derived distros you can also do this:
 INET_IP=`grep 'address ' /etc/network/interfaces | awk '{print $2}'`
INET_IFACE="eth0"
# Secondary LAN address, illustrating how to deal with another interface.
# If you don't have one, remove all lines that refer to INET2_IFACE and INET2_IP.
# If you comment only these lines out, you may be confused by errors later on although
# the firewall will not be affected.
#INET2_IP="y.y.y.y"
#INET2_IFACE="eth1"

# Clear all chains (but not policies; this is a race condition)
$IPTABLES -X

modprobe ip_tables
modprobe ip_conntrack
modprobe ipt_state

# Make some chains

$IPTABLES -N bad_tcp
$IPTABLES -N allowed
$IPTABLES -N icmpin
$IPTABLES -N tcpin
$IPTABLES -N udpin

#### start iptables rules

#Loopback - open
$IPTABLES -A INPUT -p ALL -i lo -j ACCEPT
$IPTABLES -A OUTPUT -p ALL -o lo -j ACCEPT

#Allow local connections to local interfaces
$IPTABLES -A INPUT -p ALL -i $INET_IFACE -s $INET_IP -j ACCEPT
#$IPTABLES -A INPUT -p ALL -i $INET2_IFACE -s $INET2_IP -j ACCEPT

#Private ethernet - open.
#$IPTABLES -A INPUT -p ALL -i $INET2_IFACE -j ACCEPT
#$IPTABLES -A OUTPUT -p ALL -i $INET2_IFACE -j ACCEPT

#Rules for bad_tcp
$IPTABLES -A bad_tcp -p tcp ! --syn -m state --state NEW -j LOG \
--log-prefix "New packet no syn:"
$IPTABLES -A bad_tcp -p tcp ! --syn -m state --state NEW -j DROP

#Rules for allowed
#$IPTABLES -A allowed -p TCP --syn -j ACCEPT
$IPTABLES -A allowed -p TCP -m state --state NEW -j ACCEPT
$IPTABLES -A allowed -p TCP -j DROP

#Rules for icmp
#  Firstly echo reply/request 
$IPTABLES -A icmpin -p ICMP --icmp-type 0 -j ACCEPT
$IPTABLES -A icmpin -p ICMP --icmp-type 8 -j ACCEPT
#  Secondly time exceeded (for traceroute)
$IPTABLES -A icmpin -p ICMP --icmp-type 11 -j ACCEPT
#  Thirdly want to get dest unreachable because 3 error codes important:
#    1 is "Host unreachable"
$IPTABLES -A icmpin -p ICMP --icmp-type 3/1 -j ACCEPT
#    3 is "Port unreachable"
$IPTABLES -A icmpin -p ICMP --icmp-type 3/3 -j ACCEPT
#    4 is "Fragmentation Required but DF Bit Is Set", for PMTUD.
$IPTABLES -A icmpin -p ICMP --icmp-type 3/4 -j ACCEPT

#Rules for tcpin

#This is the magic that avoids us having to write lots
#of rules to get both sides of a conversation, thanks to CONNTRACK
$IPTABLES -A tcpin -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT

# And here we open up for incoming ssh, web and email. DNS is slightly trickier, as
# is RDP but it is all variations on a theme. This is whitelisting packets.

# Ratelimit ssh, and allow for a non-standard port
SSH=22
#$IPTABLES -I INPUT -p TCP --dport $SSH -m state --state NEW -m recent --set
#$IPTABLES -I INPUT -p TCP --dport $SSH -m state --state NEW -m recent --update --seconds 30 --hitcount 3 -j DROP
#$IPTABLES -A tcpin -p TCP --dport $SSH -j allowed

#$IPTABLES -A tcpin -p TCP --dport 80 -j allowed
#$IPTABLES -A tcpin -p TCP --dport 25 -j allowed

$IPTABLES -A tcpin -p TCP --dport 22 -s $PRIME -j allowed
$IPTABLES -A tcpin -p TCP --dport 22 -s $TIERCE -j allowed
$IPTABLES -A tcpin -p TCP --dport 22 -s $MPFH -j allowed
$IPTABLES -A tcpin -p TCP --dport 22 -s $SHEARER -j allowed
$IPTABLES -A tcpin -p TCP --dport 22 -s $VALLEYT -j allowed

#$IPTABLES -A tcpin -p TCP --dport 465 -j allowed
#$IPTABLES -A tcpin -p TCP --dport 587 -j allowed
#$IPTABLES -A tcpin -p TCP --dport 993 -j allowed
#$IPTABLES -A tcpin -p TCP --dport 995 -j allowed

$IPTABLES -A tcpin -p TCP -j DROP

#Rules for udp
# The default traceroute port range
$IPTABLES -A udpin -p udp --dport 33434:33524 -j ACCEPT
# Replies to outgoing DNS etc
$IPTABLES -A udpin -p UDP -m state --state ESTABLISHED -j ACCEPT

#Rules for non-whitelisted incoming packets
$IPTABLES -A INPUT -p tcp -j bad_tcp
$IPTABLES -A INPUT -p ICMP -i $INET_IFACE -j icmpin
$IPTABLES -A INPUT -p TCP -i $INET_IFACE -j tcpin
$IPTABLES -A INPUT -p UDP -i $INET_IFACE -j udpin

$IPTABLES -A OUTPUT -p icmp --icmp-type 0 -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type 8 -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type 11 -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type 3/1 -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type 3/3 -j ACCEPT
$IPTABLES -A OUTPUT -p icmp --icmp-type 3/4 -j ACCEPT

# This is a bit odd, check rewriting habits of iptables.
$IPTABLES -A OUTPUT -p ALL -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPTABLES -A OUTPUT -p ALL -s $INET_IP -j ACCEPT

$IPTABLES -A OUTPUT -p tcp -j bad_tcp