web hosting

Remco Bressers' Comfort zone

Configuring native IPv6 in pfSense firewall

pfSense

Today, we’re going to talk about pfSense. A software stateful-firewall based on the excellent pf firewall in FreeBSD. It’s an easy to install from-ISO appliance.

From the pfSense website:

pfSense is a free, open source customized distribution of FreeBSD tailored for use as a firewall and router. In addition to being a powerful, flexible firewalling and routing platform, it includes a long list of related features and a package system allowing further expandability without adding bloat and potential security vulnerabilities to the base distribution. pfSense is a popular project with more than 1 million downloads since its inception, and proven in countless installations ranging from small home networks protecting a PC and an Xbox to large corporations, universities and other organizations protecting thousands of network devices.

pfSense is a nice piece of software, but the developers don’t seem to be very interested in integrating IPv6 support in the interface. Too bad, because IPv6 is hot and will replace IPv4 within the next few years. I’m not going to integrate IPv6 in the GUI of pfsense with this tutorial, but after following the instructions you will have a working IPv6 router/firewall with support for stateless autoconfiguration. The configuration is built from my own needs, so if it doesn’t match your expectations please add your features.

For this setup i use pfSense 1.2.3-RC1 which is out for quite a while and pretty stable in it’s use.

I’m not going to discuss the installation of pfSense. If you can’t install the pfSense ISO, you shouldn’t be doing IPv6 on it anyway :). First of all, make sure you enable SSH in pfSense. You can find the feature at “System” > “Advanced”

Enable SSH on pfSense

After enabling, connect (via SSH) to the pfSense box. Ofcourse, if you’re sitting behind the box you can do it on the console also :).

You will be presented a nice text menu:

*** Welcome to pfSense 1.2.3-RC1-pfSense on myFirewall ***

WAN*                     ->    bce0    ->    123.123.123.1
LAN*                     ->    bce1    ->    192.168.0.254

pfSense console setup
***********************
0)  Logout (SSH only)
1)  Assign Interfaces
2)  Set LAN IP address
3)  Reset webConfigurator password
4)  Reset to factory defaults
5)  Reboot system
6)  Halt system
7)  Ping host
8)  Shell
9)  PFtop
10)  Filter Logs
11)  Restart webConfigurator
12)  pfSense PHP shell
13)  Upgrade from console
14)  Disable Secure Shell (sshd)

We want to go to the CLI shell. Select 8.

On my box, i’m using Broadcom network interfaces. On FreeBSD these are named ‘bce0′ and ‘bce1′. You can find the respective names with the ‘ifconfig’ command. On my setup, bce0 is the outside interface and bce1 is the inside interface.
My setup is fully native-IPv6, which means that i’m not doing any tunnelling at all. On the outside interface, i have an IPv6 address from my provider’s /64 block he used for my connection. On the inside, i have  a /64 of IPv6 addresses which are publically reachable (global-unicast). Ofcourse i’m using fake addresses to prevent my firewall being bombed all-over :).

Let’s say, these are my network variables :

  • The WAN IPv6 network is : 2001:4cb8:a95:1::/64
  • The WAN IPv6 address is : 2001:4cb8:a95:1::2
  • The WAN IPv6 default gateway is : 2001:4cb8:a95:1::1
  • The LAN IPv6 network is : 2001:4cb8:b95:1::/64
  • The LAN IPv6 address is : 2001:4cb8:b95:1::1

With this information, we’re going to create our boot-script to configure the interfaces and routing.

cd /usr/local/etc/rc.d
vi 00_config-ipv6-if.sh

#!/bin/sh
#
# IFOUT = outside interface
# IFIN = inside interface
# DFGW = default gateway
IFOUT="bce0"
IFIN="bce1"
DFGW="2001:4cb8:a95:1::1"

####### Configure the stuff

# Configure the interfaces
ifconfig $IFOUT inet6 alias 2001:4cb8:a95:1::2 prefixlen 64
ifconfig $IFIN inet6 alias 2001:4cb8:b95:1::1 prefixlen 64

