Tool-BarfreeBSD ArticlesSearch Our SiteHOMEfreeBSD LinksContribute to FreeBSD HelpFreeBSD FilesFreeBSD Script Corner

PF and NAT Quick and Dirty HOWTO

This sample setup should work on FreeBSD 5.2.1 and up using the version
of pf that is in the base system. As always before following online
make sure that you understand what is done and read related
such as pf(4), pf.conf(5) and pflogd(8). Good luck!

The physical configuration looks like this:

/----------\  /-------------------------------\  /------------------\
| Internet  | - |    FreeBSD router        | - | Internal Network |
|  0/0    |  | fxp0: dhcp, fxp1: |  | |
\----------/  \-------------------------------/  \------------------/

1) Make sure you have these in your kernel config ...

options     PFIL_HOOKS   # pfil(9) framework
device     pf       # PF OpenBSD packet-filter firewall
device     pflog      # logging support interface for PF

... or if you are running the GENERIC kernel you can use the pf kld,
it will be loaded automatically if you have pf_enable="YES" in rc.conf.

2) /etc/rc.conf network and pf related configuration.

ifconfig_fxp1="inet netmask"

3) Here is a basic /etc/pf.conf that will work out-of-the-box in this

# macros
ext_if = "fxp0"
int_if = "fxp1"
internal_net = ""

# tables
table <firewall> const { self }

# options
set block-policy drop
set state-policy if-bound

# scrub incoming packets
scrub all reassemble tcp fragment reassemble

# nat
nat on $ext_if from $internal_net to any -> ($ext_if)

# setup a default deny policy
block drop log all

# pass traffic on the loopback interface in either direction
pass quick on lo0 all

# bootp
pass out log-all quick on $ext_if inet proto udp from any port 68 to
any port 67 keep state

# dns, ntp
pass out quick on $ext_if inet proto udp from ($ext_if) to any port {
53, 123 } keep state

# outgoing from firewall
pass out log quick on $ext_if inet proto tcp from ($ext_if) to any
flags S/SA keep state
pass out log quick on $ext_if inet proto { udp, icmp } from ($ext_if)
to any keep state

# incoming, ssh, http (uncomment next line to enable)
#pass in log quick on $ext_if inet proto tcp from any to ($ext_if) port
{ 22, 80 } flags S/SA keep state

# incoming active ftp-data (this is required for active ftp to work)
pass in log quick on $ext_if inet proto tcp from any port 20 to
($ext_if) port >= 1024 flags S/SA keep state

# incoming tcp and udp from the internal network to the internet
pass in log quick on $int_if inet proto tcp from $internal_net to
!<firewall> flags S/SA modulate state
pass in log quick on $int_if inet proto udp from $internal_net to
!<firewall> keep state

4) Reboot your FreeBSD router.

5) On the devices on the internal network configure an ip address
in the range and set the default gateway
to You should now be able to access the network behind
the FreeBSD router.

6) To watch the "live" pf log you can run 'tcpdump -nei pflog0'.
The log file is by default /var/log/pflog and rotated when it grows to
100k which is a bit small, you can change that to rotate it daily at
midnight and keep one week of logs. Modify /etc/newsyslog.conf, change
this line:
/var/log/pflog             600 3   100 *   JB 
/var/log/pflog             600 7   *  @T00 JB 

Pawel Worach

© 1997 - 20013 Defcon1, , Copyrights for all materials on this web site are held by the individual authors, artists, photographers or creators. Materials may not be reproduced or otherwise distributed without permission of and the content's original author.

Tool-Bar-2Defcon1  Webmail