#! /bin/bash
#
# iptables.sh - Packet Filtering Template
#
# Sample ruleset for iptables/netfilter stateful packet filter,
# with detailed comments.
# The provided rules support both Packet Filtering and Network 
# Address Translation.
#
# Disclaimer: the layout for this template is mainly mutuated
# from raptor's ones ;-)
# You're invited in visiting his site at www.0xdeadbeef.info
# You could easily find there lots of interesting tools,
# templates, etc.
#
# Disclaimer 2: the following rules are just which I mainly
# use. If you're interested in using them in a production or
# personal environment, feel free to use and redistribute
# them, but take present that no warranty is included.



#########################################################
# VARIABLES
#
# Here we define all the variables that we are going to
# use later in the ruleset. 
#
# Defining executables
iptables=/sbin/iptables
modprobe=/sbin/modprobe
# Available interfaces
EXT_DEV=eth0
INT_DEV=eth1
# Configured networks
INT_NET=192.168.1.0/24
EXT_NET=x.x.x.0/24
# Firewall external IP address
FW=x.x.x.x
# Here we set the kind of check we use to match new states
# for tcp. Note that with this configuration ESTABLISHED 
# connection will starve each time you reload rules.
tcpinit="-m state --state NEW --tcp-flags SYN,RST,ACK SYN"
# Defining also the kind of check we do for new udp
# connections. This will be mainly unuseful, but
# elegance rules...
udpinit="-m state --state NEW"

#########################################################
# ENVIRONMENT
#
# Here we set global-system preferences which determine
# OS's behaviour.
# Each semaphore is preceded by its meaning and use.
#
# Ping scanning is typically used to determine which
# hosts on a network are up. Typically this is done by
# sending ICMP ECHO request packets to the target host.
# This is seemingly innocent behavior, however often
# network administrators will block such traffic to
# increase their obscurity. The choices involve blocking
# ICMP ECHO requests to broadcast/multicast addresses
# and directly to the host itself.
echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
#
# ICMP redirect messages can also be a pain. If your
# box is not acting as a router, you'll probably want
# to disable them:
echo 1 > /proc/sys/net/ipv4/conf/all/accept_redirects
#
# Sometimes you will come across routers that send out
# invalid responses to broadcast frames. This is a
# violation of RFC 1122, "Requirements for Internet Hosts
# -- Communication Layers". As a result, these events are
# logged by the kernel. To avoid filling up your logfile
# with unnecessary clutter, you can tell the kernel not
# to issue these warnings:
echo 0 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
#
# Here determine if we are enabling forwarding between
# network interfaces or not.
echo 1 > /proc/sys/net/ipv4/ip_forward
#
# The rp_filter can reject incoming packets if their
# source address doesn't match the network interface
# that they're arriving on, which helps to prevent IP
# spoofing.It's important to note that even if you do
# not enable the rp_filter, protection against broadcast
# spoofing is always on. Also, the protection it provides
# is only against spoofed internal addresses; external
# addresses can still be spoofed
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
#
#  If you have compiled your kernel with
# CONFIG_SYNCOOKIES, you will be able to optionally turn
# on or off protection against SYN flood attacks. Note
# the emphasis, as compiling the kernel with this value
# does not enable it by default. It works by sending out
# 'syncookies' when the syn backlog queue of a socket
# overflows.
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
#
# Normally, a host has no control over the route any
# particular packet takes beyond its first hop. It is up
# to the other hosts on the network to complete the
# delivery. IP Source Routing (SRR) is a method of
# specifying the exact path that a packet should take
# among the other hosts to get to its destination.
# This is generally a bad idea for the security
# conscious, as someone could direct packets to you
# through a trusted interface and effectively bypass
# your security in some cases.
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
#
# Packets that have source addresses with no known route
# are referred to as "martians".
echo 1 > /proc/sys/net/ipv4/conf/all/log_martians


#########################################################
# KERNEL MODULES LOADING
#
#f Here we tell netfilter which modules to load.
# These could depend on which kind of controls you are
# going to make, and also on how your kernel has been
# compiled.
# We include here only those which are usually needed.
# You may want to take a look at your
# /lib/modules/`uname -r`/kernel/net/ipv4/netfilter
# directory, which is where iptables modules compiled
# with your kernel are stored.
# Just refer to kernel help to understand what each of
# those does.
#
$modprobe ip_conntrack_ftp
$modprobe ip_nat_ftp
$modprobe ipt_REJECT


