BSD PF IPv6 and IPv4 /etc/pf.conf Firewall Script

This is my working IPv6 and IPv4 dual stack script from FreeBSD 7.1 server. It should work with any latest PF version under OpenBSD / FreeBSD / NetBSD without a problem.

You need to add following lines to /etc/rc.conf under FreeBSD to turn on PF firewall:

pf_enable="YES"
pflog_enable="YES"
pflog_logfile="/var/log/pflog"
pf_rules="/etc/pf.conf"

Next create /etc/pf.conf file as follows. Replace variable with appropriate values.

  1. By default firewall drops all incoming and outgoing connections for both IPv4 and IPv6.
  2. By default IPv4 and IPv6 outgoing allowed for ssh, smtp, domain / dns, www, https, ntp, ping and whois requests.
  3. By default IPv4 and IPv6 incoming allowed for ssh, smtp, domain / dns, www, https, and ping only.
#### S0.1 First declare a couple of variables ####
# Created by Vivek Gite <vivek@nixcraft.com>
# See more info @
# http://bash.cyberciti.biz/firewall/pf-ipv6-ipv4-firewall-for-freebsd-openbsd-netbsd/
tcp_services = "{ ssh, smtp, domain, www, https, 122, ntp, 43}"
udp_services = "{ domain, ntp }"
icmp_types = "{ echoreq, unreach }"
mail_ports = "{ smtp, imaps }"
 
### define tables
table <droplasso> persist file "/etc/pf.drop.lasso.conf"
table <blockedip> persist file "/etc/pf.block.ip.conf"
 
### IPv4 ranges
martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, 0.0.0.0/8, 240.0.0.0/4, 255.255.255.255/32 }"
http_servers = "{ 208.xx.yyy.zzz }"
mail_servers = "{ 208.xx.yyy.zzz}"
dns_servers = "{ 208.xx.yyy.zzz }"
 
adminrange = "66.228.118.0/23"
 
### ipv6 ranges 
adminrange6 = "{ 2607:F0D0:2000:0000::/48 }"
http_servers6 = "{ 260z:xxx.. }"
mail_servers6 = "{ 260z:xxx.. }"
dns_servers6 = "{ 260z:xxx.. }"
 
IPV6LAN = "{ 260z:xxx../64 }"
IPV6MAIN = "{ 260z:xxx.. }"
 
### Interfaces 
ext_if = "em1"
int_if = "em0"
 
## S0.2: Options
set block-policy return
set loginterface $ext_if
 
#### S0.3: Normliaztion
#scrub provides a measure of protection against certain kinds of attacks based on incorrect handling of packet fragments
scrub in all 
 
#### S0.4: NAT and RDR start
 
# Drop ALL incomming everything 
block log all 
 
# Try to block nmap scans
block in log quick on $ext_if inet proto tcp from any to any flags FUP/FUP
 
#IPv6 - pass in/out all IPv6 ICMP traffic
pass in quick proto icmp6 all
 
# unlimited traffic for vpn and loopback 
set skip on {lo0, $int_if}
 
# activate spoofing protection for all interfaces
block in quick from urpf-failed
#antispoof is a common special case of filtering and blocking. This mechanism protects against activity from spoofed or forged IP addresses
antispoof log for $ext_if
 
#Block RFC 1918 addresses
block drop in log (all)  quick on $ext_if from $martians to any
block drop out log (all) quick on $ext_if from any to $martians
 
#Block DROP LASSO
#block log (all) all
# pfctl -t droplasso -T show
block drop in log (all)  quick on $ext_if from <droplasso> to any
block drop out log (all) quick on $ext_if from any to <droplasso>
 
# pfctl -t blockedip -T show
block drop in log (all)  quick on $ext_if from <blockedip> to any
block drop out log (all) quick on $ext_if from any to <blockedip>
 
# allow outgoing via ssh, smtp, domain, www, https, 122
pass out on $ext_if proto tcp to any port $tcp_services
pass out on $ext_if proto udp to any port $udp_services
 
# trace route
pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 keep state
 
# SL admin allow 66.228.118.0/255.255.254.0 (23)
pass in on $int_if from $adminrange to any
 
