Skip to content

Instantly share code, notes, and snippets.

@mikaeldui
Last active November 18, 2025 04:07
Show Gist options
  • Select an option

  • Save mikaeldui/12127c91ccece42ea375c9f42d94aa8a to your computer and use it in GitHub Desktop.

Select an option

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!

@webstrand
Copy link

I've been seeing weird misdirected ping responses. When I leaked some traffic with the wrong source address, the wireguard server decided to direct all response traffic to that address. So the ping requests would go out, but the replies would come back with a different destination address. I encourage you to check and see with wireshark.

I've been able to make both addresses work 2a07:b944::2:2/128 and fd54:20a4:d33b:b10c:0:2:0:2 (My config). The server will remember your alleged IP for an hour or so, reconnecting does nothing to help reset it. You just have to wait it out.

Note that you can only ping the DNS server that's the network address of your currently alleged IP. So if the server alleges you are at IPv6 fd54:20a4:d33b:b10c:0:2:0:2 then you can ping fd54:20a4:d33b:b10c:0:2:0:1 but not 2a07:b944::2:1, and vice versa.

@the-solipsist
Copy link

This gets me both IPv6 and IPv4 connectivity over ProtonVPN. All I need is AllowedIPs = 0.0.0.0/0, ::/0:

❯ sudo cat /etc/wireguard/protonvpn.conf | sed 's/^PrivateKey = .*/PrivateKey = ***/'
[Interface]
PrivateKey = ***
Address = 10.2.0.2/32

PostUp = resolvectl dns %i 10.2.0.1; resolvectl domain %i '~.'; resolvectl dnsovertls %i no
PreDown = resolvectl revert %i

[Peer]
# NL-FREE#12
PublicKey = 1s5mwMp3fZKNucEO3GeHRSUrhGLu/BYeC0UdusyxSWU=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 138.199.7.159:51820
sol@atri ~ 
❯ wg-quick up protonvpn
[#] ip link add dev protonvpn type wireguard
[#] wg setconf protonvpn /dev/fd/63
[#] ip -4 address add 10.2.0.2/32 dev protonvpn
[#] ip link set mtu 1420 up dev protonvpn
[#] wg set protonvpn fwmark 51820
[#] ip -6 rule add not fwmark 51820 table 51820
[#] ip -6 rule add table main suppress_prefixlength 0
[#] ip -6 route add ::/0 dev protonvpn table 51820
[#] nft -f /dev/fd/63
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] ip -4 route add 0.0.0.0/0 dev protonvpn table 51820
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] nft -f /dev/fd/63
[#] resolvectl dns protonvpn 10.2.0.1; resolvectl domain protonvpn '~.'; resolvectl dnsovertls protonvpn no
sol@atri ~ 
❯ curl -4s ifconfig.co/json --connect-timeout 1 | jq -r '. | {ipv4: .ip, ipv4_ISP: .asn_org, ipv4_city: .city, ipv4_country: .country}'
  curl -6s ifconfig.co/json --connect-timeout 1 | jq -r '. | {ipv6: .ip, ipv6_ISP: .asn_org, ipv6_city: .city, ipv6_country: .country}'
{
  "ipv4": "138.199.7.163",
  "ipv4_ISP": "Datacamp Limited",
  "ipv4_city": "Amsterdam",
  "ipv4_country": "The Netherlands"
}
{
  "ipv6": "2a02:6ea0:c041:2193::14",
  "ipv6_ISP": "Datacamp Limited",
  "ipv6_city": "Amsterdam",
  "ipv6_country": "The Netherlands"
}

@webstrand
Copy link

@the-solipsist You didn't mention how you configured your local IPv6 address? Are you using SLAAC, configuring it manually, or something else?

If its auto-configured you'll want to make sure its not a privacy address, since that'll randomize every time you reboot and break the VPN for a little while (in my experience anyway).

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