IPv6 Payload Patch for OpenVPN 2.1


Background

As of OpenVPN v2.1, OpenVPN has limited support for transporting IPv6 packets (IPv6 payload):

OpenVPN v2.1 has no support for transporting VPN packets over IPv6 transport (``IPv4, IPv6 or Ethernet inside, IPv6 outside'') either, but there are other people already working on this, so I did not touch this field. See here for JuanJo's OpenVPN-over-IPv6 patch. My patch and JuanJo's patch are mostly compatible and can be used together, to get IPv6-in-OpenVPN-over-IPv6.

The Features

The patch set below adds support for transporting IPv6 payload in point-to-multipoint (P2MP) TUN server mode. That is, you run a single OpenVPN instance on the VPN server side, and multiple clients connect to it.

Every client is assigned a single IPv6 address by the server, coming from a shared transfer network between all clients and the server. Usually this would be a common /64, but theoretically a smaller subnet could also be used (not implemented yet).

This is analogous to the IPv4 option ``--topology subnet'', implemented by OpenVPN 2.1 and up, and unlike the old ``net30'' topology that allocates a dedicated /30 per client. Since IPv6 subnets are ``big enough'' by definition, the extra effort of defining different topology options and writing the implementation could be avoided. (Depending on operating system capabilites and configured IPv4 topology, the actual tunnel interface will be configured as ``point-to-point'' or ``network'', but logically it's always a shared subnet for all clients). If a whole subnet is to be routed to a network ``behind'' an OpenVPN client (in addition to the single host address allocated automatically), this can be done with ``iroute'' and per-client configuration. No automatic support for ``receive a whole prefix from the server, do something smart with it'' (as in ``configure on internal ethernet, setup radvd, ...'') exists in the client implementation yet.

The Configuration

new options for the server side:

optionwhat it does
server-ipv6 2001:db8::/64 sort of a macro - enables IPv6 server mode, sets up local IPv6 addresses for the TUN interface on the server (ifconfig-ipv6 $prefix::1 $prefix::2), sets up ifconfig-ipv6-pool and tun-ipv6 accordingly
ifconfig-ipv6 2001:db8:5::1 2001:db8:5::2 interface configuration for TUN interface, usually setup automatically via ``server-ipv6'' on the server side and via automatic push from the server to the client.
The first address given is used for the ``tun'' interface (``ifconfig'' on the operating system side), the second address is used as a route gateway for operating systems that do not know how to setup a route to an interface without an explicit gateway IP address.
ifconfig-ipv6-pool 2001:db8:6::7/64 hand out IPv6 addresses from the specified pool with the specified netbits (/64) to the clients. Do not use IPv6 addresses lower than the one specified (in this example: ::1 to ::6 are reserved for other purposes). Usually setup automatically by ``server-ipv6''.
caveat: the implementation is currently tied to ``ifconfig-pool'' - that is, IPv6 addresses are always allocated and released together with IPv4, and if the IPv4 pool is full, no IPv6 address can be allocated either. Needs cleanup when IPv4 is finally dead.
ifconfig-pool-persist file sec not a new option, but now also used to store ``ifconfig-ipv6-pool'' assignments (for information, not used on reading)
iroute-ipv6 2001:db8:a0::/60 route an IPv6 prefix to a specific client (goes to per-client configuration file, needs ``route-ipv6'' statement to install the route from the OS to the OpenVPN server)
route-ipv6 2001:db8:1000::/60 similar to ``route'' for IPv4 - route this prefix from the operating system to the OpenVPN process, and subsequently across the tunnel. Needed to complement ``iroute-ipv6'' on the server side, and pushed to the client to get packets to the ``internal network'' routed through the tunnel.
push route-ipv6 ... tell the client to route the specific prefix via the OpenVPN tunnel
ifconfig-ipv6-push 2001:db8:1001::1 Push ``ifconfig-ipv6'' config to client, and route the specified IPv6 address to that client. To be used from ccd/ per-client configuration, analogous to ``ifconfig-push'' for IPv4.
tun-ipv6 enable IPv6 routing on the tunnel. Not strictly a new option, but was only implemented in point-to-point mode so far (with manual configuration of all the IPv6 parameters and routing).

Other Uses

While the patch was primarily built to enable point-to-multipoint tun, it should help other uses as well:

Test Results

The following table lists operating systems successfully tested in ``server-ipv6'' or ``client vs. IPv6-enabled server'' mode. If a column is empty, I have not tested this myself - it might work, or might not work, please let me know.

OS/variantserver-ipv6client-ipv6remarks
Linux/iproute2 ok, 31.12.09 ok, 31.12.09gert
Linux/ifconfig ok, 31.12.09 ok, 31.12.09gert, berniv6
Linux/ARM (Debian Squeeze)   ok, 18.06.10gert
FreeBSD 6.3/i386 ok, 01.01.10  gert
MacOS X 10.5 i386   ok, 02.01.10gert
NetBSD 3.1/Sparc64   no kernel IPv6 support on tun interfacesgert
NetBSD 5.0/Sparc64  ok, 03.01.10gert
Solaris 10U5/Sparc64  ok, 04.01.10gert
Windows XP  ok, 07.03.10gert (tap 9.7!)
OpenWRT 10.03/ar71xx ok, 10.06.10ok, 18.06.10gert (ipk here)

Other combinations that have been (mostly successfully) tested:

ClientServerremarks
unmodified 2.1rc15IPv6-enabled server warnings about unknown config options (ifconfig-ipv6, route-ipv6), but does not fail
unmodified, various client versionsIPv6-enabled server warnings about unknown config options (ifconfig-ipv6, route-ipv6), but does not fail
unmodified, various client versionspatched server, but IPv6 not enabled no visible change to the client - works as usual
older clients (debian lenny, 2.0rc11) IPv6-enabled server with lots of ``push'' options configured (long string, needing push-continuation) fails, because IPv4 ifconfig is sent in a 2nd ``push'' packet, which the older client doesn't handle (reduce number of ``push'' options)

Tests needed...:

What Does Not Work

Some things have not been implemented yet, to get this out quickly:

The Patch Sets

DateLinkChangeLog
31.12.2009 openvpn-2.1-ipv6-20091231-1.patch.gz basic client-server p2mp functionality works
tested on linux with a single simultaneous client (ping, and ssh).
iroute-ipv6 is not working yet.
01.01.2010 openvpn-2.1-ipv6-20100101-1.patch.gz iroute-ipv6 implemented and tested (Linux and FreeBSD 6), works.
tested on FreeBSD 6.3 (server side), works.
tested on NetBSD, does not work yet.
ChangeLog.IPv6 and README.IPv6 included.
03.01.2010 openvpn-2.1-ipv6-20100103-1.patch.gz fixed system-dependent stuff for NetBSD and MacOS X (major rework of tunnel open/read/write code for NetBSD, needs to use multi-af mode).
fixed setting of gateway IPv6 address for route-ipv6 config options without gateway address.
tested on MacOS 10.5 (client side). works.
tested on NetBSD 5.0/Sparc64 (client side). works!.
04.01.2010 openvpn-2.1-ipv6-20100104-1.patch.gz adapted ifconfig/route stuff and system dependent stuff (u_int32_t) for Solaris 10.
tested on Solaris 10/Sparc64 (client side) - works!. Use together with the ``new'' tun/tap driver from here.
Implement online help (openvpn --help) for new options.
14.01.2010 openvpn-2.1-ipv6-20100114-1.patch.gz fixed NetBSD-pre-4.0 which has no multi-af tunnels.
implement ``ifconfig-ipv6-push'' ccd/ option (for gizmo).
add lots of warnings to code to spot common misconfigurations.
GIT repository set up (berniv6).
16.02.2010 openvpn-2.1-ipv6-20100216-1.patch.gz print patch version on --version.
fix ``make check'' regression (revert unneeded change).
rebase to OpenVPN-Testing GIT tree.
07.03.2010 openvpn-2.1-ipv6-20100307-1.patch.gz Windows support! (needs new TUN/TAP driver, no easy-to-install binary distribution yet)
cleanup MacOS X support (clean deconfiguration of IPv6 address on close)
cleanup NetBSD support (destroy/recreate tun, remove ``old'' config)

Acknowledgement

Thanks goes to:

Binary Packages

Bernhard Schmidt has put up debian/ubuntu binary packages for easy installing of fully IPv6 capable OpenVPN, both with IPv6 transport as well as IPv6 payload.

If you use OpenWRT, I have compiled two packages (OpenVPN 2.1.1 plus my IPv6 patch, no other -devel patches) for the platforms I have available and can test. Download with "wget" to your router, install with "opkg install ./openvpn*ipv6*ipk"

(Don't send me questions whether this works for your specific OpenWRT hardware - I wouldn't know, I don't know other OpenWRT-supported platforms, and which chipsets are used inside. If your normal opkg packets have names ending in "ar71xx.ipk" or "brcm-2.4.ipk", chances are fairly good that it will work...)

Whether you trust a binary compiled by someone you don't know is your choice, of course. If you don't, just get the OpenVPN source and the patch set, review the source for backdoors, and build your own binary.

GIT repository

I'm working with Berni's repository, which can be found here:
git://git.birkenwald.de/openvpn.git
and my stuff is in the ``gert-ipv6'' branch.

There is an official OpenVPN testing repository now, to be found at:

git://openvpn.git.sourceforge.net/gitroot/openvpn/openvpn-testing.git
The IPv6 payload patch is included there, in the ``feat_ipv6_payload'' branch and also in the ``allmerged'' branch (with all OpenVPN patches currently under test, so beware :-) ).

Feebdack

If you test this, and want to report anything back (it works, it does not work, it needed a patch, ...) please contact me at gert<at>greenie.muc.de

You can also comment my blog article (German!) about this project.

Please do not send me questions for precompiled binaries for your architecture of choice. This stuff is in a quite early phase, and you should have some experience in compiling and patching open source software to make use of it (I hope that the IPv6 stuff will be integrated into the main OpenVPN line, and then the distribution vendors will of course pick it up).