Your VPN with IPv6 support based on Wireguard

Sometimes it becomes necessary to access sites, for example, https://refactoring.guru or https://leafletjs.com, but for some reason these sites are blocked in your country. A VPN might be the solution. However, buying a VPN somewhere on the side with your own VPS server, where the Internet works fine, is just a waste of money. In this case, the question arises: how, in fact, to organize this same VPN? There are many instructions on the Internet, but they usually do not touch on the topic of the IPv6 protocol, or they do, but controversial decisions are used there.

One of the popular VPN options is Wireguard. By itself, Wireguard is quite simple, but at the same time it can be used in any scheme: point-to-point, star, and even a mesh network. In the future, the “star” scheme will be used, which implies the use of a separate server and the presence of at least one or more clients.

If everything is clear with IPv4, since most guides converge to a solution using grayscale addressing with NAT organization on the server. In fact, this is the standard scheme for IPv4 addressing. IPv4 addresses are scarce and expensive, so no one in their right mind would use whitelisted addresses directly on devices, unless, of course, it’s a server that’s available on the internet. But with IPv6, not everything is so simple.

The IPv6 protocol itself is based on the fact that no one will need to use NAT. However, this does not mean that NAT itself in IPv6 is not available. NAT for IPv6 is available (commonly referred to as NAT66), but its use is not recommended, and in some cases it is even harmful. In addition, there is always the opportunity not to use it, as opposed to IPv4.

Hosting providers can issue IPv6 addresses in different ways:

1. Issuance of IPv6 addresses individually. The strangest choice. If this is the case with your hosting provider, then most likely you should just change it to another one, even in the context of using a VPS for a regular server, not to mention using it as a VPN. With some degree of probability, you can also get a VPN with IPv6, but this option is simply not considered further. After reading the material, you yourself will be able to understand what you need to do if you still decide to use such a provider.

2. Issuing a net /64. The most common option for small providers. Sometimes it is possible to get a /63 or even larger network through support, which will be discussed in the next option. Having only /64 is not the best option for a VPN, but you can already work with it.

3. The option is not very different from the previous one, but instead of a /64 network, you are given a larger network (up to /48), i.e. you have a number of /64 networks at your disposal. For example, with / 48 – 65536 pieces.

4. Routing a specific IPv6 prefix to your virtual machine. The rarest option among small providers, this almost never occurs in public access, but it is possible to get a prefix through technical support. This option assumes that your hosting provider has registered a route to your virtual server for the prefix allocated to you. You may be given a network from /64 to /48, which you can use without crutches to organize a VPN.

The difficulty of setting up a VPN gradually decreases from 1 to 4 options, so let’s start with 4 options and gradually climb up.

Step 1: Enable Routing on the VPN Server

The easiest to set up is when your ISP has assigned a route for the /64 network or networks to your virtual machine. In such a case, the only thing you will need to do to make the VPN work is enable routing on your machine.

For IPv4, routing is enabled using sysctl by setting

net.ipv4.ip_forward=1

For IPv6, this is done in the same way:

net.ipv6.conf.all.forwarding = 1

But there is one BUT! If your machine receives addresses in automatic mode, then after enabling routing, it will no longer accept router announcements, which means it will no longer be able to obtain an address in automatic mode. To fix this, enable

net.ipv6.conf.ens3.accept_ra = 2

In this example, `ens3` is the network interface of our VPS where we want to receive router announcements from. On most hostings, the assignment of IPv6 addresses to VPS was done by manual configuration, which means that it is not required to accept RA, i.e. this setting can be skipped.

Now it remains to select the /64 network from the range available to you, assign one of the addresses to the Wireguard interface on the VPS, and also issue each client with an IPv6 address from the same range. Everything is written in the configuration of the server and clients. This completes the VPN setup for option 4.

Step 2: Provide packet routing for the server without a dedicated prefix

Now let’s move on to the option when we are allocated, at best, from / 63 to / 48, at worst / 64. Let’s look at the best option first.

The first thing to check is that your server’s network interface is set to a standard size /64 network. In this case, the received packet from the range that goes beyond its limits will be transmitted in accordance with the routing table.

IPv6 has a neighbor discovery feature. This means that if the host wants to contact someone, it first of all sends a request to find a neighbor with the given addresses. If a response is received, the host can forward the data directly, bypassing the router. If the destination host is unreachable, then the host will use the routing table and forward the packet to the appropriate router. For IPv4, this situation is a bit unusual. And in IPv6, packets between different address ranges can go directly between hosts, and also, there are situations when even hosts on the same network will communicate through a router.

Since we have assigned a /64 network for our server, when the provider’s router tries to find a neighbor with an address that does not fall into this subnet, our host will ignore these requests. To prevent this from happening, you can use a special NDP proxy service. This service can forward requests to find neighbors and return responses and respond to specified requests with a positive response. Unfortunately, Wireguard operates at a higher network layer, so the only option for us is to simply give positive responses when asked for addresses that are used in the VPN.

One of the options for solving the problem is to install the ndppd package. The package is definitely available in the standard Ubuntu and Fedora distributions in the official repositories. Install it with your package manager. The ndppd configuration is quite simple. The service configuration file is located at /etc/ndppd.conf. The content of this file should be something like this:

proxy ens3 {
rule 2001:0db8:827:fcde:cafb:073d:a65e:25b0 {
static
}
}

