#!/bin/sh

# This is a simple iptables firewall script. This can be used stand-alone and
# it can be use as an init.d script to restore firewall settings on boot. This
# is designed to be simple and put a familiar init.d interface around iptables.
# These default firewall settings are indented for an isolated system exposed
# to an untrusted WAN. Only a few critical incoming ports are left open. This
# script includes options to start, stop, and show the status of iptables. The
# "stop" command doesn't really stop iptables (it is not a daemon). In this
# case, "stop" just flushes all policies and rules which opens networking to
# all traffic.
#
# This has been tested on Ubuntu and RedHat systems. To restore rules on boot,
# copy this script to /etc/init.d/firewall. On Ubuntu or Debian systems, run
# "update-rc.d firewall defaults" and the system will start loading the
# firewall rules on boot. On RedHat systems, run "chkconfig --add firewall" and
# the system will start loading the firewall rules on boot.
#
# Note that RedHat has its own iptables init.d script that must be turned off
# if this script is to be used. Alternatively, you can run this script with the
# 'rhsave' option to save the current iptables rules using RedHat's init.d
# script. Be sure to run 'firewall start' before 'firewall rhsave' to set
# the current iptables rules.
#
# Noah Spurrier
# $Id: firewall 341 2008-10-28 22:53:17Z root $
#
# chkconfig: 2345 08 92
# description: This loads iptables firewall rules.
#
### BEGIN INIT INFO
# Provides:          firewall
# Required-Start:    $network $local_fs $remote_fs
# Required-Stop:     $network $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      S 0 1 6
# Short-Description: This loads iptables firewall rules.
# Description:       This loads iptables firewall rules.
#
### END INIT INFO

PATH=/usr/sbin:/usr/bin:/sbin:/bin

