OpenBSD firewall using pf

原创 2004年10月17日 16:13:00
OpenBSD pf by Hoang Q. Tran

OpenBSD firewall using pf

by Hoang Q. Tran

It is really easy to configure an OpenBSD gateway for a private network. Here are the following steps:

Lock down the box

The first step to lock down the firewall box is to disable all unnecessary running services. Luckily, OpenBSD out of the box is really secure even with ident, comsat, daytime, time, rstatd and rusersd enabled in /etc/inetd.conf. Comment out mentioned services in /etc/inetd.conf and edit /etc/rc.conf and make sure portmap, sendmail and ntpd daemons are disabled as well. Don't disable inetd as you will need it later for ftp-proxy.
sshd is enabled out of the box. If you don't plan to use it, disable it with sshd_flags=NO

Once you disabled unnecessary services, go to unixcircle to remotely port scan your own box from the outside. Be careful when you do this behind a firewall box as the port scan script will scan the firewall instead. If you have another box, use nmap to scan the box from the inside.

Get the latest OpenBSD security patches and manually apply or download all the patches in one file or use AnonCVS to synchronize to stable release and build from source.

Make sure you check out the 3.2 stable branch with -rOPENBSD_3_2. Otherwise, you're checking out the ``current'' branch instead.

Finally, readup on SANS's The Twenty Most Critical Internet Security Vulnerabilities (Updated)

Install second Ethernet card in the OpenBSD box

Use any supported ethernet card for the second NIC in the OpenBSD machine. One card will be given a public IP address (assigned by your ISP or obtained dynamically, e.g., with DHCP) and the other will be given an IP address in a non-routable network. Your choices for private network addresses must come from one of these ranges (see RFC 1918): -      netmask -    netmask -  netmask
Assume the first card is ``ep", create /etc/hostname.ep0 with the following x.x.x.x netmask x.x.x.x where x.x.x.x is what you choose above.
# First NIC - private netmask media 10baseT
And if you have a static IP address for the second NIC, you naturally need to have it configured as /etc/hostname.ep1 as well.
# Second NIC with public IP address netmask media 10baseT
Be sure to indicate a correct IP address and netmask for both interfaces. Once you have chosen a private network address range for your inside machines, stay with that same range.

Whatever address you choose for the first interface in the OpenBSD gateway becomes the default gateway IP address for all machines on the inside private network.

Customize the kernel

Compile the new kernel and remove any unwanted devices from the kernel.

Retrieve the kernel source and unpack it as:

# tar xzvf srcsys.tar.gz -C /usr
( kernel source unpacking output... )

Or use AnonCVS to get just the kernel source it:
# setenv CVSROOT
# cd /usr
# cvs -q get -rOPENBSD_3_2 -P src/sys
( checking out files output... )
# cd /sys/arch/i386/conf
I usually name the kernel to the machine hostname, but you can give it any name. Edit the kernel config file:

Remove any hardware related options that are not relevant to your machine. One way to find out what to keep is to consult the dmesg output and remove all the rest. For all available kernel options, refer to GENERIC in the same directory as your kernel file and /sys/conf/GENERIC or man options(4).

Save the kernel config file and then compile and install it:

# config firewall
# cd ../compile/firewall
# make depend; make
( kernel building output... )
# cp /bsd /bsd.old
# cp bsd /bsd
# reboot
This will retain the old kernel as /bsd.old just in case something has gone awry with the new one and the box doesn't boot. If that happens you can type 'bsd.old' at the boot: prompt to boot the old kernel.

Enable packet forwarding, dhcp, firewall and network address translation

To enable packet forwarding uncomment the following line in /etc/sysctl.conf and for extra protection, enable encryption on swap pages:
net.inet.ip.forwarding=1        # 1=Permit forwarding (routing) of packets
vm.swapencrypt.enable=1         # 1=Encrypt pages that go to swap
To enable high performance data transfers on hosts according to Enabling High Performance Data Transfers on Hosts, add the following to /etc/sysctl.conf:
# 1. Path MTU discovery: enabled by default
# 2. TCP Extension (RFC1323): enabled by default
# 3. Increase TCP Window size for increase in network performance
# 4. SACK (RFC2018): enabled by default

