You are on page 1of 15

8. 7.

2017 OpenVPN and IPv6 – Because I'm a geek…

Because I'm a geek…
Interesting computer things I'm working on.

OpenVPN and IPv6

Man, oh man, the hours of research and experimentation it took to nally
discover the right options in OpenVPN to make my IPv6 routing go. Still, now I
know how it works, and now I can explain it to you. For the impatient, the
trick is to use the client-con g-dir option on the server.

So, with that in mind, let’s begin.

The working con g

The server side.

Starting out, I’ll show the con guration les for my setup, then explain how
things work.

Because OpenVPN requires that I con gure the routing information I want to set
up using a separate le per client, I decided to  additionally put my site-speci c
routing information into a separate le /etc/openvpn/ccd/routes.conf, and
include it from the main con guration. Turns out, setting up this way you only
have to put 1 or 2 lines in that le.

So to begin, here is my OpenVPN /etc/openvpn/v6_server.conf le:

# OpenVPN configuration file for
# IPv6 tunnel using TLS 1/15

0. 2017 OpenVPN and IPv6 – Because I'm a geek… port 1194 proto udp dev tun # TLS is required for server/ channel/ # suggested for use over UDP: sndbuf 212992 rcvbuf 212992 push "sndbuf 212992" push "rcvbuf 212992" # Private ULA network for the tunnel 2/15 .wordpress.0 255. # server-ipv6 is required for ccd/DEFAULT.comp-lzo # faster to process on RPi cipher AES-128-CBC # client IP can be dynamic float # resolver.255. # ccd/DEFAULT is required for routing tls-server server 10. Doesn't get routed.0 keepalive 10 120 user nobody group nogroup persist-key persist-tun status openvpn-status.8. 7.8. push "dhcp-option DNS 2001:470:20::2" # http://winaero.255.log verb 4 mute 20 mute-replay-warnings # MTU magic tun-mtu 1480 fragment 1428 mssfix 1428 . .server-ipv6 fd00::/112 https://cuzimageek.

This will be di erent for every site.conf client-config-dir ccd (This should hopefully work without modi cation where you’re at… but remember if yours is di erent enough that this hiccups.8. /etc/openvpn/ccd/routes. 7.pem # site specific routing config ccd/routes.push "route-ipv6 2000::/3" push "route-ipv6 ::/0" # if this is tunnel detail page. please don’t get angry at me!) Now. :) # Here.crt cert server. need to set up NAT for # the IPv4 tunnel endpoint . I'm going to use feed::/112.push "redirect-gateway def1 bypass-dhcp" ca ca.key tls-auth ta. representing feed::0 through feed::ffff server-ipv6 feed::/112 # direct ipv6 traffic thru this interface .crt key server. # Routed IPv6 Prefixes # Routed /64: 2001:db8:b:b02::/64 # Routed /48: 2001:db8:1234::/48 route-ipv6 2001:db8:b:b02::/64 # only necessary if you requested a /48 route-ipv6 2001:db8:1234::/48 and the le ccd/megan: 3/15 .wordpress. These include feee::/16 and feed::/16 as well.conf. 2017 OpenVPN and IPv6 – Because I'm a geek… # with deprecated Site-Local Addresses instead # # site-local prefix is fec0::/10. # 64k addresses. and uses the information from the tunnelbroker.key 0 dh dh2048. and smallest subnet OpenVPN supports is /112.

a Raspberry Pi 1B running Debian jessie). 7. the le /etc/openvpn/v6_tunnel. which I named /etc/openvpn/client. I again removed the client-speci c data into its own le.conf: ############################################### # client-side OpenVPN config file # for connecting to IPv6 gateway tls-client # must match on both ends dev tun proto udp cipher AES-128-CBC # MTU magic tun-mtu 1480 fragment 1428 # set on the server side .comp-lzo # for when our connection isn't up yet.mssfix 1428 . # the :0: here makes explicit what is implied iroute-ipv6 2001:db8:1234:0::/64 If you will only ever have one client. or flaky resolv-retry infinite nobind https://cuzimageek.params. The client For the client (in my case. you can simply name this le ccd/DEFAULT instead. 2017 OpenVPN and IPv6 – Because I'm a geek… # Routed /64: iroute-ipv6 2001:db8:b:b02::/64 # I've assigned megan the first subnet from our routed / 4/15 . rst.wordpress.8.

