A default-deny stance on in-bound traffic makes a good firewall; a default-deny stance on out-bound traffic in addition to this makes a better one. Firewalls in which not a single packet is allowed in or out of a machine unless it matches a tightly-specified rule are called pinprick (or pinhole) firewalls.
This example is implemented using IPTables. Points to note --- the machine running this firewall is:
#!/bin/sh
# -- where's the iptables binary?
IPT="/sbin/iptables"
# ------------------------------------------------------------------------------------------
# -- to start with, clean out the bath :
# ------------------------------------------------------------------------------------------
for i in filter nat mangle
do
$IPT -t $i -F
$IPT -t $i -X
done
# ------------------------------------------------------------------------------------------
# -- create our tables :
# ------------------------------------------------------------------------------------------
# ...we use separate tables for different things, since it's faster...
$IPT -N TCP_IN
$IPT -N TCP_OUT
$IPT -N UDP_IN
$IPT -N UDP_OUT
# ------------------------------------------------------------------------------------------
# -- me/local :
# ------------------------------------------------------------------------------------------
# ...allow me to talk to myself on both loopback and external-facing devices...
$IPT -t filter -A INPUT -s 127.0.0.1 -j ACCEPT
$IPT -t filter -A OUTPUT -s 127.0.0.1 -j ACCEPT
$IPT -t filter -A INPUT -i lo -p tcp -s 130.88.253.254 -j ACCEPT
$IPT -t filter -A OUTPUT -o lo -p tcp -s 130.88.253.254 -j ACCEPT
# ------------------------------------------------------------------------------------------
# -- remote debug :
# ------------------------------------------------------------------------------------------
# ...occasionally we are crazy enough to modify the IPTables rules remotely, so offer
# a safety net: allow in a hardened machine to sort it out :
$IPT -t filter -A INPUT -s 130.88.253.255 -j ACCEPT
$IPT -t filter -A OUTPUT -d 130.88.253.255 -j ACCEPT
# ------------------------------------------------------------------------------------------
# -- handle TCP and UDP :
# ------------------------------------------------------------------------------------------
# ...TCP and UDP traffic, in-bound and out-bound, is handled by the
# appropriate table, so we jump to it...
$IPT -t filter -A INPUT -p tcp -i eth0 -d 130.88.253.254 -j TCP_IN
$IPT -t filter -A OUTPUT -p tcp -o eth0 -s 130.88.253.254 -j TCP_OUT
$IPT -t filter -A INPUT -p udp -i eth0 -d 130.88.253.254 -j UDP_IN
$IPT -t filter -A OUTPUT -p udp -o eth0 -s 130.88.253.254 -j UDP_OUT
# ------------------------------------------------------------------------------------------
# -- handle ICMP :
# ------------------------------------------------------------------------------------------
# ...we don't like it...
$IPT -t filter -A INPUT -p icmp -j DROP
# ------------------------------------------------------------------------------------------
# -- default drops :
# ------------------------------------------------------------------------------------------
# ...frankly, anything that gets this far is something we are not interested in,
# and which is going to the bin...
#
# -- e.g., windoze broadcast/netbios-type crap is going straight down the hole
# -- other stuff we log, before dropping, just to see what it is...
$IPT -t filter -A INPUT -p udp --sport 137 --dport 137 -j DROP
$IPT -t filter -A INPUT -p udp --sport 138 --dport 138 -j DROP
$IPT -t filter -A INPUT -j LOG --log-prefix " **INPUT DROP** "
$IPT -t filter -A INPUT -j DROP
$IPT -t filter -A OUTPUT -j LOG --log-prefix " **OUTPUT DROP** "
$IPT -t filter -A OUTPUT -j DROP
# ------------------------------------------------------------------------------------------
# -- the policies which override everything else :
# ------------------------------------------------------------------------------------------
$IPT -t filter -P INPUT DROP
$IPT -t filter -P OUTPUT DROP
$IPT -t filter -P FORWARD DROP
# ------------------------------------------------------------------------------------------
# -- THE END. (End of "main"; following are the "subroutines/functions".)
# ------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------
# -- CHAIN TCP_IN : new inward TCP connections :
# ------------------------------------------------------------------------------------------
# -- bad stuff :
#
$IPT -t filter -A TCP_IN -p tcp ! --syn -m state --state NEW -j LOG --log-prefix " **NEW NOT SYN** "
$IPT -t filter -A TCP_IN -p tcp ! --syn -m state --state NEW -j DROP
# -- incoming packets related to connections we initiated out-bound :
#
$IPT -t filter -A TCP_IN -p tcp --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT
# -- allow new connections to our http-server plus traffic on established connections from all hosts :
#
$IPT -t filter -A TCP_IN -p tcp --sport 1024: --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
# -- ssh connections to our daemon from selected hosts only :
#
$IPT -t filter -A TCP_IN -p tcp -s 130.88.254.254 --sport 1024: --dport 22 -m state --state NEW -j LOG --log-level warn
$IPT -t filter -A TCP_IN -p tcp -s 130.88.254.254 --sport 1024: --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
# -- nfs (mount a remote disk from 254.254) :
#
$IPT -t filter -A TCP_IN -p tcp -s 130.88.254.254 --sport 111 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -t filter -A TCP_IN -p tcp -s 130.88.254.254 --sport 2049 --dport 1024: -m state --state NEW,ESTABLISHED -j ACCEPT
# -- est/rel ftp (for apt-get) :
#
# ...need to deal with initial connection out to 21, passive FTP (high to high,
# originating from client/us) and active FTP (originates from server on 20
# to client/us on high)...
#
# ...addresses reflect contencts of /etc/apt/sources.list...
#
$IPT -t filter -A TCP_IN -p tcp -s 195.224.53.39 --sport 21 -m state --state ESTABLISHED -j ACCEPT
$IPT -t filter -A TCP_IN -p tcp -s 195.224.53.39 --sport 20 -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -t filter -A TCP_IN -p tcp -s 195.224.53.39 --sport 1024: --dport 1024: -m state --state ESTABLISHED -j ACCEPT
# -- every other tcp connection can go in the bin :
#
# ...alternatively: $IPT -t filter -A TCP_IN -m state --state NEW -j DROP...
#
$IPT -t filter -A TCP_IN -m state --state NEW -j REJECT --reject-with icmp-port-unreachable
# -- drop any other tcp packet :
#
$IPT -t filter -A TCP_IN -p tcp -j LOG --log-prefix " **TCP_IN DROP** "
$IPT -t filter -A TCP_IN -p tcp -j DROP
# ------------------------------------------------------------------------------------------
# -- CHAIN TCP_OUT : outward TCP :
# ------------------------------------------------------------------------------------------
# ...output is default-deny too...
#
# allow connections from all local high-numbered ports to all remote --- so that any TCP
# client on our machine can get new connections out :
#
# $IPT -t filter -A TCP_OUT -p tcp --sport 1024:65535 -j ACCEPT
#
# NO! The above rule is common, but lazy/sloppy.
# YES: allow strictly limited TCP client access out :
#
$IPT -t filter -A TCP_OUT -p tcp --sport 1024: --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -t filter -A TCP_OUT -p tcp --sport 1024: --dport 2222 -m state --state NEW,ESTABLISHED -j ACCEPT
# -- allow established outward http to any host :
#
$IPT -t filter -A TCP_OUT -p tcp --sport 80 --dport 1024: -m state --state ESTABLISHED -j ACCEPT
# -- allow established outward traffic to vips from our sshd :
#
$IPT -t filter -A TCP_OUT -p tcp --sport 22 -d 130.88.254.254 -m state --state ESTABLISHED -j ACCEPT
# -- nfs (mount a remote disk from 254.254) :
#
$IPT -t filter -A TCP_OUT -p tcp -d 130.88.254.254 --dport 111 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -t filter -A TCP_OUT -p tcp -d 130.88.254.254 --sport 1024: --dport 2049 -m state --state NEW,ESTABLISHED -j ACCEPT
# -- allow ftp so apt-get can do its stuff :
#
# ...need to deal with initial connection out to 21, passive FTP (high to high,
# originating from client/us) and active FTP (originates from server on 20
# to client/us on high)...
#
# ...addresses reflect contencts of /etc/apt/sources.list...
#
$IPT -t filter -A TCP_OUT -p tcp -d 195.224.53.39 --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -t filter -A TCP_OUT -p tcp -d 195.224.53.39 --dport 20 -m state --state ESTABLISHED -j ACCEPT
$IPT -t filter -A TCP_OUT -p tcp -d 195.224.53.39 --sport 1024: --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT
# -- default deny :
#
$IPT -t filter -A TCP_OUT -p tcp -j LOG --log-prefix " **TCP_OUT DROP** "
$IPT -t filter -A TCP_OUT -p tcp -j DROP
# ------------------------------------------------------------------------------------------
# -- CHAIN UDP_IN : new inward UDP connections :
# ------------------------------------------------------------------------------------------
$IPT -t filter -A UDP_IN -p udp -m state --state ESTABLISHED,RELATED -j ACCEPT
# -- nfs (mount a remote disk from 254.254) :
#
$IPT -t filter -A UDP_IN -p udp -s 130.88.254.254 --sport 111 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -t filter -A UDP_IN -p udp -s 130.88.254.254 --sport 2049 --dport 1024: -j ACCEPT
# -- default deny :
#
$IPT -t filter -A UDP_IN -p udp -j DROP
# ------------------------------------------------------------------------------------------
# -- CHAIN UDP_OUT : new outward UDP connections :
# ------------------------------------------------------------------------------------------
# -- DNS lookups (we must have these!) :
#
$IPT -t filter -A UDP_OUT -p udp --sport 1024: --dport 53 -j ACCEPT
# -- nfs (mount a remote disk from 254.254) :
#
$IPT -t filter -A UDP_OUT -p udp -d 130.88.254.254 --dport 111 -j ACCEPT
$IPT -t filter -A UDP_OUT -p udp -d 130.88.254.254 --dport 1024: -j ACCEPT
# -- remote syslog logs (syslogs are copied to a secure remote server) :
#
$IPT -t filter -A UDP_OUT -p udp -d 130.88.254.253 --sport 514 -j ACCEPT
# -- default deny :
#
$IPT -t filter -A UDP_OUT -p udp -j DROP
# ------------------------------------------------------------------------------------------
# ------------------------------------------------------------------------------------------
| ...previous | up (conts) | next... |