And if you receive your routable address assignment dynamically through DHCP:
# echo dhcp > /etc/hostname.ep1
The dhcp server will assign the IP, netmask and default gateway for interface ``ep1''. /etc/resolv.conf will be created with ``search'' and ``nameservers'' statements from the ISP.

Filter rule:

Starting with OpenBSD 3.2, filter and nat rules are combined into /etc/pf.conf. The order of /etc/pf.conf is really important and the format of /etc/pf.conf must follow this order:

1. Options
2. Scrub
3. NAT & RDR
4. Filter

If there are no filter rules, the default action is pass.

Network Address Translation rule:

For clients behind NAT to work, 1 NAT and 1 RDR rule is sufficient:

# NAT internal IP addresses of range to external routable
# IP on ep1 interface
nat on ep1 from to any -> ep1

# Translate outgoing ftp control connections to send them to localhost
# for proxying with ftp-proxy(8) running on port 8081
rdr on ep0 proto tcp from any to any port 21 -> port 8081

ftp-proxy runs inside inetd, add the following line to /etc/inetd.conf in order for ftp clients behind NAT to work by going through ftp-proxy daemon:  stream tcp nowait root /usr/libexec/ftp-proxy ftp-proxy
As a result, ftp port and port 8081 will be opened. ftp-proxy supports -w option which will use tcp_wrappers to control source ftp client as well as destination ftp server access control based on /etc/hosts.allow and /etc/hosts.deny. Assume source ftp client IP doesn't have permission to use ftp, a similar log entry in /var/log/messages when attempted to reach
Sep 14 15:55:38 firewall ftp-proxy[20970]: tcpwrappers rejected: ->

An example of a working /etc/pf.conf

Transparent proxy:

If there's a mail server as and a DNS server as inside the private network, use ``rdr'' to transparent proxying. Since NAT happens before ``rdr'', a ``pass in'' is required in /etc/pf.conf for the translated packets to flow into the mail server and DNS server.


# Redirect incoming smtp traffic to mail server behind NAT
rdr on ep1 proto tcp from any to port 25 -> port 25

# Redirect incoming domain traffic to DNS server behind NAT
rdr on ep1 proto { tcp,udp } from any to port 53 -> port 53
Finally, enable pf in /etc/rc.conf:
pf=YES                   # Packet filter / NAT / logging using pflogd

Configure machines behind NAT

All the machines on the private network should be configured to use the address of the private interface of the OpenBSD box as the default gateway. To set the internal boxes to the default OpenBSD gateway on various operating systems with IP address:
AIX: edit /etc/ and add /usr/sbin/route add gateway >> $LOGFILE 2>&1

FreeBSD: edit /etc/rc.conf and add defaultrouter=""
HP-UX: edit /etc/rc.config.d/netconf and add ROUTE_GATEWAY[0]=""
Linux Redhat: edit /etc/sysconfig/network and add GATEWAY=
NetBSD:  echo "" > /etc/mygate
OpenBSD: echo "" > /etc/mygate

Solaris: echo "" > /etc/defaultrouter
Win2k: Start-Settings->Control Panel->Network and Dial-up Connections->Local Area Network->
       Properties->Internet Protocol (TCP/IP)->Default Gateway->

If you don't want to reboot to pick up the IP address for the default gateway, use ``route'' to manually add the default route.

AIX: route add 0

HP-UX: route add

FreeBSD,NetBSD,OpenBSD,Solaris: route add default

Linux Redhat: route add default gw

Familiarize with pf

Once your firewall is online, you should start reading pf.conf(5), nat.conf(5), ftp-proxy(8), pfctl(8), pf(4) and The OpenBSD Packet Filter HOWTO. Also consult IPFILTER-HOWTO since both pf and IP Filter have 90% identical syntax. One noticable difference is OpenBSD pf doesn't support IP Filter ``keep frags'' syntax. The alternative is to use ``scrub'' statement.

Each time /etc/pf.conf or /etc/nat.conf are modified, you have to reload them using pfctl. Reloading these rules will flush all current active connections. Unlike IPFilter, pf needs to enable nat and pf rules manually.

Flush current nat rules & reload:

