IPFW Rules

Matthew Seaman m.seaman at plasm.demon.co.uk
Sun May 12 12:20:41 BST 2002

On Fri, May 10, 2002 at 08:48:17PM -0000, Dave Peacock wrote:
> I am looking for help please from someone with more IPFW clue than me. I am
> one of the lucky people to receive an ADSL line lately and have setup my
> NAT/firewall.
> I am having trouble, I am sure I have got my rules incorrect. If I turn this
> ruleset on, my local machines can NAT through and get to the internet, but
> they cannot log on to the firewall with SSH or connect to FTP.
> Also, I cannot connect to SSH from external sites either, I need this
> functionality.

Hmmm...  Well, I don't claim to be a massive expert on IPFW, but I've
done a few things with it.

Before I start: note that you're always going to have problems with
FTP through firewalls, because of the way it uses separate control and
data connections.  You will have to use passive mode ftp --- web
browsers do this by default, and you can just type `passive' on the ftp
command line for FreeBSD or use the `-p' flag.  Setting
FTP_PASSIVE_MODE=yes in your environment helps.  See ftp(1) for the
full story.

Let's see.  To summarise what you want:

	Private local network connected via xe0 --- I'm going to
assume you're using the RFC1918 net block on your
private net: substitute as appropriate.  External (ADSL) interface via
tun0.  It's not clear if you have a fixed IP number externally so I'm
going to assume not.

	Internal hosts can make tcp connections outwards through the
NAT gateway, or to the FW machine without restriction.  The only UDP
traffic permitted is DNS queries which must be forwarded to  Only SSH is allowed inwards.  Other inward
connections are simply dropped, except for ident where a reset is

Try something like this for your ${firewall_type}:

add 100  deny log all from any to any ipoptions rr
add 200  pass all from any to any via lo0
add 300  deny all from any to
add 400  deny ip from to any
add 500  divert natd all from any to any via tun0
add 600  check-state
add 700  deny log tcp from any to any established
add 800  deny log tcp from to any in via tun0
add 900  allow tcp from me to any keep-state
add 1000 allow tcp from to any keep-state
add 1100 allow tcp from any to me 22 keep-state
add 1200 reset log tcp from any to me 113 in via tun0
add 1300 allow udp from me to 53 keep-state
add 1400 allow udp from to 53 keep-state
add 1500 allow icmp from me to any
add 1600 allow icmp from to any
add 1700 allow icmp from any to any in icmptype 0,3,4,8,11,12
add 65534 deny log ip from any to any


rule 100: packets with the `record route' option really don't occur in
normal valid use, other than in cracking attempts.  Drop them instantly.

rules 200-400: check your /etc/rc.firewall script --- it used to
provide these three rules automatically, but that changed a few months
ago.  In any case, it will do no harm to repeat them.

rule 500: divert any packets crossing the tun0 interface to natd.
After this point you can (almost) forget that NAT is happening. 

rule 600: let's use stateful filtering, as IPFW is capable and it
closes down some potential attacks.  Think of the dynamically
generated rules triggered by the 'keep-state' lines below being
inserted here.

rule 700: looks daft --- deny any established TCP connection? Except
that legitimate connections will already have been allowed at rule
500.  Remember that to IPFW an established TCP connection simply means
a tcp packet without the setup bit set, and that a black hat could
generate those by the bucketful.

rule 800: anti-spoofing.  Don't let packets pretending to be from our
internal networks in through our external interface.

rules 900, 1000: the only things that should hit these rules are new
TCP connections (ie. with the setup bit) from your firewall or from
your internal machines.  That includes SSH from your internal machines
to the firewall, and vice versa.  Nb. using `me' in the rules should
match any IP number configured on any interface of the firewall, which
is handy if you don't know beforehand what your external IP will be.
I'm not sure if it would pick up a change of IP number on your tun0
interface should your ISP force you to do that dynamically.

rule 1100: all other permissible ssh connections having been allowed
above, now permit ssh connections from external sites to the firewall.

rule 1200: reject ident connections from external sites. ident
connections from internal machines were allowed earlier by rule 1000.

rules 1300, 1400: dns queries.  Note that because of the high latency
of some parts of the DNS, you will see quite a lot of what looks like
DNS replies being rejected, simply because the dynamic rules generated
here have timed out before the reply comes back.  Usually this is
harmless, because most resolvers will just try again and the response
will have been cached.  You can tune the timeout for UDP packets by:

	sysctl net.inet.ip.fw.dyn_udp_lifetime=300

which lets you wait 5 minutes for a response to a UDP packet (use
/etc/sysctl.conf to make that happen every reboot).

Nb. no other UDP connections are allowed, including between the FW and
your internal machines.  That's going to rule out such things as using
syslogd for remote logging, NFS, NTP.  Apart from NTP you probably
shouldn't want to use any of those services on a firewall. If you do
want to use NTP insert rules like:

    add 1350 allow udp from me 123 to any 123 keep-state
    add 1450 allow udp from 123 to any 123 keep-state

rules 1500-1700: icmp. Let you generate any type of icmp packet from
the firewall or internal machines, but limits types coming into your
network -- see /usr/include/netinet/ip_icmp.h for the full list, but
the types shown here are:

0	echoreply         --- this is their reply to your ping packet
3	destination unreachable
4	source quench (ie. destination is asking you to slow down)
8	echo              --- this is them trying to ping you
11	time exceeded
12	parameter problem

Now, this is all untested, and I've probably made a few typos but I
think it should do pretty much what you want and stop the bad guys
doing what you don't want.  As always, Caveat Emptor.  Test
thoroughly.  Since this is free advice, you're entitled to a full



Dr Matthew J Seaman MA, D.Phil.                       26 The Paddocks
                                                      Savill Way
Tel: +44 1628 476614                                  Marlow
Fax: +44 0870 0522645                                 Bucks., SL7 1TH UK

More information about the Ukfreebsd mailing list