#########################################################
# PRE-RULES
# 
# Here we just flush all chains and define default
# filtering policies, create necessary chains.
#
$iptables -F FORWARD
$iptables -F -t nat
$iptables -P INPUT DROP
$iptables -P FORWARD DROP
$iptables -P OUTPUT DROP


#########################################################
# ENABLE LOOPBACK
#
# Allow loopback, which is required by most local
# services to work correctly.
$iptables -A INPUT -i lo -j ACCEPT
$iptables -A OUTPUT -o lo -j ACCEPT


#########################################################
# DROP SPOOFING
#
# Block IP spoofing attacks from the Evil Internet,
# filtering all packets coming from reserved address
# space (most likely spoofed or misconfigured).
# Obviously, we can't reply to them.
# By default, we don't log them. Anyway, just uncomment
# the LOG rules to log.
# Please note that we do not do any egress filtering on
# any packet which is going to exit with its internal
# address.
# This kind of filtering must be done in the
# POSTROUTING chain. Think we'll include it later on.
#
#$iptables -A INPUT -i $EXT_DEV -s 192.168.0.0/16 -j LOG --log-prefix=" Spoofed source? "
#$iptables -A INPUT -i $EXT_DEV -s 172.16.0.0/12 -j LOG --log-prefix=" Spoofed source? "
#$iptables -A INPUT -i $EXT_DEV -s 10.0.0.0/8 -j LOG --log-prefix=" Spoofed source? "
$iptables -A INPUT -i $EXT_DEV -s 192.168.0.0/16 -j DROP
$iptables -A INPUT -i $EXT_DEV -s 172.16.0.0/12 -j DROP
$iptables -A INPUT -i $EXT_DEV -s 10.0.0.0/8 -j DROP
#$iptables -A FORWARD -i $EXT_DEV -s 192.168.0.0/16 -j LOG --log-prefix=" Spoofed source? "
#$iptables -A FORWARD -i $EXT_DEV -s 172.16.0.0/12 -j LOG --log-prefix=" Spoofed source? "
#$iptables -A FORWARD -i $EXT_DEV -s 10.0.0.0/8 -j LOG --log-prefix=" Spoofed source? "
$iptables -A FORWARD -i $EXT_DEV -s 192.168.0.0/16 -j DROP
$iptables -A FORWARD -i $EXT_DEV -s 172.16.0.0/12 -j DROP
$iptables -A FORWARD -i $EXT_DEV -s 10.0.0.0/8 -j DROP


#########################################################
# DROP BAD TRAFFIC
#
# Here we block suspicious tcp segments. These present
# uncommon combinations of tcp flags often used by
# network scanners.
# Please note that these will be blocked anyway if 
# "tcpinit" variable has been initialized with SYN check.
# We log them before blocking, but with a very low rate,
# because they really could be a lot during massive scans.
#
$iptables -A FORWARD -p tcp --tcp-flags ALL FIN,URG,PSH -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "XMAS Scan: "
$iptables -A FORWARD -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$iptables -A FORWARD -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "SYN/FIN: "
$iptables -A FORWARD -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "SYN/RST: "
$iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN,RST -j DROP


#########################################################
# BIDIRECTIONAL NAT (one-to-one mapping)
#
# NAT of internal addresses for let them be visible
# from Internet. 
# Remember that to be genuinely useful, this should 
# be used in conjunction with either proxy arp, or 
# ifconfig(8) aliases. 
# Please note that this configuration is deprecated,
# due to its security issues, if these internal machines
# are located within your LAN, but it is a good chance if
# you're just protecting public machines.
# If you want to use this feature anyway, change the
# following to your settings; otherwise, please, comment
# out all this section.
EXT_WEB=x.x.x.33
INT_WEB=192.168.1.33
EXT_MAIL=x.x.x.34
INT_MAIL=192.168.1.34
# webserver
$iptables -A PREROUTING -t nat -i $EXT_DEV -d $EXT_WEB -j DNAT --to-destination $INT_WEB
$iptables -A POSTROUTING -t nat -o $EXT_DEV -s $INT_WEB -j SNAT --to-source $EXT_WEB
# mailserver
$iptables -A PREROUTING -t nat -i $EXT_DEV -d $EXT_MAIL -j DNAT --to-destination $INT_MAIL
$iptables -A POSTROUTING -t nat -o $EXT_DEV -s $INT_MAIL -j SNAT --to-source $EXT_MAIL