# /sbin/pfctl -F nat && /sbin/pfctl -N /etc/pf.conf
Flush current filter rules & reload:
# /sbin/pfctl -F rules && /sbin/pfctl -R /etc/pf.conf
Show filter information (statistics and counters):
# pfctl -s info
To display the current list of active MAP/Redirect filters and active sessions:
# /sbin/pfctl -s state
To find out the ``hit" statistic for each individual rule in /etc/pf.conf:
# /sbin/pfctl -s rules -v
Watch port scans going by on the screen:

/var/log/pflog is a binary file generated by pflogd so you can't just view it. Use tcpdump instead:

# tcpdump -i pflog0

Read the log for pf activities:

# tcpdump -n -e -ttt -r /var/log/pflog

Quality of Service (QoS)

Bandwidth limiting:

OpenBSD 3.2 has ALTQ integrated in the base system. The kernel generic kernel is also compiled with options ALTQ so you're ready to use. Otherwise, download the latest KAME snap kit which has ALTQ bundle from:

Now, to configure a token bucket regulator (tbrconfig) for the interface ep1 to rate limit the pipe from 100Mbps to 10Mbps for outgoing connection:

# tbrconfig ep1 10M auto
ep1: tokenrate 10.00M(bps)  bucketsize 12.21K(bytes)
To remove the installed token bucket regulator on ep1:
# tbrconfig -d ep1
deleted token bucket regulator on ep1

Class-based queuing (CBQ):

From man options(4) description of CBQ:

CBQ achieves both partitioning and sharing of link bandwidth by hierarchically structured classes. Each class has its own queue and is assigned its share of bandwidth. A child class can borrow bandwidth from its parent class as long as excess bandwidth is available.

Here is an example of a working /etc/altq.conf. /etc/altq.conf is read by altqd so to enable it on startup, edit /etc/rc.conf and change altqd_flags=NO to altqd_flags="". Or just manually start altqd. altqd won't start if there are errors in /etc/altq.conf. Watch /var/log/messages for any information.

Here's the class hierarchy: cbq.txt

# ep1: Interface to a 10M link
interface ep1 bandwidth 10M cbq
class cbq ep1 root NULL pbandwidth 100
# meta classes
class cbq ep1 ctl_class root pbandwidth 4 control
class cbq ep1 def_class root borrow pbandwidth 95 default
# Allocate bandwidth for:
# firstclass: 70%
# businessclass: 15%
# generalclass: 5%
class cbq ep1 firstclass def_class borrow pbandwidth 70
class cbq ep1 businessclass def_class borrow pbandwidth 15
class cbq ep1 generalclass def_class borrow pbandwidth 5
# Allocate bandwidth for firstclass (tcp) data classes:
# tcp: 28%
# smtp: 10%
# http: 30%
# dns: 2%
class cbq ep1 tcp firstclass borrow pbandwidth 28 red
    filter ep1 tcp 0 0 0 0 6    # other tcp
class cbq ep1 smtp firstclass borrow pbandwidth 10 red
    filter ep1 smtp 0 0 0 25 6  # smtp
    filter ep1 smtp 0 25 0 0 6  # smtp
class cbq ep1 http firstclass borrow pbandwidth 30 red
    filter ep1 http 0 0 0 80 6  # http
    filter ep1 http 0 80 0 0 6  # http
class cbq ep1 dns firstclass borrow pbandwidth 2 red
    filter ep1 dns 0 0 0 53 6   # dns
    filter ep1 dns 0 53 0 0 6   # dns

# Allocate bandwidth for businessclass (udp) classes:
# udp: 10%
# dns: 5%
class cbq ep1 udp businessclass borrow pbandwidth 10 red
    filter ep1 udp 0 0 0 0 17   # udp
class cbq ep1 dns businessclass borrow pbandwidth 5 red
    filter ep1 dns 0 0 0 53 17  # dns
    filter ep1 dns 0 53 0 0 17  # dns
# Allocate bandwidth for generalclass (icmp) classe:
# icmp: 5%
class cbq ep1 icmp generalclass borrow pbandwidth 5 red
    filter ep1 icmp 0 0 0 0 1   # icmp
Now, run altqstat and monitor the bandwidth. You should see something similar here: cbq stat

Weighted Fair Queueing (WFQ):

To use weighted fair queueing, add the following to kernel file.

option          ALTQ_WFQ

