Aug 142011
 

Welcome to part two of my multipart series on IPv6. In this post I’ll cover how to use packet filter (pf) to configure a host firewall on BSD. The host used runs FreeBSD 8.2, but this should be largely applicable to any version of OpenBSD or FreeBSD with packet filter support.

Because this is a single host rather than a network, the firewall is pretty straightforward. Allow access to what you want, deny everything else. The IPv6 rules are largely just a copy of the IPv4 rules. The only differences stem from ICMPv6 which is used much more extensively in IPv6 than in IPv4, and from some new address types introduced by IPv6.

Here’s a copy of my /etc/pf.conf:

[cc lang=”bash”]
$ cat /etc/pf.conf
#################################################
# Macros #
#################################################
wan_if = em0
icmp_types = “{ echoreq, unreach }”
icmp6_types = “{ unreach, toobig, timex, paramprob, echoreq, echorep, neighbradv, neighbrsol, routeradv, routersol }”

table const { fe80::/8 }
table const { ff02::/8 }
table const {\
0.0.0.0/8, 10.0.0.0/8, \
127.0.0.0/8, 169.254.0.0/16, \
172.16.0.0/12, 192.168.0.0/24, \
240.0.0.0/4, 255.255.255.255 }

#################################################
# Firewall Option #
#################################################
set skip on lo
set skip on em1
set block-policy return
set state-policy if-bound
set loginterface $wan_if

#################################################
# Scrub Options #
#################################################
scrub in all

#################################################
# Filter Rules #
#################################################

###################
# Universal Rules #
###################
# Block everything
block log all
# Block logically impossible packets
block drop in log quick on $wan_if from to any
block drop out log quick on $wan_if from any to
# Block obviously spoofed packets
antispoof log for $wan_if

##############
# IPv4 Rules #
##############
# Allow ICMP echo requests
pass in log on $wan_if inet proto icmp from any to ($wan_if) icmp-type $icmp_types
# Allow connections to valid services
pass in log on $wan_if inet proto tcp from any to ($wan_if) port ssh
pass in log on $wan_if inet proto tcp from any to ($wan_if) port domain
pass in log on $wan_if inet proto udp from any to ($wan_if) port domain
pass in log on $wan_if inet proto tcp from any to ($wan_if) port www
# Allow all outbound connections
pass out log on $wan_if inet proto icmp from ($wan_if) to any icmp-type $icmp_types
pass out log on $wan_if inet proto tcp from ($wan_if) to any
pass out log on $wan_if inet proto udp from ($wan_if) to any

##############
# IPv6 Rules #
##############
# Allow ICMP echo requests
pass in log on $wan_if inet6 proto icmp6 from any to ($wan_if) icmp6-type $icmp6_types
# Allow connections to valid services
pass in log on $wan_if inet6 proto tcp from any to ($wan_if) port ssh
pass in log on $wan_if inet6 proto tcp from any to ($wan_if) port domain
pass in log on $wan_if inet6 proto udp from any to ($wan_if) port domain
pass in log on $wan_if inet6 proto tcp from any to ($wan_if) port www
pass in log on $wan_if inet6 from to pass in log on $wan_if inet6 from to
# Allow all outbound connections
pass out log on $wan_if inet6 from to pass out log on $wan_if inet6 from to
pass out log on $wan_if inet6 proto icmp6 from ($wan_if) to any icmp6-type $icmp6_types
pass out log on $wan_if inet6 proto tcp from ($wan_if) to any
pass out log on $wan_if inet6 proto udp from ($wan_if) to any
[/cc]

To enable the above rule set without rebooting, run the following:

[cc lang=”bash”]
$ pfctl –f /etc/pf.conf
[/cc]

To enable packet filter after a reboot, add the following entries to /etc/rc.conf:

[cc lang=”bash”]
$ cat /etc/rc.conf | grep pf
pf_enable=”YES”
pflog_enable=”YES”
[/cc]

As you can see, I’ve just duplicated the IPv4 rule set and modified the syntax to suit IPv6. In fact, about the only different between the two of them is how ICMPv6 is handled, and the rules allowing access to link-local and multicast address types. One of the big changes with IPv6 is the elimination of the broadcast address. In its place, support for multicast has been expanded, and the new anycast address type has been introduced.

The link-local addresses in IPv6 are used for stuff like router and neighbour advertisements and solicitations, and this traffic is required to work properly. In fact, it’s worth noting that in the routing table snippet I showed in, I could have configured the default gateway to be the link-local address of the router on the subnet, and it would have worked. This is largely irrelevant here, but has potential implications for how IPv6 support is configured over PPP and other tunneled links, wherein the tunnel can be configured to use link-local addresses at both sides, rather than using global addresses for tunnels between hosts.

Sorry, the comment form is closed at this time.