# pass in  on $ext_if proto tcp from any to any port 25
pass in on $ext_if inet proto tcp from 72.xx.yyy.zzz to 208.xx.yyy.zzz port ssh flags S/SA synproxy state
pass in on $ext_if inet proto udp from any to $dns_servers  port domain
pass in on $ext_if inet proto tcp from any to $dns_servers  port domain flags S/SA synproxy state
pass in on $ext_if inet proto tcp from any to $http_servers port http flags S/SA synproxy state
pass in on $ext_if inet proto tcp from any to 208.43.79.236 port https flags S/SA synproxy state
pass in on $ext_if inet proto tcp from any to $mail_servers port $mail_ports flags S/SA synproxy state
 
# ping pong 
pass inet proto icmp all icmp-type $icmp_types keep state
 
# Outgoing ftp
pass out on $ext_if inet proto tcp from any to any port ftp
pass out on $ext_if inet proto tcp from any to any port >1023
 
###### IPv6 rules #############
# Allow outgoing services
pass out on $ext_if inet6 proto tcp to any port $tcp_services
pass out on $ext_if inet6 proto udp to any port $udp_services
 
# Trace route out
pass out on $ext_if inet6 proto udp from any to any port 33433 >< 33626 keep state
 
# SL Admin in
pass in on $ext_if inet6 from $adminrange6 to any
 
# Open ports out
pass in on $ext_if inet6 proto udp from any to $dns_servers6 port domain
pass in on $ext_if inet6 proto tcp from any to $dns_servers6 port domain keep state
pass in on $ext_if inet6 proto tcp from any to $http_servers6 port http keep state
pass in on $ext_if inet6 proto tcp from any to $mail_servers6 port $mail_ports keep state
 
# Ftp out 
pass out on $ext_if inet6 proto tcp from any to any port ftp
pass out on $ext_if inet6 proto tcp from any to any port >1023                                                                      
 
# Allow ping pong out
pass out on $ext_if inet6 proto icmp6 all icmp6-type echoreq keep state
 
# ND solicitation out
pass out on $ext_if inet6 proto icmp6 all icmp6-type {neighbradv, neighbrsol}
 
# ND advertisement in
pass in on $ext_if inet6 proto icmp6 all icmp6-type {neighbradv, neighbrsol}
 
# Router advertisement out
pass out on $ext_if inet6 proto icmp6 all icmp6-type routeradv 
 
# Router solicitation in
pass in on $ext_if inet6 proto icmp6 all icmp6-type routersol
 
# Allow Ping pong in
pass in on $ext_if inet6 proto icmp6 all icmp6-type echoreq

You also need to create /etc/pf.block.ip.conf file with list of IPs and subnet to block manually as follows:

202.54.1.2
191.10.1.0/29

This script also supports Spamhaus database to block SMTP / WWW spam bots. Download Shell Script To Update Spamhaus Lasso Spam Database for PF .

Get the latest tutorials on SysAdmin, Linux/Unix, Open Source, and DevOps topics:
CategoryList of Unix and Linux commands
File Management cat
Firewall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilities dig host ip nmap
OpenVPN CentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Manager apk apt
Processes Management bg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searching grep whereis which
User Information groups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPN CentOS 8 Debian 10 Firewall Ubuntu 20.04
5 comments… add one
  • Tekki Jul 28, 2011 @ 18:54

    Hi there! I would like to know if this configuration can help me block IPv6 domain like https facebook? I have a problem blocking Https facebook.

  • 🐧 Vivek Gite Mar 27, 2009 @ 16:15

    Yes, it passes all ICMP6 traffic. Feel free to modify pf.conf it as per your requirements and setup.

  • Roberto Greiner Mar 26, 2009 @ 19:34

    Hi, I think i got a small security problem.

    At the end of the script you have a few lines controlling what of icmp6 can get in. But at the start of the script you have

    #IPv6 – pass in/out all IPv6 ICMP traffic
    pass in quick proto icmp6 all

    which lets all icmp6 traffic in. Or did I get something wrong?

  • 🐧 Vivek Gite Feb 2, 2009 @ 21:38

    Thanks for the heads up.

  • xcezzz Feb 2, 2009 @ 18:25

    There should be a correction on the line below, of where to put pf_enable=”YES”

    You need to add following lines to /etc/pf.conf under FreeBSD to turn on PF firewall:

    It should be rc.conf?

    You need to add following lines to /etc/rc.conf under FreeBSD to turn on PF firewall:

Leave a Reply

Your email address will not be published. Required fields are marked *

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.