# Set the default route
route -n add -inet6 default $DFGW

# Configure IPv6 forwarding
sysctl net.inet6.ip6.forwarding=1

# My /etc/rtadvd.conf looks like this
#
# bce1:\
#   :addrs#1:addr="2001:4cb8:b95:1::":prefixlen#64:tc=ether:
#
# Startup rtadvd
/usr/sbin/rtadvd -d -D -c /etc/rtadvd.conf $IFIN

Ok, that’s pretty much all there is to enable IPv6 and configure the static routing to the ISP.
Next, we need to change permissions on this file :

chmod 755 /usr/local/etc/rc.d/00_config-ipv6-if.sh

After bootup, IPv6 will be running on the pfSense box, but it won’t do a thing. This is because we need to change the filter (PF) also. This is going to be our next script.

cd /usr/local/etc/rc.d
vi 10_config-ipv6-pf.sh

#!/bin/sh
#
# IFOUT = outside interface
# IFIN = inside interface
# DFGW = default gateway
IFOUT="bce0"
IFIN="bce1"

####### Configure the stuff

# Configure PF
# pfSense puts it's rules in /tmp/rules.debug for debugging purposes after boot
# We will use these rules, add IPv6 additions, read the config with pfctl and
# disable and enable PF
cat /tmp/rules.debug | sed "/User-defined rules follow/{
p;s/.*/\
pass in quick on $IFIN inet6 from any to any\\
pass out quick on $IFIN inet6 from any to any\\
pass out quick on $IFOUT inet6 from any to any\\
pass quick proto ipv6-icmp from any to any\\
pass in on $IFOUT inet6 proto tcp from any to any port 22\\
/;}" > /tmp/rules.config-ipv6.txt

# Read the new PF configuration file
pfctl -f /tmp/rules.config-ipv6.txt
pfctl -d; pfctl -e

And change the permissions also:

chmod 755 /usr/local/etc/rc.d/10_config-ipv6-pf.sh

Finally, we need to configure the router advertisement daemon (rtadvd) to get stateful autoconfiguration to work.

vi /etc/rtadvd.conf

bce1:\
  :addrs#1:addr="2001:4cb8:b95:1::":prefixlen#64:tc=ether:

After rebooting the pfSense firewall (or run script 00 and 10) IPv6 will work on your box.
But.. when you change filter rules (or anything actually) in the GUI, the filter settings are overwritten and your IPv6 connectivity will break.
After some searching on the box, i noticed that after changing things in the GUI the function filter_configure_sync() is called and the rules will be flushed.
This function can be found in /etc/inc/filter.inc (line 78). In the function, there’s a hook to a plugin directory. When the function filter_configure_sync() is called, the function will look in the /usr/local/pkg/pf directory for scripts, which will be executed. This only happens if scripts end with “.sh” as the extension.
We will symlink the 10_config-ipv6-pf.sh script to this location to make it work.

ln -s /usr/local/etc/rc.d/10_config-ipv6-pf.sh /usr/local/pkg/pf/

Congratulation! You got yourself a working IPv6 setup.

If you want to know more ins and outs about IPv6, i suggest reading the book “Running IPv6″ by Iljitsch van Beijnum. You can find more information at http://runningipv6.net/

