Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
DigitalOcean, assign public ipv6 to wireguard clients
# /etc/sysctl.d/wireguard.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.eth0.proxy_ndp=1
#/etc/wireguard/wg0.conf (DO virtual machine)
[Interface]
# The server interface does not actually need an ipv6.
# The 2 following must be repeated for each used addres [0, 1]
PostUp=ip -6 neigh add proxy 2a03:b0c0:2:f0::2c:2002 dev eth0
PostDown=ip -6 neigh del proxy 2a03:b0c0:2:f0::2c:2002 dev eth0
[Peer]
# This must be one of the ips assigned by DO,
# usually they assign a /124 thus only
# the last 4 bits can vary for a total of 16 addresses.
# Example for a vm with ip -> 2a03:b0c0:2:f0::2c:2001
AllowedIps = 10.200.200.2/32, 2a03:b0c0:2:f0::2c:2002/128
#/etc/wireguard/wg0.conf (client)
[Interface]
Address = 10.200.200.2/32, 2a03:b0c0:2:f0::2c:2002/64
[Peer]
# ...
AllowedIPs = 0.0.0.0/0, ::/0
# Refs and Resources
[0] https://www.linuxquestions.org/questions/linux-networking-3/how-do-i-enable-proxy-ndp-proxy-arp-works-933174/
[1] https://manpages.debian.org/unstable/wireguard-tools/wg-quick.8.en.html
[*] https://www.reddit.com/r/WireGuard/comments/egik62/give_hosts_in_a_wg_interface_a_public_ipv6_address
@daryll-swer
Copy link

daryll-swer commented Apr 18, 2021

Is there a way to assign a public IPv6 address to the wg0 interface itself, in order to allow remote clients to directly connect via the endpoint through their own IPv6 address (if their ISP gives them IPv6) instead of IPv4 (which results in 6to4 transition)?

I have tried giving the wg0 interface a public IPv6 out of the /124 like
[Interface] Address = 10.7.0.1/24, 2400:6180:100:d0::8e0:100f/64
Now when I ping the 100f from the outside world, it is reachable. But at the same time when I my clients connect via IPv4, IPv6 no longer works (6to4 as in your text doc), it works again when I remove the IPv6 from the server interface.

Even if we could make it work, is there a way for the remote client to actually connect to the wg0 interface via IPv6? Since even if we use a domain name, it would ideally be set to eth0's IPv6 address (hosting etc), so many some dst nat/port forwarding to redirect traffic hitting eth0 IPv6 based on the port?

Also had to clamp TCP MSS as IPv6 sites/services like Netflix wouldn't work without it, my guess is because wg0 interface has 1420mtu while eth0 has 1500 mtu and that created some conflict as any outgoing IPv6 packet from wg0 interface will get a reply back from the remote host with 1500 mtu as it comes in from eth0. Is there a way to solve this without clamping? As UDP packets would still be affected regardless.
ip6tables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o eth0 -j TCPMSS --clamp-mss-to-pmtu

@MartinBrugnara
Copy link
Author

MartinBrugnara commented Apr 18, 2021

Hi @daryll-swer,
the setup proposed here was designed to provide public ipv6 addresses (from a DO pool) to ipv4 clients.
That said, I will try to answer but I cannot test, as I do not have ipv6 native "clients" at hand.

Is there a way to assign a public IPv6 address to the wg0 interface itself, in order to allow remote clients to directly connect via the endpoint through their own IPv6 address (if their ISP gives them IPv6) instead of IPv4 (which results in 6to4 transition)?

Are you asking if your vpn gateway can have its own ipv6, and native ipv6 clients can connect directly with it? yes.
You do not have to modify wg0 to achieve that. You must assign such ipv6 to the interface that is actually connected to internet (e.g. eth0), and then use that ip in the "client" config or use a DNS record.

  • For the first solution, use the ipv6 of the gateway (dose not have to be in the same pool as they one you are "roouting") in the clients [Peer] /Endpoint configuration parameter.
  • For the second solution, set the domain name (e.g. vpn.example.org) in the clients [Peer] /Endpoint . Then add both ipv4 and ipv6 to the domain address, respectively to the A record and to the AAA record.