By default, WFQ allocates 256 queues and packets are mapped into one of the queues by hashing the destination address. So, packets for the same host will be put in the same queue.

To enable WFQ on interface "ep0" and "ep1", add the following lines to your altq.conf(5) and start altqd.

interface ep0 bandwidth 10M wfq
interface ep1 bandwidth 10M wfq
The following command can be used to monitor the wfq statistics.
altqstat -i ep1
You should see something similar:
% altqstat
altqstat: wfq on interface ep1
wfq on ep1: 256 queues are used

[QID] WEIGHT QSIZE(KB) SENT(pkts)     (KB)       DROP(pkts)     (KB)     bps
[ 141]  100    0         14              1          0              0     0.09K
[ 103]  100    0          2              0          0              0     0.09K
[ 131]  100    0         11              1          0              0         0
[ 155]  100    0         10              0          0              0         0
[ 124]  100    0          9              0          0              0         0
[ 184]  100    0          5              0          0              0         0
[  12]  100    0          2              0          0              0         0
[   0]  100    0          0              0          0              0         0
[   1]  100    0          0              0          0              0         0
[   2]  100    0          0              0          0              0         0
First-In First-Out Queueing (FIFOQ):

To use first-in first-out queueing, add the following to kernel file.

option          ALTQ_FIFOQ
To enable FIFOQ on interface ep1, add the following line to your altq.conf(5) and start altqd.
interface ep1 bandwidth 10M fifoq
Run altqstat and you should see something similar:
% altqstat
altqstat: fifoq on interface ep1
 q_len:0 q_limit:50 period:2
 xmit:2 pkts (108 bytes) drop:0 pkts (0 bytes)
 throughput: 0.17Kbps
 q_len:0 q_limit:50 period:2
 xmit:2 pkts (108 bytes) drop:0 pkts (0 bytes)
 throughput: 0bps
Random Early Detection (RED):

Since RED is part of ALTQ, no kernel option is required.

To enable random early detection on interface ep1, add the following line to your altq.conf(5) and start altqd.

interface ep1 bandwidth 10M red

Run altqstat and you should see something similar:
% altqstat
altqstat: red on interface ep1
 weight:512 inv_pmax:10 qthresh:(5,15)
 q_len:0 (avg: 0.00), q_limit:60
 xmit:1 pkts, drop:0 pkts (forced: 0, early: 0)
 throughput: 0.09Kbps

 weight:512 inv_pmax:10 qthresh:(5,15)
 q_len:0 (avg: 0.00), q_limit:60
 xmit:1 pkts, drop:0 pkts (forced: 0, early: 0)
 throughput: 0bps
Diffserfv traffic conditioner (CDNR):

>From man options(4):

Traffic conditioners are components to meter, mark, or drop incoming packets according to some rules. As opposed to queueing disciplines, traffic conditioners handle incoming packets at an input interface.

To use conditioner to drop incoming packets from a particular IP address, add the following to kernel file.

option          ALTQ_CDNR
To enable conditioner on interface ep1, add the following line to your altq.conf(5) and start altqd.
interface ep1
# Drop all packets coming in from (ficticious)
conditioner ep1 dropper <drop>
     filter ep1 dropper 0 0 0 0
Run altqstat to monitor the drop packets:
% altqstat
altqstat: cdnr on interface _fxp0
  pass:471 drop:3 mark:0 next:0 return:0 none:0

  pass:501 drop:3 mark:0 next:0 return:0 none:0

Priority Queueing (PRIQ):

>From man options(4):

PRIQ implements a simple priority-based queueing. A higher priority class is always served first.

High number has higher priority. Maximum value is 15 and minimum value is 0. Default is 0. A higher priority class is always served first in PRIQ. Priority must be unique for the interface.

To use priority queueing to prioritize based on type of packet, add the following to kernel file.

option          ALTQ_PRIQ
To enable priority queueing on interface ep1, add the following line to your altq.conf(5) and start altqd.
# Prioritize based on protocol:
# tcp: high priority
# udp:  medium priority
# icmp: low priority
# others: bottom priority
interface ep1 bandwidth 10M priq
class priq ep1 highest_class NULL priority 3
     filter ep1 highest_class 0 0 0 0 6
class priq ep1 medium_class NULL priority 2
     filter ep1 medium_class 0 0 0 0 17