15 Responses to Configuring native IPv6 in pfSense firewall

  1. Respect!

    But then why using pfsense at all, if it seemingly is an obstacle for the implementation? By using such an ammunition you use to hack the core functionality of the pfsense, you would better take a naked freebsd as basis for a production ipv6 router and firewall (eg. there are no magic php scripts you have to fight with in the dark of your shell).

  2. I definitely agree with you on that. In my case that’s not a problem, but if you work in a big networking team where changes in the firewall / IPSEC / OpenVPN policy get applied almost every day this is not a good option. Not everyone is skilled enough to edit on the CLI although i wish everything was. Thanks for the respect.

  3. Thanks very much for the great post, I’ve stumbled upon it multiple times in my web travels! While it may be possible to go through all this trouble to get IPv6 tunnels working through pfSense, would it be possible to simply give pfSense a link-local IPv6 address?

    The reason I ask is because I don’t necessarily need outward IPv6 connectivity yet, but when configuring servers on the network it would be nice to be able to reach the gateway over IPv6 fabric only. In other words, I’d like to be able to turn off IPv4 completely and still have a fully functioning network and web access.

    How would that be done?

  4. rbressers: (this is my 2nd post to 2nd site like here)

    Great work :)

    But i have some few issues.. I am not an CLI guy of course..So this is my story..

    1st i cd /usr/local/etc/rc.d and vi 00_config-ipv6-if.sh and then i paste this:
    #!/bin/sh
    #
    # IFOUT = outside interface
    # IFIN = inside interface
    # DFGW = default gateway
    IFOUT=”vr0″
    IFIN=”dc0″
    DFGW=”2001:4cb8:a95:1::1″

    ####### Configure the stuff

    # Configure the interfaces
    ifconfig $IFOUT inet6 alias 2001:4cb8:a95:1::2 prefixlen 64
    ifconfig $IFIN inet6 alias 2001:4cb8:b95:1::1 prefixlen 64

    # Set the default route
    route -n add -inet6 default $DFGW

    # Configure IPv6 forwarding
    sysctl net.inet6.ip6.forwarding=1

    # My /etc/rtadvd.conf looks like this
    #
    # bce1:\
    # :addrs#1:addr=”2001:4cb8:b95:1::”:prefixlen#64:tc=ether:
    #
    # Startup rtadvd
    /usr/sbin/rtadvd -d -D -c /etc/rtadvd.conf $IFIN

    then i save..I type this after saving :

    chmod 755 /usr/local/etc/rc.d/00_config-ipv6-if.sh

    and reboot…

    I type this command:
    cd /usr/local/etc/rc.d
    vi 10_config-ipv6-pf.shI

    and paste this:

    #!/bin/sh
    #
    # IFOUT = outside interface
    # IFIN = inside interface
    # DFGW = default gateway
    IFOUT=”vr0″
    IFIN=”dc0″

    ####### Configure the stuff

    # Configure PF
    # pfSense puts it’s rules in /tmp/rules.debug for debugging purposes after boot
    # We will use these rules, add IPv6 additions, read the config with pfctl and
    # disable and enable PF
    cat /tmp/rules.debug | sed “/User-defined rules follow/{
    p;s/.*/\
    pass in quick on $IFIN inet6 from any to any\\
    pass out quick on $IFIN inet6 from any to any\\
    pass out quick on $IFOUT inet6 from any to any\\
    pass quick proto ipv6-icmp from any to any\\
    pass in on $IFOUT inet6 proto tcp from any to any port 22\\
    /;}” > /tmp/rules.config-ipv6.txt

    # Read the new PF configuration file
    pfctl -f /tmp/rules.config-ipv6.txt
    pfctl -d; pfctl -e

    Save the code and i type this: chmod 755 /usr/local/etc/rc.d/10_config-ipv6-pf.sh

    Then i type this : vi /etc/rtadvd.conf

    and paste the code:

    bce1:\
    :addrs#1:addr=”2001:4cb8:b95:1::”:prefixlen#64:tc=ether:

    then save and reboot…

    After reboot i type this: ln -s /usr/local/etc/rc.d/10_config-ipv6-pf.sh /usr/local/pkg/pf/

    then reboot again..

    I go to workstation and do “ifconfig” linux or “ipconfig” for windows..

    Nothing happen really.. All i see is 192.168.4.245 ip address when i do “ipconfig”.. I dont see ip like this:

    2001:4cb8:b95:1

    My config is:

    192.168.4.0/24
    subnet mask: 255.255.255.0
    Gateway: 192.168.4.1
    WAN: isp

    I tried to change the number 64 into 24 but no luck..
    # Configure the interfaces
    ifconfig $IFOUT inet6 alias 2001:4cb8:a95:1::2 prefixlen 64 changed to 24
    ifconfig $IFIN inet6 alias 2001:4cb8:b95:1::1 prefixlen 64 changed to 24
    ….

    I use “ipconfig on windows workstations but i dont see this kind of ipv6 ips..

    jigp
    1.2.2

  5. Hi,
    Thanks!! Your investigations helped me out of a big problem ;-) I have a m0n0wall/pfSense combination and had the problem that pfSense blocked IPv6 between the (bridged) LAN and WLAN. Developers are sadly zero interested in resolving. Your Text helped me a lot to manipulate pf in needed order. But anyway.. looking for IPv6 capable home-firewall project with 802.11n capable WLAN.

  6. IPV6 will be backported from m0n0wall shortly after 2.0 releases. 2.0 will be going BETA on xmas so it is not as far off as some might think.

    And saying we do not care at all about IPV6 is false. It is extremely hard to get a IPV6 connection where we live without using a tunnel.

  7. P. Harmor

    Thanx for this howto! I now have hope again, that IPv6 and pfSense might work together, for me. However, I use a tunnel (/48) with tunnelbroker.com, and don’t yet know quite what changes need to be made to accommodate for that difference.

    ATM, my IPv4 network is trashed, as I believe it’s all trying to be routed thru the tunnel, and I’m not sure what to do to fix it…

  8. pfsense user

    P. Harmor were you able to find anything with getting this to work on tunnelbroker.com?
    I can’t get a native tunnel through my ISP either and am facing this problem

    I like how this is addressed and hope it works with tunnelbroker.com… but I just do not know :(

  9. mthode

    I know this is old but it’s worth a shot.

    All I’d need to do for vlan support is to change the interface name to be the vlan interface name?

  10. barf

    you can also use git0 interface for a 6-to-4 tunnel if you don’t have native IPv6
    ifconfig gif0 create
    ifconfig gif0 tunnel x.x.xx.xxx 192.88.99.1
    ifconfig gif0 inet6 alias 2002:beef:b00b::f00d
    route add -inet6 default -interface gif0

    but you will then need to add a route for the new ipv6 subnetwork you send router advertisments to:
    route add -net -inet6 2002:beef:b00b:face::/64 -interface rl0

  11. Shell

    @Scott Ullrich, from a long-time PFsense supporter and advocate

    I think you’ve totally missing the point we’re making, when you say “it’s extremely difficult to get ipv6 without using a tunnel”. What PFsense urgently needs (for 1.2.3 and not just the oh-so-mythical-and-long-promised-but-never-finished2.0) is a way to get tunneled IPv6 on it as the endpoint, because that’s the only way that most individuals and businesses are going to be getting v6 for some considerable time.

    Only 1 ISP where I live can even offer native IPv6, and they are 120$ a month for basic ADSL. Tunnels, however, are free, functional, available over 15$ a month ADSL, yet appear to have been ignored by the PFsense developers for _far_ too long, giving the impression that pfsense is now a legacy appliance. The situation is much the same worldwide.

    I’ve been using (at home) and recommending (to work customers) PFsense for years now, yet all but two of the pfsense boxes at those customers have been ripped out in a purge of v4-only equipment, as the replacement cycle dictates that dual-stack equipment is now required. The irony is, of course, that PFsense is dual-stack but the GUI code screws up attempts to use IPv6 properly.

    The gap between PFsense 1.2.3 and the long-awaited 2.0 has been filled by Cisco, much to my dismay, due to the slow response to requests for IPv6 in the GUI.
    Those customers will now be PFsense-less for 3-5 years until the Ciscos come up for replacement again, a tragic loss.

    Most of these companies (sohos to smb’s) bought the wonderful book about PFsense 1.2.3 but were rather annoyed to find that it’s the “end of the line”.
    We can only wonder at how much useful bounty and contributed code has been lost due to abandoning 1.2.3 and ignoring IPv6 for so long.

    ……sometimes you have to hear it from your nearest and dearest, but it had to be said, sorry

  12. @Scott Ullrich I don’t know if it makes any difference for you guys, but we are willing to provide you with native-IPv6 over a IPv4 GRE tunnel. This way you can still use native-IPv6 to test.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>