Skip to content

Instantly share code, notes, and snippets.

@mikaeldui
Last active August 16, 2025 10:09
Show Gist options
  • Save mikaeldui/12127c91ccece42ea375c9f42d94aa8a to your computer and use it in GitHub Desktop.
Save mikaeldui/12127c91ccece42ea375c9f42d94aa8a to your computer and use it in GitHub Desktop.
Proton VPN IPv6 Manual Setup

Proton VPN IPv6 Manual Setup

Over 80% of the servers support IPv6 but only the Linux & Android apps and the browser extension support it at the moment.

The Linux app supports IPv6 over the VPN but still connects to the VPN server using IPv4.

It's possible to make changes to the WireGuard configs that you can get from https://account.protonvpn.com/downloads to enable IPv6.

An easy way to test if a server supports IPv6 is to use the browser extension and then go to myip.wtf or test-ipv6.com, or you could check the list at https://mikaeldui.github.io/proton-vpn-server-list/.

Original .conf

Here's an example of a WireGuard profile I got for CH#600:

[Interface]
# Key for Reddit Test Config 2025-01-05
# Bouncing = 2
# NetShield = 1
# Moderate NAT = on
# NAT-PMP (Port Forwarding) = on
# VPN Accelerator = on
PrivateKey = *redacted*
Address = 10.2.0.2/32
DNS = 10.2.0.1

[Peer]
# CH#600
PublicKey = Ii6hAbnu84wZ8NzVt5+ylO4FnX+ANrKNzpFOSYq9dks=
Endpoint = 79.127.184.216:51820

# For Windows
AllowedIPs = 0.0.0.0/1, 128.0.0.0/1

# For Linux, Android, routers, etc.
AllowedIPs = 0.0.0.0/0 

IPv6 over VPN (Change Address and AllowedIPs)

I'll now make some changes to Address, DNS and AllowedIPs to enable IPv6 over VPN.

Note: 2a07:b944::2:2/128 and 2a07:b944::2:1 are the same for all servers, it's not specific to CH#600.

[Interface]
# Key for Reddit Test Config 2025-01-05
# Bouncing = 2
# NetShield = 1
# Moderate NAT = on
# NAT-PMP (Port Forwarding) = on
# VPN Accelerator = on
PrivateKey = *redacted*
Address = 10.2.0.2/32, 2a07:b944::2:2/128
DNS = 10.2.0.1, 2a07:b944::2:1

[Peer]
# CH#600
PublicKey = Ii6hAbnu84wZ8NzVt5+ylO4FnX+ANrKNzpFOSYq9dks=
Endpoint = 79.127.184.216:51820

# For Windows
AllowedIPs = 0.0.0.0/1, 128.0.0.0/1, ::/1, 8000::/1

# For Linux, Android, routers, etc.
AllowedIPs = 0.0.0.0/0, ::/0

Add dual stack to the VPN server (Change Endpoint)

If your ISP supports IPv6 then you can enable IPv6 connectivity to the VPN server, and to do that we need to look up the node's domain at https://api.protonmail.ch/vpn/logicals https://mikaeldui.github.io/proton-vpn-server-list/. For CH#600 the domain is node-ch-31.protonvpn.net. This can be used as the Endpoint to enable automatic switching between IPv4 and IPv6, useful on a phone or laptop using hotspots without IPv6.

[Interface]
# Key for Reddit Test Config 2025-01-05
# Bouncing = 2
# NetShield = 1
# Moderate NAT = on
# NAT-PMP (Port Forwarding) = on
# VPN Accelerator = on
PrivateKey = *redacted*
Address = 10.2.0.2/32, 2a07:b944::2:2/128
DNS = 10.2.0.1, 2a07:b944::2:1

[Peer]
# CH#600
PublicKey = Ii6hAbnu84wZ8NzVt5+ylO4FnX+ANrKNzpFOSYq9dks=
Endpoint = node-ch-31.protonvpn.net:51820