I suggest the latter.

I have tried giving the wg0 interface a public IPv6 out of the /124 like ...

This is likely because now both your eth0 and your wg0 have that same address .
Since you are routing the whole /124 via eth0, the wireguard clients will be able to connect to the vpn machine even if the ip is only added to the eth0 interface.
If instead you are routing a different subnet (which from what you are asking doesn't seem to be the case) you can try to add one ip from that pool with /128 to the server wg0 address field.

Even if we could make it work, is there a way for the remote client to actually connect to the wg0 interface via IPv6? Since even if we use a domain name, it would ideally be set to eth0's IPv6 address (hosting etc), so many some dst nat/port forwarding to redirect traffic hitting eth0 IPv6 based on the port?

I am not sure what you are asking here... I will give a pair of hints, than feel free to replay if it's not enough.

  • Since we are assigning public ipv6 addresses to these "clients", they will be reachable from any other machine to their pub ipv6 address.
    The traffic will be routed and not natted. (Bonus: you can still filter the traffic by setting up a firewall on the vpn host).
  • If what you want is exposing a service on an ipv6 address (on the vpn host) and then proxy the request to one of the wireguard clients you can setup an easier solution. For example, have the clients only work on ipv4 (and not public ipv6), then have a proxy that redirects the calls based on port/protocol, and domain (even if you are usign TLS via SNI). Have a look at solutions like haproxy.

Also had to clamp TCP MSS as IPv6 sites/services like Netflix wouldn't work without it, my guess is because wg0 interface has 1420mtu while eth0 has 1500 mtu and that created some conflict as any outgoing IPv6 packet from wg0 interface will get a reply back from the remote host with 1500 mtu as it comes in from eth0. Is there a way to solve this without clamping? As UDP packets would still be affected regardless.
ip6tables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o eth0 -j TCPMSS --clamp-mss-to-pmtu .

Unfortunately, I believe, Netflix has mapped all DO ips as "vpn" services, so you cannot use them to stream.
Nevertheless Path MTU Discovery (PMTUD) should still work; that said, accordingly to random posts, it seams like many devices on the network break it (something to do with "All ICMPs packets are bad" - lol). Thus it may be necessary to force it like you did.
Maybe @CristianCantoro , or someone else can help with this; I would be interested too.

@daryll-swer
Copy link

daryll-swer commented Apr 18, 2021

@MartinBrugnara

You must assign such ipv6 to the interface that is actually connected to internet (e.g. eth0)

That's already done right from the VM creation instance by DO in this case.

For the first solution, use the ipv6 of the gateway (dose not have to be in the same pool as they one you are "roouting") in the clients [Peer] /Endpoint configuration parameter.

WireGuard Client App/Config syntax does not accept IPv6 addresses as a valid syntax.

For the second solution, set the domain name (e.g. vpn.example.org) in the clients [Peer] /Endpoint . Then add both ipv4 and ipv6 to the domain address, respectively to the A record and to the AAA record.

As discussed here, the WireGuard client never resolves the AAAA record.

This is likely because now both your eth0 and your wg0 have that same address.

That's not the case. eth0 has its own static IPv6 address, wg0 has its own unique IPv6 address. For some reason, IPv6 dies completely on WireGuard clients the moment I assigned the public IPv6 address to the wg0 interface.

I am not sure what you are asking here... I will give a pair of hints, than feel free to replay if it's not enough.

On this part, basically, I want a true IPv6 to IPv6 tunnel. The reason being I want to eliminate 6to4 tunnelling which is the current setup on WireGuard by default. So Client A has IPv6 native, connects to Server A via their IPv6 native, no IPv4 tunnel is ever created. Which goes back to the AAAA resolving problem and the Reddit thread mentioned there along with the wg0 interface not working with public IPv6 assigned to it.

Unfortunately, I believe, Netflix has mapped all DO ips as "vpn" services, so you cannot use them to stream.

That's not true. I actively use DO IPs and use Netflix through DO. At least it works in my country.

Nevertheless Path MTU Discovery (PMTUD) should still work; that said, accordingly to random posts, it seams like many devices on the network break it (something to do with "All ICMPs packets are bad" - lol). Thus it may be necessary to force it like you did.
Maybe @CristianCantoro , or someone else can help with this; I would be interested too.

Found a solution, first, wg0 interface should default to 1420 MTU which is the proper WireGuard MTU as per the creator. Next on the client .conf file, manually specific MTU=1420. Leaving it blank/auto will never work as there's no mechanism to negotiate MTU over TCP/UDP, this is something that usually works only between layer 2.5-layer 2 protocols as far as I know. That's it, no more MTU problems with WireGuard. Assuming your WAN interface has MTU= 1492 (typical PPPoE without RFC4638) or greater or the standard 1500.

@MartinBrugnara
Copy link
Author

MartinBrugnara commented Apr 18, 2021

You must assign such ipv6 to the interface that is actually connected to internet (e.g. eth0)

That's already done right from the VM creation instance by DO in this case.

Indeed

For the first solution, use the ipv6 of the gateway (dose not have to be in the same pool as they one you are "roouting") in the clients [Peer] /Endpoint configuration parameter.

WireGuard Client App/Config syntax does not accept IPv6 addresses as a valid syntax.

Doesn't make any sense... Never tested though, cannot confirm.

For the second solution, set the domain name (e.g. vpn.example.org) in the clients [Peer] /Endpoint . Then add both ipv4 and ipv6 to the domain address, respectively to the A record and to the AAA record.

As discussed here, the WireGuard client never resolves the AAAA record.

This statement does not seams to be correct. Please read the comments and additional resources, one of the first on gsearch https://pmcc.net/posts/automated-wireguard-endpoint-updates-reachability-checks .

This is likely because now both your eth0 and your wg0 have that same address.

That's not the case. eth0 has its own static IPv6 address, wg0 has its own unique IPv6 address. For some reason, IPv6 dies completely on WireGuard clients the moment I assigned the public IPv6 address to the wg0 interface.

Ok, you said you were assigning /64 . You sure that's the correct mask?
I cannot help further here, but I can suggest you to check the resulting routing table.

I am not sure what you are asking here... I will give a pair of hints, than feel free to replay if it's not enough.

On this part, basically, I want a true IPv6 to IPv6 tunnel. The reason being I want to eliminate 6to4 tunnelling which is the current setup on WireGuard by default. So Client A has IPv6 native, connects to Server A via their IPv6 native, no IPv4 tunnel is ever created. Which goes back to the AAAA resolving problem and the Reddit thread mentioned there along with the wg0 interface not working with public IPv6 assigned to it.

Just removing ipv4 should do it, make sure route discorivery protocol are working .

Unfortunately, I believe, Netflix has mapped all DO ips as "vpn" services, so you cannot use them to stream.

That's not true. I actively use DO IPs and use Netflix through DO. At least it works in my country.

That's nice to know ;)
May I ask on which DO region are exiting? I was talking about AMS.

Nevertheless Path MTU Discovery (PMTUD) should still work; that said, accordingly to random posts, it seams like many devices on the network break it (something to do with "All ICMPs packets are bad" - lol). Thus it may be necessary to force it like you did.
Maybe @CristianCantoro , or someone else can help with this; I would be interested too.

Found a solution, first, wg0 interface should default to 1420 MTU which is the proper WireGuard MTU as per the creator. Next on the client .conf file, manually specific MTU=1420. Leaving it blank/auto will never work as there's no mechanism to negotiate MTU over TCP/UDP, this is something that usually works only between layer 2.5-layer 2 protocols as far as I know. That's it, no more MTU problems with WireGuard. Assuming your WAN interface has MTU= 1492 (typical PPPoE without RFC4638) or greater or the standard 1500.

Thanks for sharing.

@daryll-swer
Copy link

daryll-swer commented Apr 18, 2021

Doesn't make any sense... Never tested though, cannot confirm.

Figured it out from the iOS app. The syntax for static IPv6 is [ipv6]:port. Solved.

This statement does not seams to be correct. Please read the comments and additional resources, one of the first on gsearch https://pmcc.net/posts/automated-wireguard-endpoint-updates-reachability-checks .

Yeah I've read it before. You can test it yourself on a client with native IPv6 if you get the chance. The client app will refuse to resolve AAAA records. Solution? I used static IPv6 address.

Ok, you said you were assigning /64 . You sure that's the correct mask?
I cannot help further here, but I can suggest you to check the resulting routing table.

Mask? You mean prefix size? Yes, /64 is the correct prefix size. Anyway I solved the IPv6 issue.

  1. Give wg0 interface a /64 ULA in the wg0.conf file along with a /[whatever] for the classic IPv4 NAT/subnet
  2. Do what your original document has suggested with NDP proxying/giving static IPs to clients manually (we need an automated solution for this really)
  3. Use destination NAT to map any incoming traffic to host on Public IPv6:[port] to wg0 IPv6:port like
    ip6tables -A PREROUTING -d 2400:6280:100:d0::7e0:4001 -p udp --dport 51820 -j DNAT --to-destination [fddd:2c4:2c4:2c4::1]:51820
  4. Now client that has the static IPv6 end-point configured can connect via IPv6 if they have IPv6 connectivity. And benefit is you will get 4to6 functionality so it's all neatly dual-stacked without any bugs (with my MTU solution above).
    The only issue is Xbox's Networking/Teredo implementation refuses to work with NATted IPv4 (no port forwarding/it's like a CGNAT) and does not take advantage of IPv6.

That's nice to know ;)
May I ask on which DO region are exiting? I was talking about AMS.

DO, Bangalore, India

@MartinBrugnara
Copy link
Author

MartinBrugnara commented Apr 18, 2021

Thanks for sharing what you found =)

@luciaDary46
Copy link

luciaDary46 commented Dec 9, 2021

Just use the auto-install script wireguard created by @Nyr , make sure your virtual server has ipv6 configured... that solves the problem.

@daryll-swer
Copy link

daryll-swer commented Dec 9, 2021

@luciaDary46 all that does is NAT66 IPv6. It does not configure NDP-Proxying nor ensure each client gets a proper IPv6 address instead of NAT66.

@Nyr
Copy link

Nyr commented Dec 9, 2021

@daryll-swer it is not possible to automate provision a "proper" IPv6 address for each client when almost all of the cloud and dedi providers do not provide a routed IPv6 subnet, and most IPv6 implementations are broken somehow. That is why I do NAT for IPv6 (which was already the case for IPv4 anyway).

@daryll-swer
Copy link

daryll-swer commented Dec 9, 2021

(which was already the case for IPv4 anyway).

Agreed. But I don't see why you are promoting NAT for IPv6! @Nyr

Anyways, you can automate it via your scripting with dynamic variables, ask the user to input the non routed subnet/prefix range available and you can automatically inject those for NDP Proxy and mapping of each client in a serial/chronological order. That's basically what I do manually on DigitalOcean with their broken /124.

@Nyr
Copy link

Nyr commented Dec 9, 2021

@daryll-swer I am not promoting anything, just doing what I can to provide working IPv6 connectivity.

There are a lot of providers giving a single /128 address per server, your proposal would not work in many places and is less user-friendly. There are also many providers which require to route each /128 manually from their control panel, this is actually how SolusVM works (SolusVM is the industry standard for VPS providers).

@daryll-swer
Copy link

daryll-swer commented Dec 9, 2021

Oh boy, I would strongly recommend avoiding such crappy providers! Defeats the purpose of IPv6!

Not ALL cloud providers are bad with IPv6, this an example that provides routed /64s to the customer's host: https://twitter.com/ungleich

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment