Limited IPv6 support built into the Access Server

Can Access Server accept incoming IPv6 tunnels?

No. The OpenVPN Access Server product is still primarily an IPv4 system and requires an IPv4 address for its OpenVPN daemons to process incoming connections. But the tunnels themselves can transport IPv6 packets. We call the information inside the tunnel itself the payload layer or tunnel layer, and the encrypted packets that the OpenVPN daemon transports between VPN client and VPN server are the transport layer.

Can Access Server transport IPv6 in the VPN tunnel?

Yes, Starting with Access Server 2.0, IPv6 is supported at the tunnel layer (but not the transport layer).

Enable IPv6 routing:

./confdba -mk "vpn.routing6.enable" -v "true"

Route all IPv6 traffic through tunnel:

./confdba -mk "vpn.client.routing6.reroute_gw" -v "true"

Create a default pool of IPv6 addresses to assign to tun interfaces (the fd4a... subnet below is just a random non-routed address):

./confdba -mk "vpn.server.daemon.vpn_network6.0" -v "fd4a:e7ae:b84b:09c2::/112"

If your kernel doesn't support IPv6 connection tracking, you must tell AS to disable all IPv6 packet filtering, otherwise netfilter will drop all VPN packets:

./confdba -mk "ip6tables.vpn.disable.filter" -v "true"
./confdba -mk "ip6tables.vpn.disable.mangle" -v "true"

If your kernel doesn't support IPv6 NAT (requires the Linux 3.7 kernel at a minium), you must disable it:

./confdba -mk "vpn.server.nat6" -v "false"

IPv6 example

This example uses an Ubuntu 12 VPS to setup an IPv6 VPN with routable addresses, i.e. the IPv6 addresses distributed to clients are public and routable. Start with the AS turned off:

/etc/init.d/openvpnas stop

Next, configure the AS for IPv6 tunnel support without NAT (see above for descriptions of the purpose of each command):

cd /usr/local/openvpn_as/scripts
./confdba -mk "vpn.routing6.enable" -v "true"
./confdba -mk "vpn.client.routing6.reroute_gw" -v "true"
./confdba -mk "vpn.server.daemon.vpn_network6.0" -v "fd4a:e7ae:b84b:09c2::/112"
./confdba -mk "ip6tables.vpn.disable.filter" -v "true"
./confdba -mk "ip6tables.vpn.disable.mangle" -v "true"
./confdba -mk "vpn.server.nat6" -v "false"

The test VPS system has 16 public IPv6 addresses in the 2605:6400:2:fed5:22::/80 subnet (replace this subnet with your own).

I removed 4 of them from venet0 and reassigned them to the AS.

For each ADDR to remove:

/sbin/ip -6 addr del <ADDR>/128 dev venet0

Next, I created a test user called test and an AS group ipv6_public containing the 4 IPv6 addresses that I repurposed from venet0 using these custom JSON user properties:

{
  "ipv6_public": {
    "group_declare": "true",
    "group_range.0": "10.99.98.40-64",
    "group_range6.0": "2605:6400:2:fed5:22:9000:a238:3b6a",
    "group_range6.1": "2605:6400:2:fed5:22:4b4f:d862:3c4",
    "group_range6.2": "2605:6400:2:fed5:22:7621:5784:fd45",
    "group_range6.3": "2605:6400:2:fed5:22:24d4:554e:9bd5",
    "group_subnets.0": "10.99.98.0/24",
    "group_subnets6.0": "2605:6400:2:fed5:22::/80",
    "type": "group"
  },
  "test": {
    "conn_group": "ipv6_public",
    "prop_autologin": "true",
    "type": "user_connect"
  }
}

Import above JSON user properties:

./confdba -ulf <json-properties-file>

When user test logs in, one of the 4 addresses above from the 2605:6400:2:fed5:22::/80 subnet will be assigned. Note that it is generally necessary that public IPv6 addresses should be assigned to clients via a group, as is done above, to avoid conflicts with the network interface.

Now start the AS:

/etc/init.d/openvpnas start

Finally, generate a client config for user test:

cd /usr/local/openvpn_as/scripts
./sacli --user test GetAutologin >~/ipv6.ovpn

IPv6 config keys

vpn.routing6.enable : bool
Enable IPv6 routing.
vpn.server.nat6 : bool
Enable IPv6 NAT (if underlying kernel supports it).
vpn.server.nat6.masquerade : bool
Enable IPv6 masquerade (if underlying kernel supports it).
vpn.client.routing6.reroute_gw : bool
Route all IPv6 traffic through tunnel.
vpn.server.daemon.vpn_network6 : list of subnets
Default IPv6 VPN subnets to be subdivided among OpenVPN daemons and:
  1. used by clients as a VPN routing gateway, and
  2. allocated to non-group clients.
vpn.client.routing6.inter_client : bool
Enable client-to-client IPv6 traffic.
vpn.server.routing6.private_access : string
Controls how private traffic should be routed:
  1. nat
  2. route
  3. none
vpn.server.routing6.gateway_access : bool : default=true
If true, clients may access the server-side tun gateway IPv6 address.
vpn.server.routing6.allow_private_nets_to_clients : bool
If true, all IPv6 addresses in vpn.server.routing6.private_network will be allowed to initiate connections with clients.
vpn.server.routing6.private_network : list of subnets
Access granted to private server-side subnets.
vpn.server.routing6.incoming_network : list of subnets
IPv6 addresses within this range may initiate connections with VPN clients.
vpn.server.routing6.routed_subnets : list of subnets
Subnets that should be routed rather than NATed (when NAT is enabled).
vpn.client.routing6.vpn_supernet : list of subnets
Supernets that partially or fully encompass VPN subnets (not generally used).
vpn.server.group_pool6 : list of subnets
Optional pool of VPN IPv6 addresses to be subdivided across groups that don't define group_subnets6 or group_range6.
vpn.server.routing6.snat_source : list of SNAT spec strings

How should the AS NAT outgoing packets? A range can be given for each outgoing interface. Sample SNAT spec string:

2605:6400:2:fed5::1-2605:6400:2:fed5::ffff
vpn.server.custom_snat6_chain : string
Define a custom ip6tables chain to handle all outgoing NAT.