OpenVPN and IPv6

You might also like

Download as pdf or txt
Download as pdf or txt
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

Success!
Man, oh man, the hours of research and experimentation it took to nally
discover the rightoptions 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
trickis to use the client-con g-dir option on the server.

So, with that in mind, lets begin.

The working con g

The server side.

Starting out, Ill 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 myOpenVPN /etc/openvpn/v6_server.conf le:

# OpenVPN configuration file for


# IPv6 tunnel using TLS
https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 1/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

port 1194
proto udp

dev tun

# TLS is required for server/server-ipv6,


# server-ipv6 is required for ccd/DEFAULT,
# ccd/DEFAULT is required for routing
tls-server

server 10.8.0.0 255.255.255.0


keepalive 10 120

user nobody
group nogroup

persist-key
persist-tun

status openvpn-status.log
verb 4
mute 20
mute-replay-warnings

# MTU magic
tun-mtu 1480
fragment 1428
mssfix 1428

;comp-lzo

# faster to process on RPi


cipher AES-128-CBC

# client IP can be dynamic


float
# HE.net resolver.
push "dhcp-option DNS 2001:470:20::2"

# http://winaero.com/blog/speed-up-openvpn-and-get-faster-speed-over-its-
channel/
# suggested for use over UDP:
sndbuf 212992
rcvbuf 212992
push "sndbuf 212992"
push "rcvbuf 212992"

# Private ULA network for the tunnel itself. Doesn't get routed.
;server-ipv6 fd00::/112

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 2/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

# with deprecated Site-Local Addresses instead


#
# site-local prefix is fec0::/10, and smallest subnet OpenVPN supports is
/112,
# 64k addresses. These include feee::/16 and feed::/16 as well. :)
# Here, I'm going to use feed::/112, representing feed::0 through
feed::ffff
server-ipv6 feed::/112

# direct ipv6 traffic thru this interface


;push "route-ipv6 2000::/3"
push "route-ipv6 ::/0"

# if this is active, need to set up NAT for


# the IPv4 tunnel endpoint
;push "redirect-gateway def1 bypass-dhcp"

ca ca.crt
cert server.crt
key server.key
tls-auth ta.key 0
dh dh2048.pem

# site specific routing


config ccd/routes.conf
client-config-dir ccd

(This should hopefully work without modi cation where youre at but
remember if yours is di erent enough that this hiccups, please dont get angry
at me!)
Now, /etc/openvpn/ccd/routes.conf. This will be di erent for every site, and
uses the information from the tunnelbroker.nettunnel detail page.

# 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:

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 3/15
8. 7. 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 /48.
# the :0: here makes explicit what is implied
iroute-ipv6 2001:db8:1234:0::/64

If you will onlyever have one client, you can simplyname this leccd/DEFAULT
instead.

The client

For the client (in my case, a Raspberry Pi 1B running Debian jessie), I again
removed the client-speci c data into its own le, which I named
/etc/openvpn/client.params.

rst, the le/etc/openvpn/v6_tunnel.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
;mssfix 1428
;comp-lzo

# for when our connection isn't up yet, or flaky


resolv-retry infinite
nobind

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 4/15
8. 7. 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.


verb 4

# Silence repeating messages


mute 20
# Wireless networks often produce a lot
# of duplicate packets. Set this flag
# to silence duplicate packet warnings.
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.params

Once again, this is the generic portion of the con guration, with nothing site-
speci c.

Next, the le/etc/openvpn/client.params, with the the hostname of our server,


and our certi cate les inlined:

# The hostname/IP and port of the server.


remote my-example-server-hostname.us-west-2.compute.amazonaws.com 1194

# Here, we have inlined ca, cert, key, and tls-auth key files.
#ca ca.crt
#cert client.crt
#key client.key
#tls-auth ta.key 1

<ca>
...
</ca>

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 5/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

<cert>
...
</cert>
<key>
...
</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).
key-direction 1

<tls-auth>
...
</tls-auth>

Note that with Debian jessie on the Pi, you have to enable the OpenVPN
connection by name using systemctl:

sudo systemctl enable openvpn@v6_tunnel.service

I added the following lines to /etc/network/interfaces, to set our br0 toact 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.conf to enable IPv6 Router Advertisements on


br0:

dhcp-range=::, constructor:br0, ra-stateless, ra-names, ra-advrouter, 1h


#
dhcp-option=option6:dns-server, [::]
dhcp-option=option6:ntp-server, [2001:470:0:50::2]

Routing, part 1
https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 6/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

Routing, part 1
Setting up OpenVPN is simple enough, there are recipes all over the Internet for
doing that. But in my speci c case, I also want to tunnelIPv6 tra c through the
VPN. So after the clientis connected, some kind of routing information will
have to be con gured, such that the server knows that the given client is
responsible for a given network (or networks) that lives down that
connection, and the client knows that the rest of the IPv6 Internet lives up
the VPN connection.

