#!/bin/bash
# rc.firewall - IPTables firewall script.
#
# The Netfilter System: 
#
# --->[PRE]------>[ROUTE]--->[FWD]-------->[POST]--->
#      Conntrack     |       Filter   ^    NAT (Src)
#      Mangle        |                |    Conntrack
#      NAT (Dst)     |             [ROUTE] 
#      (QDisk)       V                |
#                  [IN] Filter      [OUT] Conntrack
#                    |  Conntrack     ^   Mangle
#                    |                |   NAT (Dst)
#                    V                |   Filter
#


## Uncomment next line to debug this script with xtrace
#set -x

# Set some parameters
INTERNAL_NET=192.168.100.0/24
INTERNAL_IP=192.168.100.254/24
LOCALHOST_IP=127.0.0.1/8
EXTERNAL_IP=
SNAT_IP=
LOOPBACK=lo
EXTERNAL=eth0
INTERNAL=eth1

# Program locations
IPTABLES=/sbin/iptables
MODPROBE=/sbin/modprobe
ECHO=/bin/echo

##Log Levels for various rules
# Syslog error levels: DEBUG = 7, INFO = 6, NOTICE = 5, WARNING = 4
LOG_DEBUG=DEBUG
EGRESS_LOG_LEVEL=NOTICE
FLAG_LOG_LEVEL=WARNING
PORT_LOG_LEVEL=WARNING
STATE_LOG_LEVEL=WARNING
LOG_LEVEL=NOTICE

LOG_LIMIT="3/minute"
LOG_BURST=3

# IP address for DNAT of internal mail server
MAIL_SERVER=192.168.100.2:25
HTML_SERVER=

## Reserved/Private IP addresses
# http://www.iana.org/assignments/ipv4-address-space
# This is a complete list of reserved addresses from IANA. Many address
# ranges have been condensed using complex subnet masking. 
#
# 5.0.0.0/8 + 7.0.0.0/8 + 69.0.0.0/8 + 71.0.0.0/8 = 5.0.0.0/189.0.0.0
# 72.0.0.0/8 -> 79.0.0.0/8 + 88.0.0.0/8 -> 95.0.0.0/8 = 72.0.0.0/232.0.0.0
# 
# Which is easier to understand if looked at in binary:
#
# 00000101 = 5     01001000 = 72
# 00000111 = 7	   01001111 = 79
# 01000101 = 69	   01011000 = 88
# 01000111 = 71	   01011111 = 95
# --------	   --------
# 10111101 = 189   11101000 = 232
#
# The first set is four seperate addresses that have oscilating 2nd and 7th 
# bits. The second is a grouping of two sets of numbers 72 thru 79 and 88 
# thru 95. You can group these numbers together under one netmask because 
# both sets use the last three bits to differentiate the number in the set 
# and the fourth bit to differentiate between the sets.

RESERVED_NET="
    0.0.0.0/7;0-1.0.0.0/8 \
    2.0.0.0/8;2.0.0.0/8 \
    5.0.0.0/189.0.0.0;5,7,69,71/8 \
   23.0.0.0/8;23.0.0.0/8 \
   27.0.0.0/251.0.0.0;27,31/8 \
   36.0.0.0/7;36-37.0.0.0/8 \
   39.0.0.0/8;39.0.0.0/8 \
   41.0.0.0/8;41.0.0.0/8 \
   42.0.0.0/8;42.0.0.0/8 \
   58.0.0.0/7;58-59.0.0.0/8 \
   60.0.0.0/8;60.0.0.0/8 \
   70.0.0.0/8;70.0.0.0/8 \
   72.0.0.0/232.0.0.0;72-79,88-95/8 \
   82.0.0.0/7;82-83.0.0.0/8 \
   84.0.0.0/6;84-87.0.0.0/8 \
   96.0.0.0/3;96-127.0.0.0/8 \
  197.0.0.0/8;197.0.0.0/8 \
  201.0.0.0/8;201.0.0.0/8 \
  219.0.0.0/8;219.0.0.0/8 \
  220.0.0.0/6;220-223.0.0.0/8 \
  240.0.0.0/4;240-255.0.0.0/8 \
   10.0.0.0/8;Class_A_Private \
  172.16.0.0/12;Class_B_Private \
  192.168.0.0/16;Class_C_Private \
  224.0.0.0/4;Multicast \
  169.254.0.0/16;Microsoft"

#Load Modules (if needed)
$MODPROBE ipt_LOG
$MODPROBE ip_nat_ftp
$MODPROBE ip_conntrack_ftp
#$MODPROBE ip_conntrack_irc

#Flush All tables
$IPTABLES -t mangle -F 
$IPTABLES -t nat -F
$IPTABLES -F

#Delete tables
$IPTABLES -t mangle -X
$IPTABLES -t nat -X
$IPTABLES -X

#Set Default Policies
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP

##################
## filter table ##
##################

###################################################################
## Keep state chain - To handle incoming, outgoing, and established 
## connections.
##
$IPTABLES -N keep_state
$IPTABLES -F keep_state

# Log and drop packets associated with an "INVALID" connection
$IPTABLES -A keep_state -m state --state INVALID -m limit \
    --limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
    --log-level $STATE_LOG_LEVEL --log-prefix "INVALID: "
$IPTABLES -A keep_state -m state --state INVALID -j DROP

# UNCLEAN match target, somewhat experamental at this point
#$IPTABLES -A keep_state -m unclean -m limit \
#    --limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
#    --log-level $STATE_LOG_LEVEL --log-prefix "UNCLEAN: "
#$IPTABLES -A keep_state -m unclean -j DROP

# Accept packets which are related to an established connection
$IPTABLES -A keep_state -m state --state RELATED,ESTABLISHED -j ACCEPT

###################################################################
## Check flags chain - Drops and logs TCP packets with certain flags
## set. Limist are used to limit the amount of crap that gets sent to
## the logs. These rules *should* never match normal traffic.
##
$IPTABLES -N check_flags
$IPTABLES -F check_flags

#NMAP FIN/URG/PSH
$IPTABLES -A check_flags -p TCP --tcp-flags ALL FIN,URG,PSH -m limit \
    --limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
    --log-level $FLAG_LOG_LEVEL --log-prefix "NMAP-XMAS: "
$IPTABLES -A check_flags -p TCP --tcp-flags ALL FIN,URG,PSH -j DROP

#SYN/RST
$IPTABLES -A check_flags -p TCP --tcp-flags SYN,RST SYN,RST -m limit \
    --limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
    --log-level $FLAG_LOG_LEVEL --log-prefix "SYN/RST: "
$IPTABLES -A check_flags -p TCP --tcp-flags SYN,RST SYN,RST -j DROP

#SYN/FIN -- Scan (Probably)
$IPTABLES -A check_flags -p TCP --tcp-flags SYN,FIN SYN,FIN -m limit \
    --limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
    --log-level $FLAG_LOG_LEVEL --log-prefix "SYN/FIN: "
$IPTABLES -A check_flags -p TCP --tcp-flags SYN,FIN SYN,FIN -j DROP

# Make some port scans annoyingly slow, also provides some protection
# agains certain types of DOS attacks.
$IPTABLES -A check_flags -p TCP --tcp-flags ALL RST -m limit \
    --limit 5/second -j ACCEPT
$IPTABLES -A check_flags -p TCP --tcp-flags ALL FIN -m limit \
    --limit 5/second -j ACCEPT
$IPTABLES -A check_flags -p TCP --tcp-flags ALL SYN -m limit \
    --limit 5/second -j ACCEPT

####################################################################
## Specifically Denied TCP ports - Logs and drops packets based on
## TCP port number for both destination and source ports.
##
$IPTABLES -N deny_tcp_ports
$IPTABLES -F deny_tcp_ports