This configuration means that if a request comes to the ens3 interface with a request for a neighbor at 2001:0db8:827:fcde:cafb:073d:a65e:25b0, then you must answer that this is our address. Entries rule you can repeat it several times and even specify in each entry not a separate address, but a whole range. However, ndppd itself does not welcome a wide netmask. If there are few VPN clients, it is better to create an entry for each of them.

Step 2.1: What if we only have a /64 network

This is the most unfavorable option, but we will still be able to ensure the operation of our VPN. In general, the very idea of ​​dividing the /64 range into smaller networks is, to put it mildly, not welcome. But since we have no other choice, we will have to do it.

Since we use VPS, we are unlikely to use the SLAAC mechanism, which only works with /64 networks. In addition, in most cases, addressing for VPS is written manually, simply because the server must have a strictly defined address. Based on this, it is possible to divide the /64 network into smaller networks. How to share? If you do not plan to run other VPN services on the server, then /65 networks are the best option, i.e. network / 64 we divide in half. In this case, for VPN clients, almost all bits from the /64 range are available to us, except for the highest bit. With this division, our address will look like a regular address, which, for example, could be allocated through SLAAC.

If, in addition to Wireguard, you want to, for example, also run OpenVPN on your server, then you may need another network for this service. In this case, you can choose the /66 network. Of course, in this case, you no longer need to take into account one high-order bit, but two. You can continue to narrow networks, but your client addresses will no longer be as similar to the addresses that are usually allocated using the SLAAC mechanism. Variants other than /65 you can organize yourself.

In order for your server to route the packets that will need to be sent to the VPN client, you need to truncate the network in the network interface settings. Instead of /64, specify the selected mask, for example, /65. After that, the configuration of your VPN server does not differ from the settings that we did in step 2. Of course, the /65 mask must also be specified in the Wireguard settings on your server.

Practical part

In order not to go into details, we will assume that you have read my “Cheat Sheet for Wireguard” or any other instructions, which are very numerous on the Internet, and you do not need to explain how to generate keys.

We enable routing on the VPS by setting parameters, for example, by adding the file /etc/sysctl.d/20-vpn.conf and loading them through sysctl -p or by rebooting the VPS:

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding = 1

Generate a key pair for your VPN server like this

wg genkey | tee private.key | wg pubkey > public.key

For added security, a PSK key can be generated for each client, but this is not required:

wg genpsk > psk.key

Generate keys for all your clients in the same way. After that, you can create a server configuration for Wireguard.

[Interface]
Address = 192.168.0.1/24, 2001:0db8:827:fcde::1/64
PrivateKey = <SERVER_PRIVATE_KEY>
ListenPort = <SERVER_PORT>

[Peer]
PublicKey =
AllowedIPs = 192.168.0.2, 2001:0db8:827:fcde::1ce:1ce:babe
PresharedKey =

It’s not hard to guess that <SERVER_PRIVATE_KEY> is the private key of the server, and <CLIENT_PUBLIC_KEY> is the client’s public key. 192.168.0.0/24 is the IPv4 network for our connection, and the address 192.168.0.1 will be assigned to the Wireguard interface. Similarly, 2001:0db8:827:fcde::/64respectively, the IPv6 network, and the address 2001:0db8:827:fcde::1 – address of the Wireguard interface. Option PresharedKey optional, but if it is specified on the server, then it must also be specified in the client configuration, the value of the keys on the server and client must match.

Section [Peer] must be created for each client. IN AllowedIPs the IP addresses and networks that we expect from the client must be specified.

Client configuration should look like

[Interface]
Address = 192.168.0.2, 2001:0db8:827:fcde:beef:1ce:1ce:babe
PrivateKey = <CLIENT_PRIVATE_KEY>

[Peer]
PublicKey =
AllowedIPs = 192.168.0.0/24, 2000::/3
Endpoint = :
PresharedKey =
PersistentKeepalive = 20

Similarly, on the client: <CLIENT_PRIVATE_KEY> – private key of the client, <SERVER_PUBLIC_KEY> – public key of the server. IN Endpoint address must be provided <SERVER_NAME> and port <SERVER_PORT> servers that match the specified parameters in the server settings. Parameter PresharedKey must be present if it is in the section [Peer] for this client, the contents of the key must match.

PersistentKeepalive may also be missing. But if specified, then the client will send a data packet every specified number of seconds. This is useful in cases where the client is behind a NAT or Firewall, which, if there is no activity, can prevent the remote host from sending you responses.

To provide clients with Internet access via IPv4 protocol, you need to enable NAT, for example, using scripts that need to be added to the `[Interface]` on the server, and disable them if clients go down.

PostUp = iptables -A FORWARD -i %i -j ACCEPT -w 10; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE -w 10
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE

Automation

Of course, doing all the necessary settings by hand, especially if a new client of your VPN does not appear often, is just a real punishment. So I thought about automation. The script was found as a base nebulakl/wireguard-config-generator. It did not quite fit my needs, so I redid it and put it in fsa/wireguard-config-generator.

The script allows you to generate a configuration for a VPN server based on Wireguard. Next, you can generate the required number of client configurations. The script retained the ability to use NAT66, as it was in the original script, but NAT66 is enabled explicitly by editing the server configuration. By default, the script uses “gray” addressing, as in the original script.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *