Creating IPv6 tunnels within OpenVPN (a HOW-TO)

  • Hi guys,

    I'll describe a way to creating IPv6inIPv4 tunnels using pfSense and remote OpenVPN clients. In order to make things easier, I'll "waste" the 1st ipv6 of each /64 assigned to remote clients for the tunnel's remote endpoint. Simple: each /64's ::1 :) For sure what's described here can be improved, changed, modified, etc; but it's enough as a proof of concept.


    • pfSense (with IPv6 support…)
    • Something > /64 (here I'm using a /60) routed to your pfSense's WAN IPv6 address.
    • OpenVPN configured and running
    • A /64 for the client. In this case I'll use XXXX:1d70:faba:db::/64. Needless to say this /64 has to be different from the existing in the WAN interface.

    a) We have to create a GIF interface:

    Parent interface: Your OpenVPN interface.
    gif remote address: OpenVPN remote endpoint (and better use a fixed vpn address for that client so you don't have to change this every time)
    gif tunnel local address: client remote endpoint, the ::1 ipv6 of the assigned /64
    gif tunnel remote address: client local ipv6, the ::2 ipv6 of the assigned /64

    b) Assign the interface:

    c) Configure the interface:

    IPv6 address: tunnel's local ipv6. In other words: the one you used for "gif tunnel local address".

    d) Now we have to allow ipv6 traffic to flow:

    (quite self-describing I think)

    Once done all of this, we can see:

    [root@ctu ~]# ifconfig gif0
    gif0: flags=8051 <up,pointopoint,running,multicast>metric 0 mtu 1280
    **       tunnel inet –>**
           inet6 fe80::218:8bff:fe73:c97b%gif0 prefixlen 64 scopeid 0x8
    **       inet6 XXXX:1d70:faba:db::1 prefixlen 64**
           nd6 options=3 <performnud,accept_rtadv>options=1 <accept_rev_ethip_ver>[root@ctu ~]#

    The pfSense part of the tunnel is finished at this point. Now we need to setup the tunnel on the client endpoint.

    For linux:

    ifconfig sit0 up
    ifconfig sit0 inet6 tunnel ::REMOTE_OPENVPN_IPV4_ENDOPOINT
    ifconfig sit1 up
    ifconfig sit1 inet6 add LOCAL_IPV6
    route -A inet6 add ::/0 dev sit1

    REMOTE_OPENVPN_IPV4_ENDOPOINT: OpenVPN's main address. In my case,
    LOCAL_IPV6: Client's local ipv6. The same specified in "gif tunnel remote address" while creating the GIF tunnel.

    in my case:

    root @ Smaug [~]# ifconfig sit0 up
    root @ Smaug [~]# ifconfig sit0 inet6 tunnel ::
    root @ Smaug [~]# ifconfig sit1 up
    root @ Smaug [~]# ifconfig sit1 inet6 add XXXX:1d70:faba:db::2
    root @ Smaug [~]# route -A inet6 add ::/0 dev sit1
    root @ Smaug [~]#

    and here's our tunnel:

    root @ Smaug [~]# ip tunnel show sit1
    sit1: ipv6/ip  remote  local any  ttl 64  6rd-prefix XXXX::/16
    root @ Smaug [~]#

    root @ Smaug [~]# ifconfig sit0
    sit0      Link encap:IPv6-in-IPv4  
             inet6 addr: :: Scope:Compat
             inet6 addr: :: Scope:Compat
             inet6 addr: :: Scope:Unknown
             UP RUNNING NOARP  MTU:1480  Metric:1
             RX packets:0 errors:0 dropped:0 overruns:0 frame:0
             TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
             collisions:0 txqueuelen:0
             RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

    root @ Smaug [~]# ifconfig sit1
    sit1      Link encap:IPv6-in-IPv4  
             inet6 addr: fe80::ac14:65/64 Scope:Link
             inet6 addr: fe80::a64:6406/64 Scope:Link
             inet6 addr: XXXX:1d70:faba:db::2/128 Scope:Global
             UP POINTOPOINT RUNNING NOARP  MTU:1480  Metric:1
             RX packets:8120 errors:0 dropped:0 overruns:0 frame:0
             TX packets:8346 errors:0 dropped:0 overruns:0 carrier:0
             collisions:0 txqueuelen:0
             RX bytes:1186292 (1.1 MB)  TX bytes:908506 (908.5 KB)

    root @ Smaug [~]# netstat -nr -6
    Kernel IPv6 routing table
    Destination                    Next Hop                   Flag Met Ref Use If
    ::/96                          ::                         Un   256 0     0 sit0
    XXXX:1d70:faba:db::2/128       ::                         Un   256 0     0 sit1
    fe80::/64                      ::                         U    256 0     0 eth0
    fe80::/64                      ::                         Un   256 0     0 sit1
    ::/0                           ::                         U    1   0     0 sit1
    ::/0                           ::                         !n   -1  1  7680 lo
    ::1/128                        ::                         Un   0   1    57 lo
    ::             ::                         Un   0   1     0 lo
    ::                ::                         Un   0   1     0 lo
    ::             ::                         Un   0   1     0 lo
    XXXX:1d70:faba:db::2/128       ::                         Un   0   1  8241 lo
    fe80::a64:6406/128             ::                         Un   0   1     0 lo
    fe80::ac14:65/128              ::                         Un   0   1     0 lo
    fe80::5e26:aff:fe3e:6b46/128   ::                         Un   0   1     0 lo
    ff00::/8                       ::                         U    256 0     0 eth0
    ff00::/8                       ::                         U    256 0     0 sit1
    ::/0                           ::                         !n   -1  1  7680 lo
    root @ Smaug [~]#

    And, finally…

    root @ Smaug [~]# ping6
    PING 56 data bytes
    64 bytes from 2a00:1450:8002::6a: icmp_seq=1 ttl=53 time=52.7 ms
    64 bytes from 2a00:1450:8002::6a: icmp_seq=2 ttl=53 time=52.9 ms
    64 bytes from 2a00:1450:8002::6a: icmp_seq=3 ttl=53 time=53.7 ms
    64 bytes from 2a00:1450:8002::6a: icmp_seq=4 ttl=53 time=51.9 ms

    And you can reach the client's ipv6 from the internet:

    root @ aries [~]# ping6 XXXX:1d70:faba:db::2
    PING XXXX:1d70:faba:db::2(XXXX:1d70:faba:db::2) 56 data bytes
    64 bytes from XXXX:1d70:faba:db::2: icmp_seq=1 ttl=53 time=57.1 ms
    64 bytes from XXXX:1d70:faba:db::2: icmp_seq=2 ttl=53 time=61.4 ms
    64 bytes from XXXX:1d70:faba:db::2: icmp_seq=3 ttl=53 time=58.5 ms

    The client side, of course, can be any other thing than linux, but I'm sure everyobdy here would know how to port the configuration to other OS commands.

    As said, just a proof of concept :)


  • Are you aware that you can already use IPv6 with OpenVPN? You can just fill in a IPv6 prefix in the pfSense webui for the server settings.

    make sure to get the updated openvpn client with patches from

    That way you just get a ipv6 address on any client that connects to the OpenVPN server. You can also add routes to push to these clients as well as a default route.

  • He he… that patches page is on my "to check" bookmars waitting to be examined. And yes: in that way (native openvpn support) things are simpler (the result is almost the same more or less). But the described method can be easily ported to a non-openvpn tunnel.



  • i`m doing something like this but only with OpenVPN, not GIF on my pfsense.

    The difference is that i run OpenBGP package on pfSense and Quagga on the others Linux box.

    In Advanced config i have..

    mode p2p;
    ifconfig-ipv6 2001:ffff::1 2001:ffff::2;

Log in to reply