FreeBSD IPFW Best Practices (IPv6 and IPv4)
Configuration of IPFW can be quite complex. However once you understand its syntax it will be fairly simple. But, This article is not a manual explaining things. It’s for those who already can understand what are they doing with IPFW.
Best Practise
To enable IPFW with logging:
# IPFW
firewall_enable="YES"
firewall_script="/etc/ipfw.rules"
firewall_logging="YES"
firewall_logif="YES"
Configure IPFW by adding rules inside /etc/ipfw.rules
as shell script:
#!/bin/sh
# Flush out the list before we begin.
ipfw -q -f flush
# Delete tables and NATs
ipfw -q table all destroy
ipfw -q nat64lsn all destroy
ipfw -q nat64stl all destroy
# Replace config
ipfw set disable 1
# Set rules command prefix (for test add -n)
cmd="/sbin/ipfw -q add"
# interface name of NIC attached to Internet
pif="vmx0"
epairs="epair*"
# Non-routable IPv4 addresses
## Enable this for RFC1918
#martians="{ 192.168.0.0/16 or 172.16.0.0/12 or 10.0.0.0/8 \
## Note: 204.152.64.0/23 is for Sun cluster interconnect
martians="{ 127.0.0.0/8 or 169.254.0.0/16 or 192.0.2.0/24 or 0.0.0.0/8 or 240.0.0.0/4 \
or 204.152.64.0/23 or 224.0.0.0/3 }"
# IPv6
## Allow IPv6 DAD
$cmd 00031 set 1 pass icmp6 from :: to ff02::/16
## Allow IPv6 RS, RA, NS, NA, & redirect
$cmd 00032 set 1 pass icmp6 from fe80::/10 to fe80::/10
$cmd 00033 set 1 pass icmp6 from fe80::/10 to ff02::/16
# Allow ICMPv6 destination unreachable, NS, NA, & too-big
$cmd 00034 set 1 pass icmp6 from any to any icmp6types 1,2,3,4
$cmd 00035 set 1 pass icmp6 from any to any icmp6types 135,136
# NAT64 Rules (50-69)
# No restrictions on Loopback/me Interfaces
$cmd 00070 set 1 pass log all from any to any via lo0 record-state
$cmd 00071 set 1 pass log all from { me or me6 } to { me or me6 } record-state
# Scrub
$cmd 00099 set 1 reass all from any to any in
# NAT Rules (100-149)
# Passes the packet through if it matches an existing entry in the dynamic rules table
$cmd 00150 set 1 check-state
# Pass from me
$cmd 00161 set 1 pass tcp from { me or me6 } to any established keep-state
$cmd 00163 set 1 pass tcp from { me or me6 } to any setup keep-state
$cmd 00165 set 1 pass udp from { me or me6 } to any keep-state
$cmd 00167 set 1 pass icmp from me to any keep-state
$cmd 00168 set 1 pass icmp6 from me6 to any keep-state
# Deny RH0 (RFC5095)
$cmd 00201 set 1 drop log ipv6 from any to any ext6hdr rthdr0
# Deny fragmented NDP packets (RFC6980)
$cmd 00211 set 1 drop log icmp6 from any to any ext6hdr frag icmp6types 130,131,132,133,134,135,136,143
# uRPF (RFC)
$cmd 00221 set 1 drop log ip from any to any not antispoof in
# Deny ICMPv6 Redirect and Renumbering
$cmd 00231 set 1 drop log icmp6 from any to any icmp6types 137,138
# Deny all inbound traffic from non-routable reserved address spaces
## IPv4
$cmd 00301 set 1 drop log ipv4 from $martians to any in recv $pif
$cmd 00302 set 1 drop log ipv4 from any to $martians out xmit $pif
## IPv6
$cmd 00321 set 1 drop log all from ::1/128 to any via $pif
### Site-local (RFC3879)
$cmd 00322 set 1 drop log all from fec0::/10 to any
### IPv4-Compatible IPv6 (RFC4291)
$cmd 00323 set 1 drop log all from ::/96 to any
### Deny Teredo IPv6 (RFC4380)
$cmd 00324 set 1 drop log all from 2001::/32 to any
$cmd 00325 set 1 drop log udp from any to any 3544
### Deny IPv6 Documentation (RFC3849)
$cmd 00326 set 1 drop log all from 2001:db8::/32 to any
### Deny Discard-Only IPv6 Address (RFC6666)
$cmd 00327 set 1 drop log all from 100::/64 to any
### Deny ORCHID (RFC5156)
$cmd 00328 set 1 drop log all from 2001:10::/28 to any
### Deny Benchmarking IPv6 (RFC5180)
$cmd 00329 set 1 drop log all from 2001:2::/48 to any
### Deny 6Bone (RFC3701)
$cmd 00330 set 1 drop log all from { 3ffe::/16 or 5f00::/8 } to any
### Deny AYIYA (draft-massar-v6ops-ayiya-02)
$cmd 00331 set 1 drop log all from any to any 5072
### Deny TSP (RFC5572)
$cmd 00332 set 1 drop log all from any to any 3653
### XMAS tree
$cmd 00341 set 1 drop log tcp from any to any in tcpflags fin,psh,urg recv $pif
### NULL scan (no flag set at all)
$cmd 00342 set 1 drop log tcp from any to any in tcpflags !fin,!syn,!rst,!psh,!ack,!urg recv $pif
### SYN flood (SYN,FIN)
$cmd 00343 set 1 drop log tcp from any to any in tcpflags syn,fin recv $pif
### Stealth FIN scan (FIN,RST)
$cmd 00344 set 1 drop log tcp from any to any in tcpflags fin,rst recv $pif
### forced packet routing
$cmd 00345 set 1 drop log ip from any to any in ipoptions ssrr,lsrr,rr,ts recv $pif
### Ack scan
$cmd 00346 set 1 drop log tcp from any to any in tcpflags ack,rst recv $pif
# Deny ident
$cmd 00351 set 1 drop log tcp from any to any 113 in via $pif
# Deny all Netbios services.
$cmd 00361 set 1 drop log tcp from any to any 137 in via $pif
$cmd 00362 set 1 drop log tcp from any to any 138 in via $pif
$cmd 00363 set 1 drop log tcp from any to any 139 in via $pif
$cmd 00364 set 1 drop log tcp from any to any 81 in via $pif
# Deny fragments
$cmd 00370 set 1 drop log all from any to not me6 frag in via $pif
# Pass ICMP
# pass path-mtu in both directions
$cmd 00381 set 1 pass icmp from any to any icmptypes 3
# pass source quench in and out
$cmd 00383 set 1 pass icmp from any to any icmptypes 4
# pass outbound traceroutes
$cmd 00385 set 1 pass icmp from any to any icmptypes 11 in
# Allow DHCP
$cmd 00391 set 1 pass udp from any dhcpv6\\-server to me6 dhcpv6\\-client in via $pif keep-state
$cmd 00393 set 1 pass udp from any 67 to me 68 in recv $pif keep-state
# Local Rules (From 400 Rule)
## Note: For ssh protection use blacklistd(8)
# Pass ICMPv6 Ping
$cmd 00401 set 1 pass icmp6 from any to any icmp6types 128,129 keep-state
# Pass outbound pings and incoming ping responses
#$cmd 00403 set 1 pass icmp from any to any icmptypes 8 out
#$cmd 00404 set 1 pass icmp from any to any icmptypes 0 in
# SSH
$cmd 00405 set 1 pass tcp from any to { me or me6 } ssh in recv $pif
# Pass Outgoing Traffic
$cmd 09901 set 1 pass all from any to any out keep-state
# Deny ACK packets that did not match the dynamic rule table
$cmd 09903 set 1 drop log tcp from any to any established in via $pif
# Everything else is denied
$cmd 09999 set 1 drop log all from any to any
#$cmd 09999 set 1 pass log all from any to any in
# NAT Outbound (10000)
# Out (Maybe)
$cmd 10001 set 1 pass log all from any to any out keep-state
# Drop Outgoing Traffic after pass ipv4 NAT
$cmd 19999 set 1 drop log all from any to any out
# Replace config
ipfw set swap 0 1
ipfw delete set 1
Don’t forget to add execute permission:
chmod +x /etc/ipfw.rules
Logging
To limit the number of times a rule is logged per connection attempt, specify the number using this line in /etc/sysctl.conf
:
net.inet.ip.fw.verbose_limit=5000
And make it persistent:
echo "net.inet.ip.fw.verbose_limit=5000" >> /etc/sysctl.conf
Keep your sessions during flush
To keep sessions during flush:
echo net.inet.ip.fw.dyn_keep_states=1 >> /etc/sysctl.conf
Increase state timeouts
echo net.inet.ip.fw.dyn_short_lifetime=30 >> /etc/sysctl.conf
echo net.inet.ip.fw.dyn_fin_lifetime=3 >> /etc/sysctl.conf
echo net.inet.ip.fw.dyn_rst_lifetime=3 >> /etc/sysctl.conf
echo net.inet.ip.fw.dyn_syn_lifetime=30 >> /etc/sysctl.conf
Default to accept for VNETs
To make your life easier by not forcing every jails that using VNET for their network to have a configured firewall.
echo 'net.inet.ip.fw.default_to_accept=1' >> /boot/loader.conf.local
In-Kernel NAT
Do not forget to disable TSO.
echo net.inet.tcp.tso=0 >> /etc/sysctl.conf
SNAT
Configure the NAT instance:
kldstat -q -m ipfw_nat || kldload ipfw_nat
ipfw nat 1 config if $pif same_ports unreg_only reset
The inbound NAT rule is inserted after the two rules which allow all traffic on the trusted and loopback interfaces and after the reassemble rule but before the check-state
rule.
$cmd 00100 set 1 nat 1 ipv4 from any to any in recv $pif
This one for outbound:
$cmd 10000 set 1 nat 1 ipv4 from any to any out xmit $pif
Skipto
Add an skipto 10000
before any pass
outbound rule after inbount NAT rule.
For our base rules:
# Pass from me
$cmd 00160 set 1 skipto 10000 ipv4 from me to any proto tcp out xmit $pif
$cmd 00161 set 1 pass tcp from { me or me6 } to any established keep-state
$cmd 00162 set 1 skipto 10000 ipv4 from me to any proto tcp out xmit $pif
$cmd 00163 set 1 pass tcp from { me or me6 } to any setup keep-state
$cmd 00164 set 1 skipto 10000 ipv4 from me to any proto udp out xmit $pif
$cmd 00165 set 1 pass udp from { me or me6 } to any keep-state
$cmd 00166 set 1 skipto 10000 ipv4 from me to any proto icmp out xmit $pif
$cmd 00167 set 1 pass ipv4 from me to any proto icmp keep-state
$cmd 00168 set 1 pass icmp6 from me6 to any keep-state
# Pass ICMP
# pass path-mtu in both directions
$cmd 00380 set 1 skipto 10000 ipv4 from any to any proto icmp icmptypes 3 out xmit $pif
$cmd 00381 set 1 pass icmp from any to any icmptypes 3
# pass source quench in and out
$cmd 00382 set 1 skipto 10000 ipv4 from any to any proto icmp icmptypes 4 out xmit $pif
$cmd 00383 set 1 pass icmp from any to any icmptypes 4
# pass outbound traceroutes
$cmd 00384 set 1 skipto 10000 ipv4 from any to any proto icmp icmptypes 11 in
$cmd 00385 set 1 pass icmp from any to any icmptypes 11 in
# Pass ICMPv6 Ping
$cmd 00401 set 1 pass icmp6 from any to any icmp6types 128,129 keep-state
# Pass outbound pings and incoming ping responses
#$cmd 00402 set 1 skipto 10000 ipv4 from any to any proto icmp icmptypes 8 out xmit $pif
#$cmd 00403 set 1 pass icmp from any to any icmptypes 8 out
#$cmd 00404 set 1 pass icmp from any to any icmptypes 0 in
# Pass Outgoing Traffic
$cmd 09900 set 1 skipto 10000 ipv4 from any to any out xmit $pif
$cmd 09901 set 1 pass all from any to any out keep-state
DNAT
Configure the NAT instance:
ipfw nat 123 config redirect_addr 10.0.0.1 10.0.0.66
redirect_port tcp 192.168.0.1:80 500
redirect_proto udp 192.168.1.43 192.168.1.1
redirect_addr 192.168.0.10,192.168.0.11
10.0.0.100 # LSNAT
redirect_port tcp 192.168.0.1:80,192.168.0.10:22
500 # LSNAT
or it could be split in:
ipfw nat 1 config redirect_addr 10.0.0.1 10.0.0.66
ipfw nat 2 config redirect_port tcp 192.168.0.1:80 500
ipfw nat 3 config redirect_proto udp 192.168.1.43 192.168.1.1
ipfw nat 4 config redirect_addr 192.168.0.10,192.168.0.11,192.168.0.12 10.0.0.100
ipfw nat 5 config redirect_port tcp 192.168.0.1:80,192.168.0.10:22,192.168.0.20:25 500
In-Kernel NAT64
Separate In/Out Traffic
echo 'net.inet.ip.fw.nat64_direct_output=1' >> /etc/sysctl.conf
Stateless
Create lookup tables
- Create lookup tables:
ipfw -q table T46 create type addr valtype ipv6
ipfw -q table T64 create type addr valtype ipv4
- Fill the tables
ipfw -q table T46 add 2.2.1.1 2a01:e140::53
ipfw -q table T64 add 2a01:e140::53 2.2.1.1
- Create NAT64 instance:
ipfw -q nat64stl NAT create table4 T46 table6 T64
- Add rules that matches the traffic:
$cmd 00100 set 1 nat64stl NAT ip from any to table(T46)
$cmd 00101 set 1 nat64stl NAT ip from table(T64) to 64:ff9b::/96
Stateful
- Create NAT64 instance:
ipfw -q set 1 nat64lsn NAT64 create prefix4 A.B.C.D/32
- Add rules that matches the traffic:
$cmd 00110 set 1 nat64lsn NAT64 ipv4 from any to A.B.C.D/32 in
$cmd 00111 set 1 nat64lsn NAT64 ipv6 from any to 64:ff9b::/96 in
- Don’t forget to add their firewall rules
$cmd set 1 pass ip from any to any
For example
kldstat -q -m ipfw_nat64 || kldload ipfw_nat64
myip4="1.1.1.1/32"
$cmd -f flush
ipfw -q nat64lsn all destroy
# NAT64 Rules
$cmd 00050 set 1 nat64lsn NAT64 log ipv4 from any to $myip4 in recv $pif record-state
$cmd 00051 set 1 nat64lsn NAT64 log ipv6 from 2a01:e140:dead::/44 to 2a01:e140:cafe:ff::/96 in record-state
$cmd 00060 set 1 pass ipv4 from 172.30.10.2 to any in recv lo0 record-state
$cmd 00061 set 1 pass ipv4 from 172.30.10.2 to any out xmit $pif record-state
$cmd 00062 set 1 pass ipv6 from 2a01:e140:cafe:ff::/96 to 2a01:e140:dead::/44 in recv $pif record-state
$cmd 00063 set 1 pass ipv6 from 2a01:e140:cafe:ff::/96 to 2a01:e140:dead::/44 out xmit $pif record-state
$cmd 00064 set 1 pass ipv6 from 2a01:e140:cafe:ff::/96 to 2a01:e140:dead::/44 in recv lo0 record-state
Note
- Both ipv4 and ipv6 routing should be enabled.
Bidirectional IPFW
By using sysctl variable below, you can separately manage/filter your inbound and outbound traffic:
sysctl net.inet.ip.fw.one_pass=0
Here is my recommended configuration:
#!/bin/sh
kldstat -q -m ipfw_nat || kldload ipfw_nat
kldstat -q -m ipfw_nat64 || kldload ipfw_nat64
### Documentations
## 5 Outgoing Jump
## 9-99 Before incoming NAT
## 100-199 Incoming NAT64
## 200-299 Incoming NAT
## 300-399 Check-state After incoming NAT
## 400-499 After incoming NAT
## 500-599 Before outgoing NAT
## 600-699 Outgoing NAT
## 700-799 Check-state After outgoing NAT
## 800-899 After NAT outgoing
### Skipto
## 1000-1999 IPv6 to me before incoming NAT
## 2000-2999 IPv4 to me before incoming NAT
## 3000-3999 IPv6 to me after incoming NAT
## 4000-4999 IPv4 to me after incoming NAT
## 5000-5999 IPv6 from me before outgoing NAT
## 6000-6999 IPv4 from me before outgoing NAT
## 7000-7999 IPv6 from me after outgoing NAT
## 8000-8999 IPv4 from me after outgoing NAT
## 9000-9099 IPv6 Link-Locals Only
## 9100-9199 Silent Drop (Incoming Drop Only)
## 9200-9999 Dangerous Packets (Incoming Drop Only)
## 10000-10999 IPv6 incoming forward
## 11000-11999 IPv4 incoming forward
## 12000-12999 IPv6 outgoing forward
## 13000-13999 IPv4 outgoing forward
# Flush out the list before we begin.
ipfw -q -f flush
# Delete tables and NATs
ipfw -q table all destroy
ipfw -q nat64lsn all destroy
ipfw -q nat64stl all destroy
# Replace Config
ipfw set disable 1
# Set rules command prefix (for test add -n)
cmd="/sbin/ipfw -q add"
# interface name of NIC attached to Internet
pif="vtnet0"
myip4="198.51.100.10/32"
# Networks
corp_pub="{ 192.0.2.0/24 or 203.0.113.0/24 }"
corp_pub6="{ 2001:2:1::/48 or 2001:2:2::/48 }"
# Non-routable IPv4 addresses
## Enable this for RFC1918
#martians="{ 127.0.0.0/8 or 192.168.0.0/16 or 172.16.0.0/12 or 10.0.0.0/8 \
## Note: 204.152.64.0/23 is for Sun cluster interconnect
martians="{ 169.254.0.0/16 or 192.0.2.0/24 or 0.0.0.0/8 or 240.0.0.0/4 \
or 204.152.64.0/23 or 224.0.0.0/3 }"
# NAT64
#ipfw -q table T46 create type addr valtype ipv6
#ipfw -q table T64 create type addr valtype ipv4
#ipfw -q set 1 nat64lsn NAT64 create prefix4 $myip4 prefix6 64:ff9b::/96
# NAT
ipfw nat 1 config if $pif same_ports unreg_only \
redirect_port tcp 172.29.0.1:80 80 \
redirect_port tcp 172.29.0.2:53 53 \
# IPv6 Link-locals
$cmd 00001 set 1 call 9000 ipv6 from any to any
# Outgoing Jump
$cmd 00005 set 1 skipto 00500 all from any to any out
#### Before incoming NAT
# Silent Drop to avoid logging
$cmd 00020 set 1 call 9100 all from any to any in
# Dangerous Packets
$cmd 00030 set 1 call 9200 all from any to any in
# IPv6 to me
$cmd 00040 set 1 call 1000 ipv6 from any to me6 in
# IPv4 to me
$cmd 00050 set 1 call 2000 ipv4 from any to me in
# Forward incoming IPv6
$cmd 00060 set 1 call 10000 ipv6 from any to any in
# Forward incoming IPv4
$cmd 00070 set 1 call 11000 ipv4 from any to any in
# Scrub (IPv4)
$cmd 00099 set 1 reass all from any to any in
#### Incoming NAT
# NAT64 Rules (100-199)
#$cmd 00110 set 1 nat64lsn NAT64 ipv4 from any to $myip4 in
#$cmd 00111 set 1 nat64lsn NAT64 ipv6 from any to 64:ff9b::/96 in
#$cmd 00120 set 1 pass ipv4 from $myip4 to any in recv lo0 record-state
#$cmd 00121 set 1 pass ipv4 from $myip4 to any out xmit $pif record-state
#$cmd 00130 set 1 pass ipv6 from 64:ff9b::/96 to 2a01:e140:dead::/44 in recv $pif record-state
#$cmd 00131 set 1 pass ipv6 from 64:ff9b::/96 to 2a01:e140:dead::/44 out xmit $pif record-state
#$cmd 00132 set 1 pass ipv6 from 64:ff9b::/96 to 2a01:e140:dead::/44 in recv lo0 record-state
# NAT Rules (200-299)
$cmd 00200 set 1 nat 1 ipv4 from any to $myip4 in recv $pif
### Check-state After incoming NAT
# Passes the packet through if it matches an existing entry in the dynamic rules table
$cmd 00300 set 1 check-state
### After incoming NAT
# Dangerous Packets
$cmd 00400 set 1 call 9200 all from any to any in
# IPv6 to me
$cmd 00410 set 1 call 3000 ipv6 from any to me6 in
# IPv4 to me
$cmd 00420 set 1 call 4000 ipv4 from any to me in
### Before outgoing NAT (500)
# IPv6 from me out
$cmd 00510 set 1 call 5000 ipv6 from me6 to any out
# IPv4 from me out
$cmd 00520 set 1 call 6000 ipv4 from me to any out
# Forward Outgoing IPv6
$cmd 00530 set 1 call 12000 ipv6 from any to any out
# Forward Outgoing IPv4
$cmd 00540 set 1 call 13000 ipv4 from any to any out
# NAT outbound
$cmd 00600 set 1 nat 1 ipv4 from any to any out xmit $pif
### Check-state After outgoing NAT
# Passes the packet through if it matches an existing entry in the dynamic rules table
$cmd 00700 set 1 check-state
### After outgoing NAT (800)
# IPv6 from me
$cmd 00810 set 1 call 7000 ipv6 from me6 to any out
# IPv4 from me
$cmd 00820 set 1 call 8000 ipv4 from any to any out
# Everything else is denied
$cmd 00999 set 1 drop log all from any to any
# IPv6 to me before incoming NAT (1000 -> 1999)
# Pass myself
$cmd 01000 set 1 pass ipv6 from me6 to me6 in
# Pass SSH
$cmd 01001 set 1 pass tcp from any to me6 ssh record-state defer-action in
# DNS
$cmd 01002 set 1 pass { tcp or udp } from any to { 2001:2::53 or 2001:2:10::53 } domain, domain\\-s record-state defer-action in
# Web
$cmd 01003 set 1 pass { tcp or udp } from any to { 2001:2::80 or 2001:2:10::80 } https,http record-state defer-action in
# Pass Internal Prefix
$cmd 01090 set 1 pass ipv6 from $corp_pub6 to any record-state defer-action in
# Pass ICMPv6
$cmd 01100 set 1 pass icmp6 from any to any in
# End of IPv6 to me6
$cmd 01999 set 1 return via any
# IPv4 to me before NAT (2000 -> 2999)
# Pass me
$cmd 02000 set 1 pass ipv4 from me to me in
# Pass SSH
$cmd 02001 set 1 pass tcp from any to $myip4 ssh record-state defer-action in recv $pif
# DNS
$cmd 02002 set 1 pass { tcp or udp } from any to $myip4 domain, domain\\-s record-state defer-action in recv $pif
# Web
$cmd 02003 set 1 pass tcp from any to $myip4 https,http record-state defer-action in recv $pif
# Pass Corp
$cmd 02090 set 1 pass ipv4 from $corp_pub to any record-state defer-action in recv $pif
# Pass ICMPv4
$cmd 02100 set 1 pass icmp from any to me record-state defer-action in recv $pif
# End of IPv4 to me
$cmd 02999 set 1 return via any
# IPv6 to me after incoming NAT (3000 -> 3999)
# End of IPv6 to me
$cmd 03999 set 1 return via any
# IPv4 to me after incoming NAT (4000 -> 4999)
# DNS
$cmd 04001 set 1 pass { tcp or udp } from any to 172.29.0.2 domain, domain\\-s keep-state in recv $pif
# Web
$cmd 04002 set 1 pass tcp from any to 172.29.0.1 https,http keep-state in recv $pif
# End of IPv4 to me
$cmd 04999 set 1 return via any
# IPv6 from me before outgoing nat (5000 -> 5999)
$cmd 05000 set 1 pass ipv6 from me6 to me6 out
$cmd 05001 set 1 pass ipv6 from me6 to any record-state defer-action out
# End of IPv6 from me6
$cmd 05999 set 1 return via any
# IPv4 from me before outgoing NAT (6000 -> 6999)
$cmd 06000 set 1 pass ipv4 from me to me out
# Allow any other out
$cmd 06101 set 1 pass ipv4 from me to any record-state defer-action out
# IPv4 xmit $pif Skipto outgoing NAT
$cmd 06900 set 1 skipto 00600 ipv4 from me to any out xmit $pif
# End of IPv4 from me before NAT
$cmd 06999 set 1 return via any
# IPv6 from me after outgoing nat (7000 -> 7999)
$cmd 07000 set 1 pass ipv6 from me6 to me6 out
$cmd 07001 set 1 pass ipv6 from me6 to any keep-state out
# End of IPv6 from me
$cmd 07999 set 1 return via any
# IPv4 from me after outgoing nat (8000 -> 8999)
$cmd 08000 set 1 pass ipv4 from me to me out
$cmd 08001 set 1 pass ipv4 from me to any keep-state out
# End of IPv4 from me
$cmd 08999 set 1 return via any
# Link-Locals Only (9000 -> 9099)
## Allow IPv6 DAD
$cmd 09000 set 1 pass icmp6 from :: to ff02::/16
## Allow IPv6 Link-locals specially for NDP (RS, RA, NS, NA, & redirect)
$cmd 09001 set 1 pass icmp6 from fe80::/10 to fe80::/10
$cmd 09002 set 1 pass icmp6 from fe80::/10 to ff02::/16
# Allow ICMPv6 NS, NA
$cmd 09010 set 1 pass icmp6 from fe80::/10 to 2000::/3 icmp6types 135,136
$cmd 09011 set 1 pass icmp6 from 2000::/3 to { ff02::/16 or fe80::/10 } icmp6types 135,136
# Link-Local Protocols
# Pass OSPF
$cmd 09020 set 1 pass ospf from fe80::/64 to any in recv $pif
# End of Link-Locals Only
$cmd 09099 set 1 return via any
# Silent Drop (9100 -> 9199)
# Drop Sooner to prevent being logged for nothing
$cmd 09100 set 1 drop udp from 0.0.0.0 68 to 255.255.255.255 67 in
$cmd 09101 set 1 drop udp from any 5678 to any 5678 in
$cmd 09102 set 1 drop udp from any to 255.255.255.255 5353 in
$cmd 09103 set 1 drop udp from any to 255.255.255.255 1900 in
# End of Silent Drop
$cmd 09199 set 1 return via any
# Dangerous Packets Drop Only (9200 -> 9999)
# Deny RH0 (RFC5095)
$cmd 09200 set 1 drop log ipv6 from any to any ext6hdr rthdr0 in
# uRPF (RFC)
$cmd 09201 set 1 drop log ip from not me to any not antispoof in
# Deny all inbound traffic from non-routable reserved address spaces
## IPv4
$cmd 09211 set 1 drop log ipv4 from $martians to any in recv $pif
$cmd 09212 set 1 drop log ipv4 from $martians to any in recv vtnet1
## IPv6
$cmd 09230 set 1 drop log ipv6 from ::1/128 to any in
### Site-local (RFC3879)
$cmd 09231 set 1 drop log ipv6 from fec0::/10 to any in
### IPv4-Compatible IPv6 (RFC4291)
$cmd 09232 set 1 drop log ipv6 from ::/96 to any in
### Deny Teredo IPv6 (RFC4380)
$cmd 09233 set 1 drop log ipv6 from 2001::/32 to any in
### Deny IPv6 Documentation (RFC3849)
$cmd 09234 set 1 drop log ipv6 from 2001:db8::/32 to any in
### Deny Discard-Only IPv6 Address (RFC6666)
$cmd 09235 set 1 drop log ipv6 from 100::/64 to any in
### Deny ORCHID (RFC5156)
$cmd 09236 set 1 drop log ipv6 from 2001:10::/28 to any in
### Deny Benchmarking IPv6 (RFC5180)
$cmd 09237 set 1 drop log ipv6 from 2001:2::/48 to any in
### Deny 6Bone (RFC3701)
$cmd 09238 set 1 drop log ipv6 from { 3ffe::/16 or 5f00::/8 } to any in
### XMAS tree
$cmd 09251 set 1 drop log tcp from any to any tcpflags fin,psh,urg in
### NULL scan (no flag set at all)
$cmd 09252 set 1 drop log tcp from any to any tcpflags !fin,!syn,!rst,!psh,!ack,!urg in
### SYN flood (SYN,FIN)
$cmd 09253 set 1 drop log tcp from any to any tcpflags syn,fin in
### Stealth FIN scan (FIN,RST)
$cmd 09254 set 1 drop log tcp from any to any tcpflags fin,rst in
### forced packet routing
$cmd 09255 set 1 drop log ip from any to any ipoptions ssrr,lsrr,rr,ts in
# Deny fragmented NDP packets (RFC6980)
$cmd 09271 set 1 drop log icmp6 from any to any ext6hdr frag icmp6types 130,131,132,133,134,135,136,143 in
# Deny ICMPv6 Redirect and Renumbering
$cmd 09272 set 1 drop log icmp6 from any to any icmp6types 137,138 in
# End of Dangerous packets
$cmd 09999 set 1 return via any
## 10000-10999 IPv6 incoming forward
$cmd 10000 set 1 pass ipv6 from 2a01:e140:dead::/48 to any in
$cmd 10001 set 1 pass ipv6 from any to 2a01:e140:dead::/48 in
# End of IPv6 Incoming Forward
$cmd 10999 set 1 return via any
## 11000-11999 IPv4 incoming forward
# End of IPv4 Incoming Forward
$cmd 11999 set 1 return via any
## 12000-12999 IPv6 outgoing forward
$cmd 12000 set 1 pass ipv6 from any to 2a01:e140:dead::/48 out
$cmd 12001 set 1 pass ipv6 from 2a01:e140:dead::/48 to any out
# End of IPv6 Incoming Forward
$cmd 12999 set 1 return via any
## 13000-13999 IPv4 outgoing forward
# End of IPv4 outgoing Forward
$cmd 13999 set 1 return via any
# Replace Config
ipfw set swap 0 1
ipfw delete set 1
Hope it helps!