So that covers routing in general. It took a LOT of experimenting to gure out


how to get it to go (because while the docs have information, its just not
obvious how the options apply),but I eventually found the trick, which like most
tricks is dead simple once you know it. As mentioned above, it is as simple as
using the client-con g-dir option.

Con gurationRequirements for Routing IPv6 via OpenVPN

In order to use the client-con g-dir option, we need to use the server option
(and in our case, server-ipv6 as well). And in order to use server, we are
required to use TLS (tls-server and tls-client).

And in order to use TLS, we must createkeys and certi cates for the server and
for each client (even if theres only one).

Generating Certi cates

I followed the instructions on the OpenVPN website to generate all of the


certi cates I needed, which kinda seemed like a ton. In addition to client and
server certi cates, there is the DH le to generate on the server side, and an
optional TLS key that is shared between server and clients.

A word aboutInline les

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 7/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

Copying everything around and not missing any details was a little confusing to
straighten out. But in searching for instructions on how to do this properly, I
found the concept of inline les for OpenVPN con guration. Speci cally, rather
than require a le like client.crt to be present, and to be mentioned in the
con g le like so:

cert client.crt

we can instead inline the contents of the le client.crt directly into the
con g le, using an XML-like syntax:

<cert>
[certificate data]
</cert>

This can be done with ca, cert, key, dh (only required for the server), and tls-
auth.

Normally, the tls-auth directive looks like this, with a 0 for the server side, and
1 for the client side:

tls-auth ta.key 0

However, the inline le support doesnt handle the extra number at the end.
Insteadthe key-direction optionis used to specify thesecond value.

key-direction [0 or 1]

So, after generating all of the certi cates, and cut/pasting the le data inline,
the certi cate and key data will looklook about like this:

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 8/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

<ca>
...
</ca>

key-direction [0 or 1]
<tls-auth>
...
</tls-auth>
<cert>
...
</cert>
<key>
...
</key>

It should be noted that if the client con guration is all present in a single le
and renamed to have a .ovpn extension, this is the normal way to distribute a
con guration le for the GUI version of OpenVPN, and to work with things like
Network Manager in Ubuntu.

A word about splitting les

Ive managed to distill my con guration down so I could divide it into the part
that is always the same, and the part that is site or client dependent. OpenVPN
has no problem reading external les for additional con g information, so Ive
got my setup for both client and server down to a main con g le that is static,
and a le thats included that has my speci c address information.

On the server side,I have to use a ccd/ directory anyway, and since that folder
holds client-speci c data on routing, it made sense to me as a place to store the
secondary include le routes.conf.

Route and CCD Con guration

A word about routing, Part 2

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 9/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

So in order to route packets through the tun0 interface created by OpenVPN, I


need to assign addresses to each end of the tunnel. This is done using IPv4 with
the serveroption. In my con g le, this is how the option looks, using the
network 10.8.0.XXX for the interface:

server 10.8.0.0 255.255.255.0

For the server-ipv6 option, at rst I had a problem where do I get the
addresses from, to go on each end of the tunnel? Since I hadnt yet discovered
the client-con g-dir option, using private addresses didnt seem to
work.Isolved it at rst by splitting my assigned /64 in half, into two /65
networks. 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. Which worked, but was tricky to deal with because most
everything expects to see /64 networks, and NOT /65 (speci cally, dnsmasq has
a way to specify the bits, but unless I used a small, static pool of addresses for
DHCP, the con g wouldnt read the number 65 in the con gurationwithout
throwing an error).

In the v6_server.conf le, this looked like:

server-ipv6 2001:db8:b:b02:8000::/65

Another optionI consideredwas to use the whole /64 for justthe point-to-point
connection, and then useone or more of the networks ofmy routed /48 on the
local side.

Then, after I found the client-con g-dirsetting and routingbegan towork


correctly, I revisited the issue of addresses for the tunnel. Theoretically, I
thought, Ishould be able to use a pair of private IPv6 addresses, corresponding
tothe 10.X.X.X or 192.168.X.X addresses of IPv4. So I went looking up what to
use for this, and immediately found the concept of Unique Local Addresses in
IPv6. A valid ULA is any address that begins with FDxx. The docs are a little

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 10/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

confusing about this, because the o cial RFC documents reserve the networks
FC00::/7, but whats 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, the valid neworke range becomes FD00::/8. Also according to the
docs, you are supposed to pick a string of 40 random bitsto ll in the rest of the
rst 64 bits of the network address, in case your organization ever connects
with another, and so your individual ULA addresses wont con ict. This is of
course, way, WAY more than Im worried about, so I just went with the simplest
version, using a /112 netmask, 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, and freed
up the addresses I had used out of my routed /64, and simpli ed my local server
setup considerably.