case "$1" in
  start)
    #
    # Flush old policies and rules.
    # Get iptables cleaned and ready for new rules.
    #
    iptables -P INPUT ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -P FORWARD ACCEPT
    iptables -F
    iptables -X

    #
    # First thing, drop illegal packets.
    #
    iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP # New not SYN
    iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
    iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
    iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP # NULL packets
    iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
    iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP # XMAS
    iptables -A INPUT -p tcp --tcp-flags FIN,ACK FIN -j DROP # FIN packet
    iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP

    #
    # Accept all connections from trusted sources.
    # These are just examples. Beware that these would override any
    # conflicting rules that come after.
    #
    #iptables -A INPUT -p tcp -j ACCEPT -s 127.0.0.0/24
    #iptables -A INPUT -p tcp -j ACCEPT -s 10.0.0.0/8
    #iptables -A INPUT -p tcp -j ACCEPT -s 172.16.0.0/12
    #iptables -A INPUT -p tcp -j ACCEPT -s 192.168.0.0/16

    #
    # Accept some remote connections.
    # This is what the system exposes to the public.
    # This is what everyone outside the system can see.
    #
    # SSH
    iptables -A INPUT -p tcp --dport 22 -j ACCEPT
    # HTTP
    iptables -A INPUT -p tcp --dport 80 -j ACCEPT
    # HTTPS
    iptables -A INPUT -p tcp --dport 443 -j ACCEPT
    # SMTP
    iptables -A INPUT -p tcp --dport 25 -j ACCEPT
    # IMAP4 SSL
    iptables -A INPUT -p tcp --dport 993 -j ACCEPT
    # POP3 SSL
    iptables -A INPUT -p tcp --dport 995 -j ACCEPT
    # DNS -- typical queries
    iptables -A INPUT -p udp --dport 53 -j ACCEPT
    ## LDAP
    #iptables -A INPUT -p tcp --dport 389 -j ACCEPT
    ## LDAP SSL
    #iptables -A INPUT -p tcp --dport 636 -j ACCEPT
    ## SMB (Samba) - Note source range is limited to 192.168.0.0/24 subnet.
    #iptables -A INPUT -p udp -s 192.168.0.0/24 --dport 137 -j ACCEPT
    #iptables -A INPUT -p udp -s 192.168.0.0/24 --dport 138 -j ACCEPT
    #iptables -A INPUT -m state --state NEW -p tcp -s 192.168.0.0/24 --dport 139 -j ACCEPT
    #iptables -A INPUT -m state --state NEW -p tcp -s 192.168.0.0/24 --dport 445 -j ACCEPT
    ## DNS -- AXFR zone transfers
    #iptables -A INPUT -p tcp --dport 53 -j ACCEPT
    ## VPN -- Accept UDP on port 1194.
    #iptables -A INPUT -p udp --dport 1194 -j ACCEPT
    ## VPN -- Accept on interfaces with names beginning with 'tun'.
    #iptables -A INPUT -i tun+ -j ACCEPT
    ## NTP -- Note source range is limited to 10.1.0.0/24 subnet.
    ##        Adjust this to match your subnet.
    #iptables -A INPUT -p udp --dport 123 -s 10.1.0.0/24 -j ACCEPT
    ## VMware console interface
    #iptables -A INPUT -p tcp --dport 902 -j ACCEPT
    ## SNMP Manager -- receive port for traps from agents.
    #iptables -A INPUT -p udp --dport 162 -j ACCEPT
    ## SNMP Agent -- receive port for requests from manager.
    #iptables -A INPUT -p udp --dport 161 -j ACCEPT
    # VNC Server -- This is usually a bad idea. A better way would use a tunnel.
    #iptables -A INPUT -p tcp --dport 5900 -j ACCEPT
    # VNC Server -- This allows tunneled connections via localhost.
    #iptables -A INPUT -p tcp -s 127.0.0.1 --dport 5900 -j ACCEPT
    # VNC Client Listen Mode -- Allows VNC servers to initiate connections.
    #iptables -A INPUT -p tcp --dport 5500 -j ACCEPT

    #
    # Accept some localhost connections.
    # This is allows the given services to run but only listen to clients
    # through localhost connections. For example, users and applications on
    # this server may use MySQL, but remote connection to MySQL are blocked.
    # Most servers allow you to configure them to listen only to localhost,
    # but these rules actually enforce a secure configuration.
    #
    # IMAP4
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 143 -j ACCEPT
    # POP3
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 110 -j ACCEPT
    # MySQL
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 3306 -j ACCEPT
    # PostgreSQL
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 5432 -j ACCEPT
    ## Oracle
    #iptables -A INPUT -p tcp -s 127.0.0.1 --dport 1521 -j ACCEPT
    ## Oracle TTC
    #iptables -A INPUT -p tcp -s 127.0.0.1 --dport 2483 -j ACCEPT
    ## Oracle TTC SSL
    #iptables -A INPUT -p tcp -s 127.0.0.1 --dport 2484 -j ACCEPT
    ## Bind RNDC -- This is needed only by Bind 9 and not other DNS servers.
    #iptables -A INPUT -p tcp -s 127.0.0.1 --dport 953 -j ACCEPT
    ## Git
    #iptables -A INPUT -p tcp -s 127.0.0.1 --dport 9418 -j ACCEPT
    ## Subversion svnserve (not required if using svn+ssh URL scheme).
    #iptables -A INPUT -p tcp -s 127.0.0.1 --dport 3690 -j ACCEPT

    #
    # Accept limited ping (ICMP).
    # Allow valid, slow pings. Ping is useful, but it can be abused.
    # Note that this will cause ping packet loss if the ICMP packets
    # come in faster than 10 per second, so using "ping -f" to test
    # connection reliability will give false bad readings.
    # This is put after most other rules because ICMP is a low priority.
    #
    iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT
    iptables -A INPUT -p icmp --icmp-type 3 -j ACCEPT
    iptables -A INPUT -p icmp --icmp-type 11 -j ACCEPT
    iptables -A INPUT -p icmp --icmp-type 8 -m limit --limit 10/second -j ACCEPT
    iptables -A INPUT -p icmp -j DROP

    #
    # This is for FTP. Pretty much only FTP does this.
    # Match related and established state connections.
    # This allows inbound connections that were initiated by the localhost.
    #
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

    #
    # These default policies handle anything not covered by a prior rule.
    #
    iptables -P INPUT DROP
    iptables -P OUTPUT ACCEPT
    iptables -P FORWARD ACCEPT
    ;;
  stop)
    iptables -P INPUT ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -P FORWARD ACCEPT
    iptables -F
    iptables -X
    ;;
  status)
    iptables -L -v -n --line-numbers
    ;;
  rhsave)
    /etc/init.d/iptables save
    ;;
  *)
    echo "Usage: $0 {start|stop|status|rhsave}" >&2
    exit 1
    ;;
esac

exit 0

