#!/bin/bash
# -vx >> add -v for verbose output, add -x for line-by-line echo as it's input
# ** above is useful for debugging purposes
# Original author is Robby Workman.
# We could not have done it without you. Cafe VXt owes you dinner!
# Show user notification
echo ""
echo "Initializing netfilter/iptables: /etc/rc.d/rc.firewall"
# Load kernel module needed for FTP and NAT
echo "loading FTP-NAT kernel module"
/sbin/modprobe ip_nat_ftp
# Set variables
IPT=/usr/sbin/iptables
INTERNET=eth0
OFFICE=eth1
CAFE=eth2
# Set default policy
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
# Flush existing rules and remove custom user chains
$IPT -F
$IPT -t nat -F
$IPT -t mangle -F
$IPT -X
# Create new custom user chains
$IPT -N STATE
$IPT -N BADSTUFF
$IPT -N TCP_IN
$IPT -N TCP_FWD
$IPT -N UDP_IN
$IPT -N UDP_FWD
$IPT -N ICMP_IN
$IPT -N ICMP_FWD
$IPT -N FWD_OUT_TCP
$IPT -N FWD_OUT_UDP
$IPT -N FWD_OUT_ICMP
$IPT -N LOCAL_SERVICES
# Allow all traffic on the loopback interface
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# Turn off packet forwarding in the kernel
# ** This will be turned on at the end of the script **
echo 0 > /proc/sys/net/ipv4/ip_forward
# Enable TCP SYN Cookie Protection
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# Disable ICMP Redirect Acceptance
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
# Do not send Redirect Messages
echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
# Enable bad error message protection
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
# Enable broadcast echo protection
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
# Disable source-routed packets
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
# Do not log spoofed packets, source-routed packets, and redirect packets
echo 0 > /proc/sys/net/ipv4/conf/all/log_martians
########################################
# Send packets to the appropriate chains
########################################
### INPUT rules are for things addressed directly to the server.
# First check for sanity. Then see if it is an already established connection.
$IPT -A INPUT -j BADSTUFF
$IPT -A INPUT -j STATE
# If we deside that staff should be able to log in from home we allow it here.
$IPT -A INPUT -i $INTERNET -p tcp -j TCP_IN
$IPT -A INPUT -i $INTERNET -p udp -j UDP_IN
$IPT -A INPUT -i $INTERNET -p icmp -j ICMP_IN
# Here we specifically allow workstations to talk to our internal services.
# Note that it allows different things to each network.
$IPT -A INPUT -i $OFFICE -j LOCAL_SERVICES
$IPT -A INPUT -i $CAFE -j LOCAL_SERVICES
### FORWARD rules are for trafic just passing through on its way somewhere else.
# First check for sanity. Then see if it is an already established connection.
$IPT -A FORWARD -j BADSTUFF
$IPT -A FORWARD -j STATE
# The next three are set to DROP. They are to be used if we wish to run
# services accessible from the internet *ON OTHER SERVERS THAN THIS ONE*
$IPT -A FORWARD -i $INTERNET -p tcp -j TCP_FWD
$IPT -A FORWARD -i $INTERNET -p udp -j UDP_FWD
$IPT -A FORWARD -i $INTERNET -p icmp -j ICMP_FWD
# Seperate OFFICE and CAFE 100%... just to be sure ;-)
$IPT -A FORWARD -i $OFFICE -o $CAFE -j DROP
$IPT -A FORWARD -i $CAFE -o $OFFICE -j DROP
# Specifically allow the kind of connections that workstations can initiate.
$IPT -A FORWARD -o $INTERNET -p tcp -j FWD_OUT_TCP
$IPT -A FORWARD -o $INTERNET -p udp -j FWD_OUT_UDP
$IPT -A FORWARD -o $INTERNET -p icmp -j FWD_OUT_ICMP
#########################
# nat table
#########################
# SNAT packets destined for the internet
$IPT -t nat -A POSTROUTING -o $INTERNET -j MASQUERADE
#########################
# OUTPUT chain
# This is a default chain like INPUT and FORWARD.
# All packets that the server generates itself, either as replies, broadcasts
# or attempts to make a new connection end up in this chain.
#########################
# Drop invalid packets trying to leave this box.
$IPT -A OUTPUT -m state --state INVALID -j DROP
# Allow all other packets destined to OFFICE and CAFE from this box.
$IPT -A OUTPUT -o $OFFICE -p all -j ACCEPT
$IPT -A OUTPUT -o $CAFE -p all -j ACCEPT
# Do not send ICMP type 11 (time-exceeded) packets - this system will
# not willfully participate in traceroute-enabled netmapping.
$IPT -A OUTPUT -o $INTERNET -p icmp --icmp-type time-exceeded -j DROP
# Allow all other packets destined to INTERNET from this box.
$IPT -A OUTPUT -o $INTERNET -p all -j ACCEPT
#########################
# BADSTUFF chain
#########################
# Drop packets that are likely to be stealth scans.
# ** first set of tcp-flags sets criteria, second set sets match
$IPT -A BADSTUFF -p tcp --tcp-flags ALL NONE -j DROP
$IPT -A BADSTUFF -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$IPT -A BADSTUFF -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$IPT -A BADSTUFF -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
$IPT -A BADSTUFF -p tcp --tcp-flags ACK,FIN FIN -j DROP
$IPT -A BADSTUFF -p tcp --tcp-flags ACK,PSH PSH -j DROP
$IPT -A BADSTUFF -p tcp --tcp-flags ACK,URG URG -j DROP
# Drop packets from the internet that claim to be from a private network
# or from the loopback range.
$IPT -A BADSTUFF -i $INTERNET -s 10.0.0.0/8 -j DROP
$IPT -A BADSTUFF -i $INTERNET -s 172.16.0.0/12 -j DROP
$IPT -A BADSTUFF -i $INTERNET -s 192.168.0.0/16 -j DROP
$IPT -A BADSTUFF -i $INTERNET -s 127.0.0.0/8 -j DROP
# Drop malformed broadcast packets.
$IPT -A BADSTUFF -i $INTERNET -s 255.255.255.255 -j DROP
$IPT -A BADSTUFF -i $INTERNET -s 0.0.0.0 -j DROP
# Drop packets from Class D Multicast addresses.
$IPT -A BADSTUFF -i $INTERNET -s 224.0.0.0/8 -j DROP
# Drop packets from Class E Reserved IP addresses.
$IPT -A BADSTUFF -i $INTERNET -s 240.0.0.0/8 -j DROP
#########################
# STATE chain
#########################
# Drop packets with invalid state flags.
$IPT -A STATE -m state --state INVALID -j DROP
# Accept packets that are part of established connections
# or are related to established connections.
$IPT -A STATE -m state --state ESTABLISHED,RELATED -j ACCEPT
#########################
# TCP_IN chain
#########################
# Drop (without logging) packets from freenode's open proxy scanner.
$IPT -A TCP_IN -p tcp -i $INTERNET -s 82.96.96.3 -j DROP
# Reject incoming identd (auth) requests.
$IPT -A TCP_IN -p tcp --dport 113 -j REJECT --reject-with tcp-reset
# All packets not already caught will be dropped.
$IPT -A TCP_IN -j DROP
#########################
# UDP_IN chain
#########################
# Drop everything.
$IPT -A UDP_IN -j DROP
#########################
# ICMP_IN chain
#########################
# Drop all fragmented ICMP packets.
$IPT -A ICMP_IN -p icmp -f -j DROP
# Allow incoming pings limited to 1 per second.
$IPT -A ICMP_IN -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
# Drop everything else.
$IPT -A ICMP_IN -j DROP
#########################
# LOCAL_SERVICES chain
#########################
# Allow packets of established connections and those related to them.
$IPT -A LOCAL_SERVICES -m state --state RELATED,ESTABLISHED -j ACCEPT
# Allow CUPS configuration from OFFICE.
$IPT -A LOCAL_SERVICES -i $OFFICE -p tcp -dport 631 -j ACCEPT
# Allow DHCP from local networks.
$IPT -A LOCAL_SERVICES -p udp --sport 68 -d 255.255.255.255 --dport 67 -j ACCEPT
$IPT -A LOCAL_SERVICES -p udp --sport 68 --dport 67 -j ACCEPT
# Allow DNS requests from local networks.
$IPT -A LOCAL_SERVICES -p udp --dport 53 -j ACCEPT
$IPT -A LOCAL_SERVICES -p tcp --dport 53 -j ACCEPT
# Allow ntp from local networks.
$IPT -A LOCAL_SERVICES -p udp --dport 123 -j ACCEPT
# Allow incoming ssh from local networks.
$IPT -A LOCAL_SERVICES -p tcp --sport 1024:65535 --dport 22 --syn -m state --state NEW -j ACCEPT
# Allow incoming pings from local networks.
$IPT -A LOCAL_SERVICES -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
# Silently drop all other LAN broadcasts
# FIXME: re-enable after SAMBA has been set up and its ports allowed!
#$IPT -A LOCAL_SERVICES -p udp -d 10.0.1.255 -j DROP
# Silently drop trafic from malconfigured Windows machines that runs a DHCP server....
$IPT -A LOCAL_SERVICES -p udp --sport 67 -d 255.255.255.255 --dport 68 -j DROP
# Reject everything else from local network
$IPT -A LOCAL_SERVICES -j REJECT
#########################
# TCP_FWD chain
#########################
# Drop everything.
$IPT -A TCP_FWD -i $INTERNET -j DROP
#########################
# UDP_FWD chain
#########################
# Drop everything.
$IPT -A UDP_FWD -i $INTERNET -j DROP
#########################
# ICMP_FWD chain
#########################
# Drop everything
$IPT -A ICMP_FWD -i $INTERNET -j DROP
#########################
# FWD_OUT_TCP chain
#########################
# Allow established/related packets
$IPT -A FWD_OUT_TCP -j STATE
# Do not allow outgoing connection attempts to NFS, SOCKS, OpenWindows, squid, samba/cifs
$IPT -A FWD_OUT_TCP -p tcp -m multiport --dports 2049,1080,2000,3128,137,138,139,445 --syn -j REJECT
# Allow ftp, ssh, whois, pop3, usenet, imap, s-pop3, AIM, Yahoo IM, jabber,jabber-s, irc 6667 & 7000
$IPT -A FWD_OUT_TCP -p tcp --sport 1024:65535 -m multiport --dports 21,22,43,110,119,143,995,5190,5050,5222,5223,6667,7000 --syn -m state --state NEW -j ACCEPT
# Allow smtp (25 & 587), finger, http on 80, 81, 88, 8080, and 8088, https, rsync, svn
$IPT -A FWD_OUT_TCP -p tcp --sport 1024:65535 -m multiport --dports 25,587,79,80,81,88,8080,8088,443,873,3690 -m state --state NEW --syn -j ACCEPT
# Allow the stupid non-standard ports our mail host uses :-/
$IPT -A FWD_OUT_TCP -p tcp --sport 1024:65535 -m multiport -dports 2525, 110 -m state --state NEW --syn -j ACCEPT
# Allow requests to keyservers
$IPT -A FWD_OUT_TCP -p tcp --dport 11371 -m state --state NEW --syn -j ACCEPT
# Log and reject all other traffic destined for the net
# Useful for when $USER says "Why won't $SOMETHING work?" :D
$IPT -A FWD_OUT_TCP -p tcp -j ULOG --ulog-prefix "REJECTED: "
$IPT -A FWD_OUT_TCP -p tcp -j REJECT
#########################
# FWD_OUT_UDP chain
#########################
# Allow established/related packets
$IPT -A FWD_OUT_UDP -j STATE
# Allow NTP traffic
$IPT -A FWD_OUT_UDP -p udp --dport 123 -j ACCEPT
# Allow outgoing traceroutes
$IPT -A FWD_OUT_UDP -p udp --sport 32769:65535 --dport 33434:33523 -j ACCEPT
# Log and drop all other traffic destined for the internet
$IPT -A FWD_OUT_TCP -p udp -j ULOG --ulog-prefix "UDP DROP: "
$IPT -A FWD_OUT_UDP -p udp -j DROP
#########################
# FWD_OUT_ICMP chain
#########################
# Allow established/related packets
$IPT -A FWD_OUT_ICMP -j STATE
# Allow pings to go out from the internal networks to the internet.
$IPT -A FWD_OUT_ICMP -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
# Do not allow ICMP time-exceeded messages to be forwarded outside of the local network
$IPT -A FWD_OUT_ICMP -p icmp --icmp-type time-exceeded -j DROP
# Drop everything else
$IPT -A FWD_OUT_ICMP -p icmp -j DROP
###############################################################################
# Turn on packet forwarding in the kernel
# now that all chains are populated
echo 1 > /proc/sys/net/ipv4/ip_forward
##############################################################################
echo "Firewall rules are in place and active..."
echo ""