One thing changed in a way I didnt expect wasthatnow traceroute6 (or tracert
on Windows) showed the OpenVPN hop quite clearly:

C:\>tracert -d ipv6.he.net

Tracing route to ipv6.he.net [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.

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 11/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

But I wasnt done ddling with it yet. Mentioned in the article on ULAs was that
there was an older version of the concept, called Site-Local Addresses. The only
di erence from MY point of view as a sysadmin was that the addresses started
with FExxinstead of FDxx. WhenI tried it, It worked just the same as the ULA
did, with one important di erence: this time, the traceroute did NOT show the
address of the OpenVPN endpoint, but the real IPv6 address of the next hop:

C:\>tracert -d ipv6.he.net

Tracing route to ipv6.he.net [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 complete.

Since its private, and it works, and does so in an interesting and useful way,
Im sticking with that. So I picked a valid Site Local pre x thats easy to
remember. Now, my v6_server.conf says:

server-ipv6 feed::/112

And when my client connects, it gets the endpoint address feed::1000, with an
upstream address (the server) as feed::1.

Server Routes

The leroutes.conf on the server needs to have aroute option for every
network this server intends to handle. Speci cally, we need one for our
assigned /64 network, and if we have a routed /48, one for that as well.
CCD Files
https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 12/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

CCD Files

The le included by the client-con g-dir option isloaded when a client with
that name (as listed in their client.crt le) connects. If you only ever intend to
run one client, you can just name this le ccd/DEFAULT.

The le must contain aniroute directive for each network that client is
responsible for. If you only have the single /64, it only needs 1 line:

iroute-ipv6 2001:db8:b:b02::/64

If, as in my case, you have a routed /48, you can direct the entire thing to the
client with another, similar line:

iroute-ipv6 2001:db8:123::/48

But I intend to run multiple cilents as I continue to experiment, so Im only


assigning the FIRST of the 64kavailable /64networks in my /48 to megan, and
leaving the rest for later. So the second line inccd/megan becomes, 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, part 1

Once the routing is correct, the most critical piece of understanding and setup
involveschoosing the correct MTU settings. The MTU is the Max Transmission
Unit, which means the largest packet size, including headers, that is allowed to
go over a given wire (Layer 2 link). For example, Ethernet has a real wire, and

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 13/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

the MTU is 1500. WiFi has a radio wire, and also uses 1500.Usually this is
handled without any user intervention.

However, all this tunneling adds a few wrinkles. First of all, the initial
6in4tunnel immediately reduces MTU by 20 bytes down to 1480, because the
information being transferred consists of IPv6 headers and data, INSIDE of a
packet with a 20-byte IPv4 header.

And thenOpenVPN adds its own serious chunk of overhead data to the packet
data, which is not always the same number of bytes (depending on how its
con gured), and is very non-obvious to determine because of the way OpenVPN
handles its own internal bu ers. Normally, OpenVPN has reasonable default
settings that work ne, however our case is enough di erent that the defaults
wont work out of the box. The short version is,even if the rest of the
tunneling is set up correctly, youre going to have nothing but problems until
the MTU is correctly accounted for. This is mostly becausethe 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.

Thevalues for thefragment andmss x parameters were found by trial and


error, and made the di erence between geeze, this is supposed to beworking!
and oh, wow, nally! I did a lot more experimentation with the various MTU
related parameters, but the details will have to wait for the next entry.

A word on Router Advertisements and DHCPv6

I knew fromthe beginning of this project that I would be serving IPv6 from this
machine, and for that reason I was drawn to using dnsmasq for my DHCP
needs, as it can handle IPv4 DHCP requests, IPv6 DHCP requests, and IPv6
autocon guring router advertisements, all in addition to functioning as a DNS
forwarder and cache.

It turns out that dnsmasq will autocon gure its IPv6 information using the
assigned address of giveninterface. This meansI dont have to add my speci c
network con guration to/etc/dnsmasq.conf.

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 14/15
8. 7. 2017 OpenVPN and IPv6 Because I'm a geek

Im still playing with the optimum con guration, but for now it looks as if the
ra-stateless option makes most clients work, ra-names is the preferred mode
for iPhone/iPad, and ra-advrouter was what made my Android phone start
working correctly. I still havent managed to gure out the distinctions between
all of the modes yet, but this con gurationworks, so thats good enough for
now.

Advertisements

September 21, 2016

Because I'm a geek /

https://cuzimageek.wordpress.com/2016/09/21/openvpn-and-ipv6/ 15/15

You might also like