# For Windows
AllowedIPs = 0.0.0.0/1, 128.0.0.0/1, ::/1, 8000::/1

# For Linux, Android, routers, etc.
AllowedIPs = 0.0.0.0/0, ::/0

Or IPv6 only to the VPN Server (Change Endpoint)

Or, you can look up its IPv6 address (in the AAAA record) and force connections to the VPN over IPv6 like this:

You can also find IPv6 addresses for the nodes at https://mikaeldui.github.io/proton-vpn-server-list/.

[Interface]
# Key for Reddit Test Config 2025-01-05
# Bouncing = 2
# NetShield = 1
# Moderate NAT = on
# NAT-PMP (Port Forwarding) = on
# VPN Accelerator = on
PrivateKey = *redacted*
Address = 10.2.0.2/32, 2a07:b944::2:2/128
DNS = 10.2.0.1, 2a07:b944::2:1

[Peer]
# CH#600
PublicKey = Ii6hAbnu84wZ8NzVt5+ylO4FnX+ANrKNzpFOSYq9dks=
Endpoint = [2a02:6ea0:d411:5432::10]:51820

# For Windows
AllowedIPs = 0.0.0.0/1, 128.0.0.0/1, ::/1, 8000::/1

# For Linux, Android, routers, etc.
AllowedIPs = 0.0.0.0/0, ::/0

Put this conf in any WireGuard app and enjoy your fully IPv6 enabled VPN!

@GongYiLiao
Copy link

not sure if this is applicable, 2a07:b944::2:2/128 is not a ULA address, and in Proton's Call for test 3 years ago the wireguard conf interface ipv6 address is an ULA one. Maybe I misunderstood something?

@mikaeldui
Copy link
Author

mikaeldui commented Jul 18, 2025

not sure if this is applicable, 2a07:b944::2:2/128 is not a ULA address, and in Proton's Call for test 3 years ago the wireguard conf interface ipv6 address is an ULA one. Maybe I misunderstood something?

@GongYiLiao it's the hard-coded address used in the Linux client for all servers with the IPv6 feature flag. I can't tell you how many days/hours I spent figuring this out, starting with 0 knowledge about WireGuard and privacy VPNs.

@GongYiLiao
Copy link

Thank you so much for extracting such an important from the code, I test if on opnsense and it indeed works!

@yllwfsh
Copy link

yllwfsh commented Jul 19, 2025

@GongYiLiao @mikaeldui I can only suspect that Proton used a Global address here instead of a ULA because most operating systems and browsers would still prefer ipv4 over the ULA ipv6 address when browsing the internet, therefore reducing the effectiveness of the ipv6 implementation.

@meehien
Copy link

meehien commented Jul 20, 2025

thanks for reverse engineering this. do you have any idea how to adapt this for systemd-networkd?
I have tried the following but it doesn't seem to be working for ipv6 (but works for ipv4):

50-wgpr.network

[Match]
Name=wgpr

[Network]
IPv4Forwarding=true

[Address]
Address=10.2.0.2/32
Peer=10.2.0.1/32

[Address]
Address=2a07:b944::2:2/128
Peer=2a07:b944::2:1

50-wgpr.netdev

[NetDev]
Name = wgpr
Kind = wireguard
Description = WireGuard tunnel wgpr

[WireGuard]
# UK-508
PrivateKey = *******************

[WireGuardPeer]
# UK-508
PublicKey = MKqrC+ee7VJKIe565rrTJjPT31Dvd5m+s6yoIQ97YyU=
Endpoint = 79.127.146.101:51820

AllowedIPs = 0.0.0.0/0
AllowedIPs = ::/0
PersistentKeepalive = 25

@mikaeldui
Copy link
Author

@meehien I tried but I'm stuck at "carrier", can't get it to "routable".

image

@FelixPehla
Copy link

thanks for reverse engineering this. do you have any idea how to adapt this for systemd-networkd? I have tried the following but it doesn't seem to be working for ipv6 (but works for ipv4):

It works for me with these configs. Though I also add some routing policies to route traffic through wireguard by default; you'll need to change that if you don't want it.

wg0.netdev:

[NetDev]
Name=wg0
Kind=wireguard

[WireGuard]
PrivateKey=<snip>
RouteTable=1000

[WireGuardPeer]
# DE#447 / node-de-17.protonvpn.net
PublicKey=9+CorlxrTsQR7qjIOVKsEkk8Z7UUS5WT3R1ccF7a0ic=
AllowedIPs=0.0.0.0/0, ::/0
Endpoint=194.126.177.14:51820

wg0.network:

[Match]
Name=wg0

[Network]
Address=10.2.0.2/32
Address=2a07:b944::2:2/128
DNS=10.2.0.1
DNS=2a07:b944::2:1
DNSDefaultRoute=true
Domains=~.

# route all traffic through the vpn
[RoutingPolicyRule]
Table=1000
Family=both
Priority=10

# ...except for traffic to the wireguard endpoint
[RoutingPolicyRule]
To=194.126.177.14/32
Priority=5

# ...and internal traffic
[RoutingPolicyRule]
To=10.0.0.0/16
Priority=6

[RoutingPolicyRule]
To=fe80::1/10
Priority=6

Oh and thanks for the writeup!

@joshcombs
Copy link

Thank you so much for extracting such an important from the code, I test if on opnsense and it indeed works!

I currently have Wireguard working with ProtonVPN in OPNsense as well as IPv6 from my ISP. Would you mind sharing what additional steps you took to achieve IPv6 tunneling through ProtonVPN? I've tried a few things over the past few days and can't seem to get it working.

Thanks

@huzky-v
Copy link

huzky-v commented Jul 31, 2025

If someone is curious the endpoint / ipv6 address of the protonvpn servers, I have grabbed these and resolved it, making a quick search list from the api.

https://github.com/huzky-v/proton-vpn-server-list

@jakepog
Copy link

jakepog commented Jul 31, 2025

Yeah, I've been having major issues too with Proton and IPv6 in OPNsense 25.1 and 25.7. Remember, that Proton advises:

…for now, while data inside the VPN tunnel is routed using IPv6, the initial connection to the VPN server is made over IPv4.

So, the only way I've found to work is to setup the Wireguard tunnel using IPv4 first then add IPv6 to the same tunnel:

[Peer]
Allowed IP = 0.0.0.0/0

[Instance]
Tunnel Address = 10.2.0.2/32

Create IPv4 Gateway with 10.2.0.1 then restart Wireguard.
Confirm that is working e.g., netstat -nr6 and ping 10.2.0.1.
Add to the same Wireguard tunnel:

[Peer]
Allowed IP = ::/0

[Instance]
Tunnel Address = 2a07:b944::2:2/128
Gateway = 2a07:b944::2:1

Then, add IPv6 Gateway using 2a07:b944::2:1 then reset Wireguard.
The IPv6 IPs should come up in netstat -nr6 and respond ping 2a07:b944::2:1

For some weird reason adding the Wireguard instance Gateway is the only way to create the IPv6 Gateway address. Also, sometimes it can take several minutes for Proton to start responding to IPv6 traffic, so don't despair immediately.

@jakepog
Copy link

jakepog commented Aug 2, 2025

Update on IPv4 and IPv6 Wireguard tunnels in OPNsense 25.1/25.7:

opnsense/core#9021
https://forum.opnsense.org/index.php?topic=48211.0

@robertswiecki
Copy link

This works sometimes. 2a07:b944::2:2 doesn't work for me at all now.

It uses ULA - fd54:20a4:d33b:b10c:0:2:0:2

For me it works for 10 seconds, then it turns itself off for another 10. Needs more testing.

I'm testing it now with CH#514

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