class priq ep1 lowest_class NULL priority 1
     filter ep1 lowest_class 0 0 0 0 1
class priq ep1 bottom_class NULL priority 0 default

% altqstat
altqstat: priq on interface ep1

[highest_class] handle:0xe09fd0c0 pri:3
  measured: 0.34Kbps qlen: 0 period:180
     packets:180 (25637 bytes) drops:0
[medium_class] handle:0xe09f1d40 pri:2
  measured: 0bps qlen: 0 period:25
     packets:25 (1997 bytes) drops:0
[lowest_class] handle:0xe09fdcc0 pri:1
  measured: 0bps qlen: 0 period:19
     packets:19 (1862 bytes) drops:0
[bottom_class] handle:0xe09a4680 pri:0
  measured: 0bps qlen: 0 period:0
     packets:0 (0 bytes) drops:0


Daniel Hartmeier the author of pf and his original page:
The OpenBSD Packet Filter HOWTO
IPFilter how-to:
Address Allocation for Private Internets:
The IP Network Address Translator (NAT):
Traditional IP Network Address Translator (Traditional NAT)
The Twenty Most Critical Internet Security Vulnerabilities (Updated)

last update: Oct 20, 2003

copyright © 2000-2003 unixcircle

The Book of PF: A No-Nonsense Guide to the OpenBSD Firewall

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版、作者信息和本声明。否则将追究法律责任。 - topmvpOpenBSDs ...
  • topmvp
  • topmvp
  • 2008年12月05日 20:59
  • 555

LR性能测试基础---网络篇 tcpdump命令

一、监视指定主机和端口的数据包 如果想要获取主机210.27.48.1接收或发出的telnet包,使用如下命令 tcpdump tcp port 23 host ...
  • he_jian1
  • he_jian1
  • 2014年11月07日 17:51
  • 1190

OpenBSD 系列(四)

OpenBSD 系列(四) OpenBSD 系列(四)在前面的三篇中我们介绍了OpenBSD的安装, 在这篇中我们简单的介绍一下OpenBSD的网络设置和内核编译。我自己是使用局域网, 所以只介绍这个...
  • nmdd
  • nmdd
  • 2005年06月21日 14:29
  • 1200


openBSD4.1安装手记(图解)一、准备工作1、下载新版openBSD4.1         地址、测试环...
  • shined_zhang
  • shined_zhang
  • 2007年10月26日 12:07
  • 1143

[转]我的OpenBSD Tips收集整理

Q:如何关闭文本控制台的哔哔声A:可以直接在命令行输入以下命令:  # wsconsctl keyboard.bell.pitch=0  # wsconsctl keyboard.bell.volum...
  • taolinke
  • taolinke
  • 2010年11月18日 18:56
  • 2513


安装OpenBSD时,到最后安装阶段时(就是安装一些xxx.tgz之类的文件时),使用网络下载速度慢,其原因是默认的那些文件服务器基本都在国外。 连接时总是延迟特别大,导致安装的过程极为漫长,而且链接...
  • u012560379
  • u012560379
  • 2017年03月01日 02:10
  • 682


OpenBSD安装简明教程安装OpenBSD 这是前一段时间安装3.6的记录,3.7我没用过,估...
  • ak47mig
  • ak47mig
  • 2007年01月30日 09:23
  • 1786


OpenBSD的IP设置在/etc/hostname.xxx文件,其中xxx就是你的网卡名。网关设置在/etc/mygate文件。DNS设置在/etc/resolv.conf文件中。 在/etc/h...
  • oyzl68
  • oyzl68
  • 2011年11月01日 22:05
  • 2937


利用openbsd+openvpn快速建立企业vpnopenvpn介绍 ,不多说了.openvpn可工作于两种模式:一种是IP遂道路由模式...
  • freebyu
  • freebyu
  • 2004年07月28日 14:18
  • 895


要编译内核,需要一套完整的syssrc包,这套东东可以通过CVS或FTP方式获得。要通过CVS方式下载,在SHELL上打:export CVS_RSH="/usr/bin/ssh"export CVS...
  • freebyu
  • freebyu
  • 2004年07月29日 22:48
  • 764
您举报文章:OpenBSD firewall using pf