DENIED_PORTS_TCP="
	137:139;SMB \
	20034;Netbus2_Pro \
	12345:12346;Netbus \
	27374;Subseven \
	27665;Trinoo \
	27444;Trinoo \
	31335;Trinoo \
	10498;Mstream \
	12754;Mstream"

for PORT in $DENIED_PORTS_TCP; do
    # LOG and DROP packets sent *TO* the denied port
    $IPTABLES -A deny_tcp_ports -p TCP --dport ${PORT//;*/} -m limit \
	--limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
	--log-level $PORT_LOG_LEVEL --log-prefix "**DENIED TCP> ${PORT//*;/}: "
    $IPTABLES -A deny_tcp_ports -p TCP --dport ${PORT//;*/} -j DROP

    # LOG and DROP packets sent *FROM* the denied port
    $IPTABLES -A deny_tcp_ports -p TCP --sport ${PORT//;*/} -m limit \
	--limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
	--log-level $PORT_LOG_LEVEL --log-prefix "**DENIED TCP> ${PORT//*;/}: "
    $IPTABLES -A deny_tcp_ports -p TCP --sport ${PORT//;*/} -j DROP
done

# Reject port 113 ident requests
$IPTABLES -A deny_tcp_ports -p TCP --dport 113 \
    -j REJECT --reject-with tcp-reset 


####################################################################
## Specifically Denied UDP ports -  Logs and drops packets based on
## UDP port number for both destination and source ports.
##
$IPTABLES -N deny_udp_ports
$IPTABLES -F deny_udp_ports

DENIED_PORTS_UDP="
	31337;BO2K \
	27444;Trinoo \
	31335;Trinoo \
	10498;Mstream"

for PORT in $DENIED_PORTS_UDP; do
    # LOG and DROP packets sent *TO* the denied port
    $IPTABLES -A deny_udp_ports -p UDP --dport ${PORT//;*/} -m limit \
	--limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
	--log-level $PORT_LOG_LEVEL --log-prefix "**DENIED UDP> ${PORT//*;/}: "
    $IPTABLES -A deny_udp_ports -p UDP --dport ${PORT//;*/} -j DROP

    # LOG and DROP packets sent *FROM* the denied port
    $IPTABLES -A deny_udp_ports -p UDP --sport ${PORT//;*/} -m limit \
	--limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
	--log-level $PORT_LOG_LEVEL --log-prefix "**DENIED UDP> ${PORT//*;/}: "
    $IPTABLES -A deny_udp_ports -p UDP --sport ${PORT//;*/} -j DROP
done

# LOG (only External) and DROP packets sent *TO* a SMB port
$IPTABLES -A deny_udp_ports -i $EXTERNAL -p UDP --dport 137:139 -m limit \
	--limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
	--log-level $PORT_LOG_LEVEL --log-prefix "**DENIED UDP> SMB: "
$IPTABLES -A deny_udp_ports -p UDP --dport 137:139 -j DROP

# LOG (only External) and DROP packets sent *FROM* a SMB port
$IPTABLES -A deny_udp_ports -i $EXTERNAL -p UDP --sport 137:139 -m limit \
	--limit $LOG_LIMIT --limit-burst $LOG_BURST -j LOG \
	--log-level $PORT_LOG_LEVEL --log-prefix "**DENIED UDP> SMB: "
$IPTABLES -A deny_udp_ports -p UDP --sport 137:139 -j DROP

####################################################################
## Allowed TCP Ports - Specifically allowed TCP ports based on port
## number. Here is where we poke holes thru the firewall for services.
## (RFC 1340 specifies ports for both TCP and UDP for each service.)
## 
$IPTABLES -N allow_tcp_ports
$IPTABLES -F allow_tcp_ports
# Allow SSH - which is configured to be started from xinetd
$IPTABLES -A allow_tcp_ports -m state --state NEW -p TCP --dport 22 -j ACCEPT
# Allow SMTP - mail is DNAT'ed to our internal mail server
$IPTABLES -A allow_tcp_ports -m state --state NEW -p TCP --dport 25 -j ACCEPT
# Allow DNS - Our firewall is also our primary domain server
$IPTABLES -A allow_tcp_ports -m state --state NEW -p TCP --dport 53 -j ACCEPT
# Allow SFTP - Port used for secure file tranfers
$IPTABLES -A allow_tcp_ports -m state --state NEW -p TCP --dport 115 -j ACCEPT
# Allow NTP - Port used for setting network time
$IPTABLES -A allow_tcp_ports -m state --state NEW -p TCP --dport 123 -j ACCEPT

####################################################################
## Allowed UDP Ports - Specifically allowed UDP ports based on port
## number. Here is where we poke holes thru the firewall for services.
## (RFC 1340 specifies ports for both TCP and UDP for each service.)
##
$IPTABLES -N allow_udp_ports
$IPTABLES -F allow_udp_ports
# Allow SSH - which is configured to be started from xinetd
$IPTABLES -A allow_udp_ports -m state --state NEW -p UDP --dport 22 -j ACCEPT
# Allow SMTP - mail is DNAT'ed to our internal mail server
$IPTABLES -A allow_udp_ports -m state --state NEW -p UDP --dport 25 -j ACCEPT
# Allow DNS - Our firewall is also our primary domain server
$IPTABLES -A allow_udp_ports -m state --state NEW -p UDP --dport 53 -j ACCEPT
# Allow SFTP - Port used for secure file tranfers
$IPTABLES -A allow_udp_ports -m state --state NEW -p UDP --dport 115 -j ACCEPT
# Allow NTP - Port used for setting network time
$IPTABLES -A allow_udp_ports -m state --state NEW -p UDP --dport 123 -j ACCEPT

####################################################################
## TCP packets chain - All TCP packets will traverse this chain
##
$IPTABLES -N tcp_packets
$IPTABLES -F tcp_packets
$IPTABLES -A tcp_packets -p TCP -j check_flags
$IPTABLES -A tcp_packets -p TCP -j allow_tcp_ports
$IPTABLES -A tcp_packets -p TCP -j deny_tcp_ports

####################################################################
## UDP packets chain - All UDP packets will traverse this chain
##
$IPTABLES -N udp_packets
$IPTABLES -F udp_packets
$IPTABLES -A udp_packets -p UDP -j allow_udp_ports
$IPTABLES -A udp_packets -p UDP -j deny_udp_ports

####################################################################
## ICMP packets chain - All ICMP packets will travers this chain
##
$IPTABLES -N icmp_packets
$IPTABLES -F icmp_packets
# Echo Reply (pong)
$IPTABLES -A icmp_packets -p ICMP --icmp-type 0 -j ACCEPT
# Destination Unreachable
$IPTABLES -A icmp_packets -p ICMP --icmp-type 3 -j ACCEPT
# Redirect
$IPTABLES -A icmp_packets -p ICMP --icmp-type 5 -j ACCEPT
# Echo Request (ping) - limited to elimiate ping of death DOS
$IPTABLES -A icmp_packets -p ICMP --icmp-type 8 -m limit \
	  --limit 1/second -j ACCEPT
# Time Exceeded
$IPTABLES -A icmp_packets -p ICMP --icmp-type 11 -j ACCEPT

####################################################################
## LOOPBACK input chain - loopback device default input chain
## (Accepts all packets)
##
$IPTABLES -N lo_input
$IPTABLES -F lo_input
$IPTABLES -A lo_input -i $LOOPBACK -j ACCEPT

####################################################################
## INTERNAL input chain - internal interface default input chain
##
$IPTABLES -N internal_input
$IPTABLES -F internal_input
# If a packet comes in on the internal interface with a source address 
# that is not on the internal network, drop it.
$IPTABLES -A internal_input -i $INTERNAL -s ! $INTERNAL_NET -j DROP
# Let mail go through on any port
$IPTABLES -A internal_input -i $INTERNAL -s ${MAIL_SERVER//:*/} \
	  -p TCP --sport ${MAIL_SERVER//*:/} -j ACCEPT
$IPTABLES -A internal_input -i $INTERNAL -p TCP -j tcp_packets
$IPTABLES -A internal_input -i $INTERNAL -p UDP -j udp_packets
$IPTABLES -A internal_input -i $INTERNAL -p ICMP -j icmp_packets

####################################################################
## EXTERNAL input chain - external interface default input chain
##
$IPTABLES -N external_input
$IPTABLES -F external_input
$IPTABLES -A external_input -i $EXTERNAL -p TCP -j tcp_packets
$IPTABLES -A external_input -i $EXTERNAL -p UDP -j udp_packets
$IPTABLES -A external_input -i $EXTERNAL -p ICMP -j icmp_packets

####################################################################
## INPUT chain - filter table INPUT chain
##
$IPTABLES -A INPUT -i $LOOPBACK -j lo_input
# Drop packets not destined for the internal address of the firewall 
$IPTABLES -A INPUT -i $INTERNAL -d ! $INTERNAL_IP -j DROP
$IPTABLES -A INPUT -i $INTERNAL -j internal_input
$IPTABLES -A INPUT -i $INTERNAL -j keep_state
$IPTABLES -A INPUT -i $EXTERNAL -j external_input
$IPTABLES -A INPUT -i $EXTERNAL -j keep_state
# Log policy dropped packets for debugging
$IPTABLES -A INPUT -m limit --limit $LOG_LIMIT --limit-burst $LOG_BURST \
    -j LOG --log-level $LOG_DEBUG --log-prefix "filter INPUT packet died: "

####################################################################
## LOOPBACK output chain - lookback device default output chain
## (Accept all packets)
##
$IPTABLES -N lo_output
$IPTABLES -F lo_output
$IPTABLES -A lo_output -o $LOOPBACK -j ACCEPT

####################################################################
## INTERNAL output chain - internal interface default output chain
##
$IPTABLES -N internal_output
$IPTABLES -F internal_output
# If packet is going out on the internal interface with a destination 
# address that is not on the internal network, drop it.
$IPTABLES -A internal_output -o $INTERNAL -d ! $INTERNAL_NET -j DROP
$IPTABLES -A internal_output -o $INTERNAL -p TCP -j tcp_packets
$IPTABLES -A internal_output -o $INTERNAL -p UDP -j udp_packets
$IPTABLES -A internal_output -o $INTERNAL -p ICMP -j icmp_packets

####################################################################
## EXTERNAL output chain - external interface default output chain
##
$IPTABLES -N external_output
$IPTABLES -F external_output
$IPTABLES -A external_output -o $EXTERNAL -p TCP -j tcp_packets
$IPTABLES -A external_output -o $EXTERNAL -p UDP -j udp_packets
$IPTABLES -A external_output -o $EXTERNAL -p ICMP -j icmp_packets


####################################################################
## OUTPUT chain - filter table OUTPUT chain
##
$IPTABLES -A OUTPUT -o $LOOPBACK -j lo_output
# Drop packets not coming from the firewall
$IPTABLES -A OUTPUT -o $INTERNAL -d ! $INTERNAL_IP -j DROP
$IPTABLES -A OUTPUT -o $INTERNAL -j internal_output
$IPTABLES -A OUTPUT -o $INTERNAL -j  keep_state
# Accept new connections from the firewall to the internal network
$IPTABLES -A OUTPUT -o $INTERNAL -s $INTERNAL_IP -d $INTERNAL_NET \
    -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -o $EXTERNAL -j external_output
$IPTABLES -A OUTPUT -o $EXTERNAL -j keep_state
# Accept outgoing packets establishing a new connection
$IPTABLES -A OUTPUT -o $EXTERNAL -m state --state NEW -j ACCEPT
# Log policy dropped packets for debugging
$IPTABLES -A OUTPUT -m limit --limit $LOG_LIMIT --limit-burst $LOG_BURST \
    -j LOG --log-level $LOG_DEBUG --log-prefix "filter OUTPUT packet died: "

####################################################################
## FORWARD chain
##
# Jump to our interface input/output chains
$IPTABLES -A FORWARD -i $EXTERNAL -j external_input
$IPTABLES -A FORWARD -i $INTERNAL -j internal_input
$IPTABLES -A FORWARD -o $EXTERNAL -j external_output
$IPTABLES -A FORWARD -o $INTERNAL -j internal_output
# Drop any new connections to the internal network
$IPTABLES -A FORWARD -i $EXTERNAL -d $INTERNAL_NET -m state --state NEW -j DROP
# Drop any outbound traffic to the internal network that is trying to 
# establish a new connection
$IPTABLES -A FORWARD -o $INTERNAL -d $INTERNAL_NET -m state --state NEW -j DROP
$IPTABLES -A FORWARD -j keep_state
# Allow new connections to the outside
$IPTABLES -A FORWARD -o $EXTERNAL -m state --state NEW -j ACCEPT
# Log policy dropped packets for debugging
$IPTABLES -A FORWARD -m limit --limit $LOG_LIMIT --limit-burst $LOG_BURST \
    -j LOG --log-level $LOG_DEBUG --log-prefix "filter FORWARD packet died: "

###############
## nat table ##
###############

####################################################################
## Ingress Filtering chain - Rules to provide filtering based on 
## Source IP address
##
$IPTABLES -t nat -N ingress
$IPTABLES -t nat -F ingress
for NET in $RESERVED_NET; do
    $IPTABLES -t nat -A ingress -s ${NET//;*/} -m limit --limit $LOG_LIMIT \
	--limit-burst $LOG_BURST -j LOG --log-level $EGRESS_LOG_LEVEL \
	--log-prefix "Ingress> ${NET//*;/}: "
    $IPTABLES -t nat -A ingress -s ${NET//;*/} -j DROP
done

####################################################################
## Egress Filtering chain - Rules to provide filtering based on
## Destination IP address
##
$IPTABLES -t nat -N egress
$IPTABLES -t nat -F egress
for NET in $RESERVED_NET; do
    $IPTABLES -t nat -A egress -d ${NET//;*/} -m limit --limit $LOG_LIMIT \
	--limit-burst $LOG_BURST -j LOG --log-level $EGRESS_LOG_LEVEL \
	--log-prefix "Egress> ${NET//*;/}: "
    $IPTABLES -t nat -A egress -d ${NET//;*/} -j DROP
done

####################################################################
## POSTROUTING chain
##
$IPTABLES -t nat -A POSTROUTING -o $EXTERNAL -j egress
# Enable simple IP FORWARDing and Masquerading (SNAT)
$IPTABLES -t nat -A POSTROUTING -o $EXTERNAL -j MASQUERADE

####################################################################
## PREROUTING chain
##
# Ingress filtering 
$IPTABLES -t nat -A PREROUTING -i $EXTERNAL -j ingress

## Redirect packets to other machines on network (DNAT)
# MAIL (SMTP)
$IPTABLES -t nat -A PREROUTING -i $EXTERNAL -p TCP -d $EXTERNAL_IP \
    --dport 25 -j DNAT --to-destination $MAIL_SERVER
$IPTABLES -t nat -A PREROUTING -i $EXTERNAL -p UDP -d $EXTERNAL_IP \
    --dport 25 -j DNAT --to-destination $MAIL_SERVER
# HTML (HTTP)
$IPTABLES -t nat -A PREROUTING -i $EXTERNAL -p TCP -d $EXTERNAL_IP \
    --dport 80 -j DNAT --to-destination $HTML_SERVER
$IPTABLES -t nat -A PREROUTING -i $EXTERNAL -p UDP -d $EXTERNAL_IP \
    --dport 80 -j DNAT --to-destination $HTML_SERVER


##################
## mangle table ##
##################

####################################################################
## mangle_output chain - Mangle values of packets created locally. Only
## TOS values are mangled right now.
## --TOS stuff--
## Minimize-Delay 16 (0x10)
## Maximize-Throughput 8 (0x08)
## Maximize-Reliablity 4 (0x04)
## Minimize-Cost 2 (0x02)
## Normal-Service 0 (0x00)
$IPTABLES -t mangle -N mangle_output
$IPTABLES -t mangle -F mangle_output
# RFC 1060/1349 suggested values
$IPTABLES -t mangle -A mangle_output -p TCP --dport 20 -j TOS --set-tos 8
$IPTABLES -t mangle -A mangle_output -p TCP --dport 21 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_output -p TCP --dport 22 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_output -p TCP --dport 23 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_output -p TCP --dport 25 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_output -p TCP --dport 53 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_output -p UDP --dport 53 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_output -p TCP --dport 80 -j TOS --set-tos 8

####################################################################
## mangle_prerouting chain - Mangle values of packets routed through the
## firewall. Only TOS values are mangled right now.
## --TOS stuff--
## Minimize-Delay 16 (0x10)
## Maximize-Throughput 8 (0x08)
## Maximize-Reliablity 4 (0x04)
## Minimize-Cost 2 (0x02)
## Normal-Service 0 (0x00)
$IPTABLES -t mangle -N mangle_prerouting
$IPTABLES -t mangle -F mangle_prerouting
# RFC 1060/1349 suggested values
$IPTABLES -t mangle -A mangle_prerouting -p TCP --dport 20 -j TOS --set-tos 8
$IPTABLES -t mangle -A mangle_prerouting -p TCP --dport 21 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_prerouting -p TCP --dport 22 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_prerouting -p TCP --dport 23 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_prerouting -p TCP --dport 25 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_prerouting -p TCP --dport 53 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_prerouting -p UDP --dport 53 -j TOS --set-tos 16
$IPTABLES -t mangle -A mangle_prerouting -p TCP --dport 80 -j TOS --set-tos 8

####################################################################
## mangle OUTPUT chain - mangle table OUTPUT chain
## 
$IPTABLES -t mangle -A OUTPUT -o $EXTERNAL -j mangle_output

####################################################################
## mangle PREROUTING chain - mangle table PREROUTING chain
##
$IPTABLES -t mangle -A PREROUTING -i $INTERNAL -j mangle_prerouting
# Null scan filtering
$IPTABLES -t mangle -A PREROUTING -p TCP --tcp-flags ALL NONE \
	  -m limit --limit $LOG_LIMIT --limit-burst $LOG_BURST \
	  -j LOG --log-level $LOG_LEVEL --log-prefix "NULL SCAN: " \
	  --log-tcp-options --log-ip-options
$IPTABLES -t mangle -A PREROUTING -p TCP --tcp-flags ALL NONE -j DROP 

####################
### Kernel Flags ###
####################
#(Most are already set with /etc/sysctl.conf, but lets make sure...)

# Enable IP forwarding, allows us to route packets to other networks.
$ECHO "1" > /proc/sys/net/ipv4/ip_forward 

# Don't accept source routed packets. Attackers can use source routing to 
# generate traffic pretending to be from inside your network, but which is
# routed back along the path from which it came, namely outside, so attackers
# can compromise our network.
for i in /proc/sys/net/ipv4/conf/*/accept_source_route; do
    $ECHO "0" > $i;
done

# Turn on Reverse Path Filtering. This helps make sure that packets use
# legitimate source addresses, by automatically rejecting incoming packets
# if the routing table entry for their source address doesn't match the 
# network interface they're arriving on. This has security advantages because 
# it prevents so-called IP spoofing. (Turned on by default when IP forwarding 
# is enabled.)
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do
    $ECHO "1" > $i;
done

# Disable ICMP broadcast response. Protects us from becoming a Smurf amplifier
$ECHO "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

# Enable bad error message protection
$ECHO "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

# Log spoofed packets, source routed packets, redirect packets
$ECHO "1" > /proc/sys/net/ipv4/conf/all/log_martians 