#########################################################
# IP MASQUERADING (many-to-one mapping)
#
# Masquerade the hosts in the Internal network, dynamically 
# changing packets as they traverse the external interface. 
# This allows a single IP address on the translating host 
# to support network traffic for a larger range of machines 
# on an inside network.
# Please note that the following rule works well only for
# static ip-addresses. If you are using a dynamic-ip
# connection, please use the second rule and comment out
# the first one: this is much more cpu-intensive, but will
# work
$iptables -A POSTROUTING -t nat -o $EXT_DEV -j SNAT --to-source $FW
#$iptables -A POSTROUTING -t nat -o $EXT_DEV -j MASQUERADE


#########################################################
# RELATED AND ESTABLISHED RULES
#
# Here we accept everything that has been already allowed
# (like return sessions) and all those sessions that are
# related to an allowed one (like data-port for ftp
# sessions or icmp responses from closed udp ports.
# We allow them here so these packets won't traverse all
# the following rules...
#
$iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
$iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT


#########################################################
# STATEFUL FILTERING - INBOUND
#
# Here we allow all those services we want to public from
# the internal network, and for which we built up those
# NAT rules. Obviously, comment out everything if you did
# the same previously.
#
# webserver
# Note that we just enable connections on port 21 for ftp.
# The other port(s) will be matched by the RELATED rules
# above.
$iptables -A FORWARD -p tcp -i $EXT_DEV -o $INT_DEV -d $INT_WEB --dport 21 $tcpinit -j ACCEPT
$iptables -A FORWARD -p tcp -i $EXT_DEV -o $INT_DEV -d $INT_WEB --dport 80 $tcpinit -j ACCEPT
$iptables -A FORWARD -p tcp -i $EXT_DEV -o $INT_DEV -d $INT_WEB --dport 443 $tcpinit -j ACCEPT
#
# mail
$iptables -A FORWARD -p tcp -i $EXT_DEV -o $INT_DEV -d $INT_MAIL --dport 25 $tcpinit -j ACCEPT
$iptables -A FORWARD -p tcp -i $EXT_DEV -o $INT_DEV -d $INT_MAIL --dport 110 $tcpinit -j ACCEPT
#
# firewall itself
# We just enable ssh from inside for administration
# purposes. This is not the case if the internal network
# is composed by public machines.
$iptables -A INPUT -p tcp -i $INT_DEV --dport 22 $tcpinit -j ACCEPT
#
# Last, we treat all requests directed to auth (ident)
# service. This is often cause of timeouts during
# connection establishing if dropped, so we explicitly
# reject it, bot inbound and outbound...
$iptables -A FORWARD -p tcp --dport 113 $tcpinit -j REJECT


#########################################################
# STATEFUL FILTERING - OUTBOUND
#
# Here we allow internal machines to just reach for the
# services they need.
# In our example, mail server needs (obviously) to
# contact other mailservers and to use external ftp
# services for antivirus updates.
# Both need to contact websites for periodic updates and
# worldwide DNS.
# DNS rule may be limited to just a single or a few
# external addresses, or by a single internal address if
# you are using an internal DNS, which could be necessary
# for servers' internal communications.
#
# mail
$iptables -A FORWARD -p tcp -i $INT_DEV -o $EXT_DEV -s $INT_MAIL --dport 25 $tcpinit -j ACCEPT
$iptables -A FORWARD -p tcp -i $INT_DEV -o $EXT_DEV -s $INT_MAIL --dport 21 $tcpinit -j ACCEPT
#
# both
$iptables -A FORWARD -p udp -i $INT_DEV -o $EXT_DEV --dport 53 $udpinit -j ACCEPT
$iptables -A FORWARD -p tcp -i $INT_DEV -o $EXT_DEV --dport 53 $tcpinit -j ACCEPT
$iptables -A FORWARD -p tcp -i $INT_DEV -o $EXT_DEV --dport 80 $tcpinit -j ACCEPT


#########################################################
# LOG RULES
#
# Here we log everything is out from allowed connections,
# limiting log rate to 1/sec to avoid syslog flooding
#
$iptables -A INPUT -m limit --limit 1/s -j LOG --log-prefix "out_of_INPUT "
$iptables -A FORWARD -m limit --limit 1/s -j LOG --log-prefix "out_of_FORWARD "
$iptables -A OUTPUT -m limit --limit 1/s -j LOG --log-prefix "out_of_OUTPUT "
