# ferm.firewall: rules for firewall/router
# Created by Thomas J. Zeeman, 22/09/2001
# Last updated: 19/10/2001
# Assume using rc.firewall to set some kernel options too.

# WARNING: due to some necessary parsing of addresses this firewall should be
# brought up AFTER networking is present. Preferably just after a result of a
# DHCP-request!

option iptables		# explicitly state the used firewall-tool
option clearall		# clear all currently used rules
option createchains	# explicitly create all rules

# Declare some handy variables

# Define location of programs explicitly
set IFCONFIG 	"/sbin/ifconfig"
set AWK 	"/usr/bin/awk"
set GREP 	"/usr/bin/grep" 
set CAT 	"/usr/bin/cat"
set SED 	"/usr/bin/sed"

# Network Interfaces
set EXTIF	"ppp0"			# Connection to the ISP
set INTIF	"eth0"			# Connection to the LAN
set LPDIF	"lo"			# Loopbackdevice

# Some much used IP-addresses & masks; see Real-World Linux Security p413-414
# Network bits for the used addresses
set EXTBITS	"16"			# Assume B-class addressing externally
set INTBITS	"24"			# Same for internal addresses
set LPDBITS	"8"			# Loopbackdevice, A-class address!

# IP-addresses for the NICs
# Use ifconfig to extract the IPs; in case of DHCP very handy!
set EXTIP `%IFCONFIG %EXTIF |%GREP addr: |%SED 's/.*addr:\([^ ]*\) .*/\1/'`
set INTIP `%IFCONFIG %INTIF |%GREP addr: |%SED 's/.*addr:\([^ ]*\) .*/\1/'`
set LPDIP "127.0.0.1"	# IP for loopbackdevice. Should never change!

# IP-broadcastaddresses for the NICs
set EXTBC `%IFCONFIG %EXTIF |%GREP Bcast: |%SED 's/.*Bcast:\([^ ]*\) .*/\1/'`
set INTBC `%IFCONFIG %INTIF |%GREP Bcast: |%SED 's/.*Bcast:\([^ ]*\) .*/\1/'`

# Set the actual netmasks
set EXTNET	"%EXTBC/%EXTBITS"
set INTNET	"%INTBC/%INTBITS"
set LPDNET	"127.255.255.255/%LPDBITS"

set ANY		"any/0"		# match any IP address

# IPs for some handy servers

# Initially use these for nameservers. Later on, after DHCP is done, 
# use the ones provided by DHCP. 
set NS `%CAT /etc/resolv.conf | %GREP nameserver | %AWK '{print $2}'`
set DOMAINNAME `%CAT /etc/resolv.conf | %GREP search | %AWK '{print $2}'`

set NEWS	"news.%DOMAINNAME"	# ISP newsserver
set PROXY	"proxy.%DOMAINNAME"	# ISP www-proxy

# This should be (manually) set to the IP your ISP is using for the DHCP-server
# Can be set to any server if you trust your network...
set DHCPS	%ANY		# Accepts DHCP offers from this IP

# Network Time Protocol servers. Should get this from /etc/ntp.conf.
set NTP	`%CAT /etc/ntp.conf | %GREP server | %AWK '{print $2}'`

# Important (and oftused) ranges of IPs
set LOOPBACK		"127.0.0.0/8"		# reserved loopback addresses
set CLASS_A		"10.0.0.0/8"		# class A private networks; 1
set CLASS_B		"172.16.0.0/12"		# class B private networks; 16
set CLASS_C		"192.168.0.0/16"	# class C private networks; 256
set CLASS_D_MULTICAST	"224.0.0.0/4"		# class D multicast addresses
set CLASS_E_RESERVED_NET	"240.0.0.0/5"	# class E reserved addresses
set BCAST_SRC		"0.0.0.0"		# broadcast source address
set BCAST_DEST		"255.255.255.255"	# broadcast destination address

# Important (and oftused) ranges of portnumbers; 
set PRIVPORTS	"0:1023"		# well known, privileged port range
set UNPRIVPORTS	"1024:65535"		# unprivileged port range

set NFS_PORT	"2049"			# (TCP/UDP) NFS
set SOCKS_PORT	"1080"			# (TCP) Socks

# X Windows port allocation begins at 6000 and increments to 6063
# for each additional server running.
set XWINDOW_PORTS	"6000:6063"	# (TCP) X windows