key 1 <ca> .amazonaws. key. verb 4 # Silence repeating messages mute 20 # Wireless networks often produce a lot # of duplicate packets. we have inlined ca.key #tls-auth ta.crt #key client.params Once again. cert. and tls-auth key files. mute-replay-warnings # apply DNS options from server script-security 2 up /etc/openvpn/update-resolv-conf down /etc/openvpn/update-resolv-conf ns-cert-type server config client..wordpress. </ca> 1194 # Here.compute. with the the hostname of our server. 2017 OpenVPN and IPv6 – Because I'm a geek… # Downgrade privileges after initialization (non-Windows only) user nobody group nogroup persist-key persist-tun # Set log file verbosity. the le /etc/openvpn/client. Set this flag # to silence duplicate packet warnings.8. #ca ca. Next. with nothing site- speci c. and our certi cate les inlined: # The hostname/IP and port of the server.crt #cert client. 7.params. this is the generic portion of the con 5/15 . remote

wordpress. [::] dhcp-option=option6:ntp-server. 2017 OpenVPN and IPv6 – Because I'm a geek… <cert> . ra-names.service I added the following lines to /etc/network/interfaces. part 1 https://cuzimageek. constructor:br0. 7. 1h # dhcp-option=option6:dns-server. 6/15 . [2001:470:0:50::2] Routing.8. ra-advrouter. </key> # Notice that --tls-auth takes a direction (1/0) when using it from a file.. but # when using tls-auth inline you must also use --key-direction (1/0).. you have to enable the OpenVPN connection by name using systemctl: sudo systemctl enable openvpn@v6_tunnel. </tls-auth> Note that with Debian jessie on the Pi..conf to enable IPv6 Router Advertisements on br0: dhcp-range=::.. key-direction 1 <tls-auth> ... to set our br0 to act as the router for our assigned /64 network: iface br0 inet6 static address 2001:470:b:b04::1 netmask 64 Then I updated /etc/dnsmasq. </cert> <key> .

