Giving yourself IPv6 with WireGuard
Tunnelling IPv6 traffic through a WireGuard server when the local ISP does not support IPv6
After many years of asking, my Internet Service Provider still doesn't support IPv6. The same goes for many other ISPs. IPv4 exhaustion has pushed some ISPs toward "Carrier-Grade NAT", where many customers share one address. Dedicated IPv4 addresses are also getting more expensive for small websites, and cloud providers have started charging for them. The obvious solution is for ISPs to support IPv6, but that takes work and many customers do not know there is a problem. Keeping the status quo is easier.
I work around this by renting a server in a datacentre with an IPv6 address and tunnelling my traffic through it with WireGuard. This is moderately involved and costs money, but it also gives websites another source of IPv6 traffic. Perhaps that will help show that IPv6 is worth implementing.
You can do this with any server that has an IPv6 address. I'll use one from OVH because it does not charge for bandwidth and has a datacentre near me, which limits the latency added by the tunnel. DigitalOcean, Vultr, Linode, and other providers could also work, but check their bandwidth costs.
I installed WireGuard on my laptop and server. On Debian or Ubuntu, run apt install wireguard on both machines.
Next, I created a public and private key on both machines with the WireGuard tools:
mkdir ~/.wg
cd ~/.wg
wg genkey | tee privatekey | wg pubkey > publickey
This creates a private key and public key in the ~/.wg directory. Next, configure the tunnel on the client and server.
# server config
# /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24 # Private IPv4 subnet for the VPN
Address = fd42:42:42::1/64 # Private IPv6 subnet for the VPN
PrivateKey = <private_key_from_server>
ListenPort = 51820
[Peer] # your laptop
PublicKey = <public_key_from_laptop>
AllowedIPs = 10.0.0.2/32, fd42:42:42::2/128
# ... you can add many other peers to this file, just make sure to increment their allowed IPs
# client config
# /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <private_key_from_laptop>
Address = 10.0.0.2/24, fd42:42:42::2/64 # addresses that matches "AllowedIPs" from server config
DNS = 1.1.1.1, 2606:4700:4700::1111 # your choice of DNS server, these are cloudflare's but you could choose your own
[Peer]
PublicKey = <public_key_from_server>
AllowedIPs = 0.0.0.0/0, ::/0 # this says to send all traffic over the tunnel
Endpoint = <server_public_ip>:51820
Now, make sure the server can route IPv6 traffic. This requires iptables rules and system settings.
# as root run the following commands
# the next three commands will let your system packet forward for IPv4 and IPv6
echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.conf
sysctl -p # this will immediately apply the configuration additions
# now we need to let iptables to route the traffic appropriately
# on my machine, my network interface is eno1, but it may be eth0 for you or something else, you can find this using: ip addr
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A FORWARD -o wg0 -j ACCEPT
iptables -t nat -A POSTROUTING -o <YOUR_NETWORK_INTERFACE> -j MASQUERADE
ip6tables -A FORWARD -i wg0 -j ACCEPT
ip6tables -A FORWARD -o wg0 -j ACCEPT
ip6tables -t nat -A POSTROUTING -o <YOUR_NETWORK_INTERFACE> -j MASQUERADE
# ensure that your server has the wireguard ports open
iptables -A INPUT -p udp --dport 51820 -j ACCEPT
ip6tables -A INPUT -p udp --dport 51820 -j ACCEPT
# don't allow outside traffic to connect back to your machine that you didn't initiate
# this is to prevent your machine becoming world accessible
# if you plan on running a public service, such as a webserver on your laptop, you may need
# to adjust these
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -j DROP
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -j DROP
Warning: The INPUT DROP rules above will drop all traffic that is not already established or explicitly allowed. If you are connected to this server over SSH, make sure you add a rule to allow SSH traffic before adding the DROP rules (e.g.
iptables -A INPUT -p tcp --dport 22 -j ACCEPTand the equivalent ip6tables rule). Otherwise, you will lock yourself out.
Note: These iptables rules are not persistent across reboots. To make them survive a reboot, you can either use the
iptables-persistentpackage (apt install iptables-persistentand thennetfilter-persistent save), or use WireGuard'sPostUpandPostDowndirectives inwg0.confto apply and remove the rules when the tunnel starts and stops.
Both machines are now ready. Run wg-quick up wg0 on the server and then on the laptop. Run wg show on both machines to check the tunnel.
Editor's Note: Tailscale exit nodes are another way to route the traffic without managing the WireGuard configuration directly.