# The SSH client starts at 1023 and works down to 513 for each
# additional simultaneous connection originating from a privileged port.
# Clients can optionally be configured to use only unprivileged ports.
set SSH_LOCAL_PORTS	"1022:65535"	# port range for local clients
set SSH_REMOTE_PORTS	"513:65535"	# port range for remote clients

# traceroute usually uses -S 32769:65535 -D 33434:33523
set TRACEROUTE_SRC_PORTS	"32769:65535"
set TRACEROUTE_DEST_PORTS	"33434:33523"

# Allowed services on in- and outgoing line;
# see /etc/services for corresponding tcp/udp port#
# Based on Debian 2.2r3; names might differ per distribution!
# NB Return traffic for in-/outgoing traffic is arranged via high-numbered
# ports that are allowed by default.

# TCP
set TCP_IN	"ssh,auth"
set TCP_OUT	"ssh,smtp,www,https,ftp,ftp-data,finger,auth"

# UDP
set UDP_IN	"ntp"
set UDP_OUT	"domain,ntp"

# ICMP
# Allows outgoing ping-requests, outgoing ping-replies, etc.
set ICMP_OUT	"ping,pong,fragmentation-needed,source-quench,parameter-problem"

# Allows incomming ping-replies, incomming ping-requests, etc.
set ICMP_IN	"ping,pong,destination-unreachable,source-quench,time-exceeded,parameter-problem"

#------------------------------------------------------------------------------
# Start with the actual rules.
# Standard policy is to deny everything except if explicitly approved.
#


# incomming packets
chain input policy DENY {

	# Loopbackdevice is accepted at all times.
	if %LPDIF ACCEPT;

	# Check those from the LAN; egress filtering!
	if %INTIF {
		proto tcp goto tcp_lan;
		proto udp goto udp_lan;
		proto icmp goto icmp_lan;
	}
										
	#Check the ones comming from the Internet
	if %EXTIF {
		# Allow friends, and they better be REAL GOOD FRIENDS!
		goto goodguys;

		# Kick out the bad guys
		goto badguys;

		# Set up the standard rules
		proto tcp goto tcp_ext;		# TCP packet rules
		proto udp goto udp_ext;		# UDP packet rules
		proto icmp goto icmp_ext;	# ICMP packet rules
	}
	
}


# forwarded packets
chain forward policy DENY {

	# Let all trafic from the LAN be forwarded/masqueraded
	if %EXTIF saddr %INTNET MASQ;

}


# outgoing packets
chain output policy REJECT {

	# Loopbackdevice is accepted at all times...
	if %LPDIF ACCEPT;

	# Use TOS to get a bit of QOS; for both interfaces!
	proto ( tcp,udp ) goto tosqueue;

	# Something else for icmp.
	if %EXTIF proto icmp icmptype ( %ICMP_OUT ) ACCEPT;
	if %INTIF proto icmp icmptype ( %ICMP_IN ) ACCEPT;

	# Log all other icmp attempts
	proto icmp DENY log;
}


# TCP traffic from LAN->Internet
chain tcp_lan proto tcp {

	# Deny all ip-addressess except local LAN
	saddr ! %INTNET REJECT log;

	# Allow traffic for specified (privileged) ports; 
	sport ( %TCP_OUT ) ACCEPT;

	# Allow specific ports to be used for ssh
	#sport ( %SSH_LOCAL_PORTS ) dport ssh ACCEPT;

	# Disallow all other traffic from privileged ports
	sport %PRIVPORTS DENY log;

	# Disallow traffic from the following ports: X-Windows, NFS
	sport ( %NFS_PORT,%XWINDOW_PORTS ) DENY log;
	
	# Allow all other traffic from unprivileged ports
	# Could be set to the small subset set in 
	# /proc/sys/net/ipv4/ip_local_port_range
	sport %UNPRIVPORTS ACCEPT;

}

# UDP traffic from LAN->Internet
chain udp_lan proto udp {

	# Deny all ip-addresses except local LAN
	saddr ! %INTNET REJECT log;

	# Allow traffic for specified (privileged) ports
	sport ( %UDP_OUT ) ACCEPT;

	# Disallow all other traffic from privileged ports
	sport %PRIVPORTS DENY log;

	# Disallow traffic from the following ports: X-Windows, NFS
	sport ( %NFS_PORT,%XWINDOW_PORTS ) DENY log;
	
	# Allow all other traffic from unprivileged ports
	# Could be set to the small subset set in 
	# /proc/sys/net/ipv4/ip_local_port_range
	sport %UNPRIVPORTS ACCEPT;
	
}

# ICMP traffic from LAN->Internet
chain icmp_lan proto icmp {

	# Deny all ip-addresses except local LAN
	saddr ! %INTNET REJECT log;
	
	# Deny all forms of ICMP except a few.
	icmptype ( %ICMP_OUT ) ACCEPT;

	# Log all other traffic, might indicate hacker active on your LAN!
	REJECT log;
}


# TCP traffic from Internet->LAN/Firewall/Router
chain tcp_ext proto tcp {

	# Deny all claiming to come from our own ip and log; it is an attack!
	saddr %EXTIP DENY log;

	# Deny all packets with local nw ip-addresses; somewhat useless to log
	saddr ( %CLASS_A,%CLASS_B,%CLASS_C,%LOOPBACK ) DENY;

	# Deny other special addresses; useless to log too
	saddr ( %CLASS_D_MULTICAST,%CLASS_E_RESERVED_NET,%BCAST_SRC,%BCAST_DEST ) DENY;

	# Specifically deny some special ports and log attempts
	dport ( %NFS_PORT,%SOCKS_PORT,%XWINDOW_PORTS ) DENY log;

	# Deny scanning via domain port
	sport domain {
		dport domain ACCEPT;
		syn DENY log;
	}

	# Accept incomming traffic on following privileged ports
	dport ( %TCP_IN ) ACCEPT;

	# Deny all other traffic to privileged ports
	dport %PRIVPORTS DENY log;

	# Special case to allow active ftp transfers to our machine
	sport ftp-data dport %UNPRIVPORTS ACCEPT;

	# awkward incoming connections
	syn DENY log;

	# Accept other traffic.
	dport %UNPRIVPORTS ACCEPT;

}

# UDP traffic from Internet->LAN/Firewall/Router
chain udp_ext proto udp {

	# Deny all claiming to come from our own ip and log; it is an attack!
	saddr %EXTIP DENY log;

	# Deny all packets with local nw ip-addresses; somewhat useless to log
	saddr ( %CLASS_A,%CLASS_B,%CLASS_C,%LOOPBACK ) DENY;

	# Deny other special addresses; useless to log too
	saddr ( %CLASS_D_MULTICAST,%CLASS_E_RESERVED_NET,%BCAST_SRC,%BCAST_DEST ) DENY;

	# Specifically deny some special ports and log attempts
	dport ( %NFS_PORT ) DENY log;

	# DNS return packets allowed...
	sport domain saddr %NS ACCEPT;

	# Again no dns fumbling around
	sport domain dport domain ACCEPT;

	# Accept incomming traffic on following privileged ports
	dport ( %UDP_IN ) ACCEPT;

	# Deny all other traffic to privileged ports
	dport %PRIVPORTS DENY log;
	
	# Accept other traffic.
	dport %UNPRIVPORTS ACCEPT;

}

# ICMP traffic from Internet->LAN/Firewall/Router
chain icmp_ext proto icmp {

	# Deny all claiming to come from our own ip and log; it is an attack!
	saddr %EXTIP DENY log;

	# Deny all packets with local nw ip-addresses; somewhat useless to log
	saddr ( %CLASS_A,%CLASS_B,%CLASS_C,%LOOPBACK ) DENY;

	# Deny other special addresses; useless to log too
	saddr ( %CLASS_D_MULTICAST,%CLASS_E_RESERVED_NET,%BCAST_SRC,%BCAST_DEST ) DENY;
	
	# Deny all forms of ICMP except a few.
	icmptype ( %ICMP_IN ) ACCEPT;

	# Log all other traffic, might indicate hacker attempting break-in!
	DENY log;

}

# TCP traffic to Internet/LAN
chain tosqueue {

	# simple traffic control: fair queueing (TOS)
	# reverse rules to match any connection
	protocol tcp reverse TOS
	{
		# set tos bits according to traffic type
		dport ( ssh,ftp ) settos min-delay;
		dport ( http,nntp,smtp,pop3,auth,domain ) settos max-reliability;
		dport ( ftp-data ) settos max-throughput;
	}
	# reset the rest for low cost! (beware!)
	settos min-cost TOS;

}