but I eventually found the trick. As mentioned above. So that covers routing in general.8.wordpress. And in order to use TLS. 7. we need to use the server option (and in our case. I also want to tunnel IPv6 tra c through the VPN. So after the client is connected. 2017 OpenVPN and IPv6 – Because I'm a geek… Routing. server-ipv6 as well). there are recipes all over the Internet for doing that. In addition to client and server certi cates. it’s just not obvious how the options apply). Con guration Requirements for Routing IPv6 via OpenVPN In order to use the client-con g-dir option. part 1 Setting up OpenVPN is simple enough. we are required to use TLS (tls-server and tls-client). which kinda seemed like a ton. we must create keys and certi cates for the server and for each client (even if there’s only one). such that the server knows that the given client is responsible for a given network (or networks) that lives “down” that connection. some kind of routing information will have to be con gured. It took a LOT of experimenting to gure out how to get it to go (because while the docs have information. which like most tricks is dead simple once you know it. there is the DH le to generate on the server side. and the client knows that the rest of the IPv6 Internet lives “up” the VPN 7/15 . Generating Certi cates I followed the instructions on the OpenVPN website to generate all of the certi cates I needed. And in order to use server. it is as “simple” as using the client-con g-dir option. But in my speci c case. and an optional TLS key that is shared between server and clients. A word about Inline les https://cuzimageek.

using an XML-like syntax: <cert> [certificate data] </cert> This can be done with ca.key 0 However.8. key. and 1 for the client side: tls-auth ta. with a 0 for the server side. rather than require a le like client.crt  directly into the con g  le. Normally.wordpress. Speci cally. 7. I found the concept of inline les for OpenVPN con guration. after generating all of the certi cates. the inline le support doesn’t handle the extra number at the end.crt … we can instead inline the contents of the le client. 2017 OpenVPN and IPv6 – Because I'm a geek… Copying everything around and not missing any details was a little confusing to straighten out. the certi cate and key data will look look about like this: https://cuzimageek. and cut/pasting the le data inline. Instead the key-direction option is used to specify the second value. dh (only required for the server). But in searching for instructions on how to do this properly. key-direction [0 or 1] So.crt to be present. 8/15 . and tls- auth. the tls-auth directive looks like this. and to be mentioned in the con g le like so: cert client.

7..wordpress...8. this is the “normal” way to distribute a con guration le for the GUI version of 9/15 . it made sense to me as a place to store the secondary include le routes.. I have to use a ccd/ directory anyway. OpenVPN has no problem reading external les for additional con g information. and a le that’s included that has my speci c address information. A word about splitting les I’ve managed to distill my con guration down so I could divide it into the part that is always the same. </cert> <key> .ovpn extension. On the server side. and to work with things like Network Manager in Ubuntu.. </ca> key-direction [0 or 1] <tls-auth> ... Route and CCD Con guration A word about routing. </tls-auth> <cert> . and the part that is site or client dependent. </key> It should be noted that if the client con guration is all present in a single le and renamed to have a .conf. 2017 OpenVPN and IPv6 – Because I'm a geek… <ca> . Part 2 https://cuzimageek.. so I’ve got my setup for both client and server down to a main con g le that is static. and since that folder holds client-speci c data on routing.

168. but was tricky to deal with because most everything expects to see /64 networks.0 255.0 For the server-ipv6 option. corresponding to the 10. I thought.conf le.8. Then. dnsmasq has a way to specify the bits.8. and NOT /65 (speci cally. using the network 10. this is how the option looks. and then use one or more of the networks of my routed /48 on the local 10/15 . and immediately found the concept of Unique Local Addresses in IPv6. to go on each end of the tunnel? Since I hadn’t yet discovered the client-con g-dir option.X.  The docs are a little https://cuzimageek. this looked like: server-ipv6 2001:db8:b:b02:8000::/65 Another option I considered was to use the whole /64 for just the point-to-point connection. In my con g le.0.  I solved it at rst by splitting my assigned /64 in half. into two /65 networks.0. Which worked.wordpress.255. 7. the con g wouldn’t read the number “65” in the con guration without throwing an error). In the v6_server.X addresses of IPv4. using private addresses didn’t seem to work. I need to assign addresses to each end of the tunnel.X. at rst I had a problem… where do I get the addresses from. I should be able to use a pair of private IPv6 addresses. after I found the client-con g-dir setting and routing began to work correctly. Then I used the second half of the network (2001:db8:b:b02:8000::/65 vs 2001:db8:b:b02:0000::/65) for the tunnel endpoint addresses. Theoretically. static pool of addresses for DHCP. but unless I used a small.XXX for the interface: server 10. This is done using IPv4 with the server option.X or 192. 2017 OpenVPN and IPv6 – Because I'm a geek… So in order to route packets through the tun0 interface created by OpenVPN.X.255. I revisited the issue of addresses for the tunnel. A valid ULA is any address that begins with FDxx.8. So I went looking up what to use for this.

wordpress. the valid neworke range becomes FD00::/8. way. 7. 2017 OpenVPN and IPv6 – Because I'm a geek… confusing about this. using a /112 11/15 . and simpli ed my local server setup considerably.8. and freed up the addresses I had used out of my routed /64. which “restricts” the address pool to the 65k addresses available in the last 2 bytes: server-ipv6 fd00::/112 And it WORKED! It worked exactly as I had originally hoped it would. you are supposed to pick a string of 40 random bits to ll in the rest of the rst 64 bits of the network address. https://cuzimageek. in case your organization ever connects with another. and so your individual ULA addresses won’t con ict. WAY more than I’m worried about. Also according to the [2001:470:0:64::2] over a maximum of 30 hops: 1 1 ms 1 ms <1 ms 2001:db8:b:b02::1 2 25 ms 24 ms 25 ms fd00::1 3 42 ms 36 ms 36 ms 2001:db8:a:b02::1 4 36 ms 43 ms 32 ms 2001:470:0:9b::1 5 54 ms 69 ms 62 ms 2001:470:0:1fe::1 6 59 ms 56 ms 51 ms 2001:470:0:2f::1 7 53 ms 53 ms 56 ms 2001:470:0:64::2 Trace complete. because the o cial RFC documents reserve the networks FC00::/7.he.he. One thing changed in a way I didn’t expect was that now traceroute6 (or tracert on Windows) showed the OpenVPN hop quite clearly: C:\>tracert -d ipv6. This is of Tracing route to ipv6. so I just went with the simplest version. but what’s not immediately obvious is that the /7 means the nal bit is not speci ed… but the network range speci ed by 0 is invalid! With that bit holding a 1.

I’m sticking with that. So I picked a valid Site Local pre x that’s easy to remember. one for that as well. 2017 OpenVPN and IPv6 – Because I'm a geek… But I wasn’t done ddling with it yet. It worked just the same as the ULA [2001:470:0:64::2] over a maximum of 30 hops: 1 1 ms 1 ms 1 ms 2001:db8:b:b02::1 2 27 ms 25 ms 25 ms 2001:db8:a:b02::2 3 62 ms 43 ms 39 ms 2001:db8:a:b02::1 4 46 ms 37 ms 35 ms 2001:470:0:9b::1 5 62 ms 59 ms * 2001:470:0:1fe::1 6 54 ms 53 ms 52 ms 2001:470:0:2f::1 7 69 ms 55 ms 55 ms 2001:470:0:64::2 Trace Tracing route to ipv6.wordpress. 7. called Site-Local 12/15 . Mentioned in the article on ULAs was that there was an older version of the concept.he. it gets the endpoint address feed::1000. and it works. but the “real” IPv6 address of the next hop: C:\>tracert -d ipv6.  Speci cally. my v6_server. When I tried it.he. with one important di erence: this time. and does so in an interesting and useful way.conf on the server needs to have a route option for every network this server intends to handle. the traceroute did NOT show the address of the OpenVPN endpoint. with an upstream address (the server) as feed::1.  Now. The only di erence from MY point of view as a sysadmin was that the addresses started with FExx instead of FDxx. we need one for our assigned /64 network. Since it’s private.8. and if we have a routed /48. Server Routes The le routes. CCD Files https://cuzimageek.conf says: server-ipv6 feed::/112 And when my client connects.

2017 OpenVPN and IPv6 – Because I'm a geek… CCD Files The le included by the client-con g-dir option is loaded when a client with that name (as listed in their client. you can just name this le ccd/DEFAULT. Ethernet has a real wire.crt le) connects. that is allowed to go over a given “wire” (Layer 2 link). which means the largest packet size. 7. the most critical piece of understanding and setup involves choosing the correct MTU settings. it only needs 1 line: iroute-ipv6 2001:db8:b:b02::/64 13/15 . similar line: iroute-ipv6 2001:db8:123::/48 But I intend to run multiple cilents as I continue to experiment. for my setup: # the :0 here is making explicit which network I'm assigning iroute-ipv6 2001:db8:1234:0::/64 A word on MTU. as in my case. part 1 Once the routing is correct. If you only have the single /64. The le must contain an iroute directive for each network that client is responsible for. so I’m only assigning the FIRST of the 64k available /64 networks in my /48 to megan. and leaving the rest for later. If you only ever intend to run one client. you can direct the entire thing to the client with another. you have a routed /48. For example. including headers.8. The MTU is the “Max Transmission Unit”.wordpress. and https://cuzimageek. So the second line in ccd/megan becomes.

This means I don’t have to add my speci c network con guration to /etc/dnsmasq. WiFi has a radio “wire.  The short version is. This is mostly because the VPN tunnel eats the ICMP messages that would normally cause this to be automatically and transparently adjusted without you needing to know or care about it. 2017 OpenVPN and IPv6 – Because I'm a geek… the MTU is 1500.8. INSIDE of a packet with a 20-byte IPv4 header. However. as it can handle IPv4 DHCP requests. and is very non-obvious to determine because of the way OpenVPN handles its own internal bu ers. nally!” I did a lot more experimentation with the various MTU related parameters. all in addition to functioning as a DNS forwarder and cache. and for that reason I was drawn to using dnsmasq for my DHCP 14/15 . First of all. because the information being transferred consists of IPv6 headers and data. Usually this is handled without any user intervention. but the details will have to wait for the next entry. and IPv6 autocon guring router advertisements. you’re going to have nothing but problems until the MTU is  correctly accounted for. IPv6 DHCP requests. The values for the fragment and mss x parameters were found by trial and error. OpenVPN has reasonable default settings that work ne.conf. And then OpenVPN adds its own serious chunk of overhead data to the packet data. wow. all this tunneling adds a few wrinkles.” and also uses 1500. 7. even if the rest of the tunneling is set up correctly.wordpress. Normally. A word on Router Advertisements and DHCPv6 I knew from the beginning of this project that I would be serving IPv6 from this machine. It turns out that dnsmasq will autocon gure its IPv6 information using the assigned address of given interface. this is supposed to be working!” and “oh. and made the di erence between “geeze. however our case is enough di erent that the defaults won’t work out of the box. the initial 6in4 tunnel immediately reduces MTU by 20 bytes down to 1480. which is not always the same number of bytes (depending on how it’s con gured). https://cuzimageek.

but for now it looks as if the ra-stateless option makes most clients 15/15 . Advertisements September 21. so that’s good enough for now. I still haven’t managed to gure out the distinctions between all of the modes yet.8. 2016 Because I'm a geek… / https://cuzimageek.wordpress. 2017 OpenVPN and IPv6 – Because I'm a geek… I’m still playing with the optimum con guration. 7. and ra-advrouter was what made my Android phone start working correctly. but this con guration works. ra-names is the preferred mode for iPhone/iPad.