Need help getting protonvpn to work with IPv6

Hello,

First of all I'm sorry for the bad description of my setup/problem, my native language isn't english and I'm a beginner in networking

Right now my setup is stable, with AGH, Unbound and IPv6 working as expected. The problem I'm having is that I can't get the vpn connection to function correctly with IPv6.

I have two lan interfaces, a main one and a guest one. I want all the traffic from the main lan interface to go through the protonvpn server, such that it also uses an IPv6 from protonvpn. The traffic from the guest lan interface shall use IPv6 from my ISP.
My ISP is 1&1 (I have DSL100), I live in Germany.

I tried for countless hours but I can't get it working. I reverted everything I tried except for the protonvpn interface.

I wanted to post screenshots of my config, but I can only upload one image, so if you need specifig configs please let me know

I would really appreciate it if you could help me out!

Are you using WireGuard or OpenVPN?

For WireGuard see:
WireGuard Client Setup Guide

Yes I use WireGuard. The document helped me, thank you!
A few questions:

I've went with the option to add ::/1 and 8000::/1 at allowed IPs.
On which of my interfaces do I enable source routing?

Where do I enable default gateway?

Where do I enable IPv4/6 masquerading? Only the wan zone?

Where do I enable MSS Clamping? Only the wan zone?

And I have a lan_guest interface. I don't want the traffic from the guest interface to exit through the vpn server.
But the lan_guest zone allows forward to the wan destination zone, which includes protonvpn... That's not supposed to be that way right?

Again thank you so much.

root@nanopi:~# ubus call system board
g/network

cat /etc/c{
        "kernel": "6.12.74",
        "hostname": "nanopi",
        "system": "ARMv8 Processor rev 0",
        "model": "FriendlyElec NanoPi R3S",
        "board_name": "friendlyarm,nanopi-r3s",
        "rootfs_type": "ext4",
        "release": {
                "distribution": "OpenWrt",
                "version": "25.12.2",
                "firmware_url": "https://downloads.openwrt.org/",
                "revision": "r32802-f505120278",
                "target": "rockchip/armv8",
                "description": "OpenWrt 25.12.2 r32802-f505120278",
                "builddate": "1774469393"
        }
}
onfig/wireless

cat /etc/config/firewall

wgroot@nanopi:~#
root@nanopi:~# cat /etc/config/network

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        list ipaddr '127.0.0.1/8'

config globals 'globals'
        option dhcp_default_duid '00047c79411fe9c14cb0807b16885eebad65'
        option ula_prefix 'fd39:9497:bd6::/48'
        option packet_steering '1'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'eth1'

config device
        option name 'eth1'
        option macaddr 'f6:44:20:63:01:15'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ip6assign '64'
        option ipaddr '192.168.10.1'
        option multipath 'off'
        option netmask '255.255.255.0'
        option defaultroute '0'
        option delegate '0'

config device
        option name 'eth0'
        option macaddr 'f6:44:20:63:01:14'

config interface 'wan'
        option device 'eth0'
        option proto 'pppoe'
        option username 
        option password 
        option ipv6 '0'
        option multipath 'off'
        option peerdns '0'
        option delegate '0'
        option sourcefilter '0'
        option force_link '1'

config interface 'wan6'
        option device '@wan'
        option proto 'dhcpv6'
        option reqaddress 'try'
        option reqprefix 'auto'
        option norelease '1'
        option multipath 'off'
        option peerdns '0'
        option force_link '1'

config interface 'lan_guest'
        option proto 'static'
        option device 'eth1.2'
        option ipaddr '192.168.20.1'
        option netmask '255.255.255.0'
        option defaultroute '0'
        option multipath 'off'
        option delegate '0'
        option ip6assign '64'

config wireguard_protonvpn
        option public_key 'XcWEb0DMaFBex2HD2DVUStifh6wBZe9ELo2N/KLlMHc='
        option persistent_keepalive '25'
        option endpoint_host '2a07:b941:e40::1:d'
        option endpoint_port '51820'
        option route_allowed_ips '1'
        list allowed_ips '::/0'
        list allowed_ips '0.0.0.0/0'
        list allowed_ips '::/1'
        list allowed_ips '8000::/1'

config device
        option name 'pppoe-wan'

config device
        option name 'eth1.2'
        option type '8021q'
        option ifname 'eth1'
        option vid '2'

config interface 'protonvpn'
        option proto 'wireguard'
        option force_link '1'
        option private_key 
        list addresses '2a07:b944::2:2/128'
        list addresses '10.2.0.2/32'
        option multipath 'off'
        option delegate '0'

root@nanopi:~#
root@nanopi:~# cat /etc/config/wireless
cat: can't open '/etc/config/wireless': No such file or directory
root@nanopi:~#
root@nanopi:~# cat /etc/config/firewall

config defaults
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'

config zone
        option name 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'lan'

config zone
        option name 'wan'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'DROP'
        option masq '1'
        option mtu_fix '1'
        option masq6 '1'
        list network 'protonvpn'
        list network 'wan'
        list network 'wan6'
        list masq_src '2a07:b944::2:2/64'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config zone
        option name 'lan_guest'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        list network 'lan_guest'

config forwarding
        option src 'lan_guest'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Guest'
        option src 'lan_guest'
        option proto 'udp'
        option dest_port '67'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Guest'
        option src 'lan_guest'
        option proto 'icmp'
        option family 'ipv6'
        option target 'ACCEPT'
        list icmp_type 'bad-header'
        list icmp_type 'destination-unreachable'
        list icmp_type 'neighbour-advertisement'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'packet-too-big'
        list icmp_type 'router-advertisement'
        list icmp_type 'router-solicitation'
        list icmp_type 'time-exceeded'
        list icmp_type 'unknown-header-type'

config rule
        option name 'Allow-DHCPv6-Guest'
        option src 'lan_guest'
        option proto 'udp'
        option dest_port '547'
        option target 'ACCEPT'

config forwarding
        option src 'lan'
        option dest 'wan'

root@nanopi:~#
root@nanopi:~# wg show
interface: protonvpn
  public key: QzMHpmI/13V2Zdb06PgGOiH7nPtu1e90T0nu7WsGCm0=
  private key: (hidden)
  listening port: 42091

peer: XcWEb0DMaFBex2HD2DVUStifh6wBZe9ELo2N/KLlMHc=
  endpoint: [2a07:b941:e40::1:d]:51820
  allowed ips: ::/0, 0.0.0.0/0, ::/1, 8000::/1
  latest handshake: 1 minute, 42 seconds ago
  transfer: 672.02 MiB received, 156.76 MiB sent
  persistent keepalive: every 25 seconds

First get basic everything default routed by VPN first, then add source based routing.

You should add a separate firewall zone for protonvpn because you need masq6 there but should keep regular v6 routing for those lans that will use the main wan.

LAN devices will each need a unique v6 address on the lan that can be masqueraded to the one /128 that is valid inside the VPN tunnel. These IPs would typically be GUAs delegated conventionally from space belonging to your ISP. When routing and masquerading to VPN they will not appear at Proton or on the Internet.

Okay I created a new firewall zone. On the guest network, the internet isn't working. On the main network, everything seems perfect, test-ipv6.run shows proton IPv4/6

root@nanopi:~# cat /etc/config/firewall

config defaults
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'

config zone
        option name 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'lan'

config zone
        option name 'wan'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        list network 'wan'
        list network 'wan6'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config zone
        option name 'lan_guest'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        list network 'lan_guest'

config forwarding
        option src 'lan_guest'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Guest'
        option src 'lan_guest'
        option proto 'udp'
        option dest_port '67'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Guest'
        option src 'lan_guest'
        option proto 'icmp'
        option family 'ipv6'
        option target 'ACCEPT'
        list icmp_type 'bad-header'
        list icmp_type 'destination-unreachable'
        list icmp_type 'neighbour-advertisement'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'packet-too-big'
        list icmp_type 'router-advertisement'
        list icmp_type 'router-solicitation'
        list icmp_type 'time-exceeded'
        list icmp_type 'unknown-header-type'

config rule
        option name 'Allow-DHCPv6-Guest'
        option src 'lan_guest'
        option proto 'udp'
        option dest_port '547'
        option target 'ACCEPT'

config zone
        option name 'protonvpn'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        option masq6 '1'
        list network 'protonvpn'

config forwarding
        option src 'lan'
        option dest 'protonvpn'

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        list ipaddr '127.0.0.1/8'

config globals 'globals'
        option dhcp_default_duid '00047c79411fe9c14cb0807b16885eebad65'
        option ula_prefix 'fd39:9497:bd6::/48'
        option packet_steering '1'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'eth1'

config device
        option name 'eth1'
        option macaddr 'f6:44:20:63:01:15'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ip6assign '64'
        option ipaddr '192.168.10.1'
        option multipath 'off'
        option netmask '255.255.255.0'
        option defaultroute '0'
        option delegate '0'

config device
        option name 'eth0'
        option macaddr 'f6:44:20:63:01:14'

config interface 'wan'
        option device 'eth0'
        option proto 'pppoe'
        option username 
        option password 
        option ipv6 '0'
        option multipath 'off'
        option peerdns '0'
        option delegate '0'
        option sourcefilter '0'
        option force_link '1'

config interface 'wan6'
        option device '@wan'
        option proto 'dhcpv6'
        option reqaddress 'try'
        option reqprefix 'auto'
        option norelease '1'
        option multipath 'off'
        option peerdns '0'
        option force_link '1'

config interface 'lan_guest'
        option proto 'static'
        option device 'eth1.2'
        option ipaddr '192.168.20.1'
        option netmask '255.255.255.0'
        option defaultroute '0'
        option multipath 'off'
        option delegate '0'
        option ip6assign '64'

config wireguard_protonvpn
        option public_key 'XcWEb0DMaFBex2HD2DVUStifh6wBZe9ELo2N/KLlMHc='
        option persistent_keepalive '25'
        option endpoint_host '2a07:b941:e40::1:d'
        option endpoint_port '51820'
        option route_allowed_ips '1'
        list allowed_ips '::/0'
        list allowed_ips '0.0.0.0/0'
        list allowed_ips '::/1'
        list allowed_ips '8000::/1'

config device
        option name 'pppoe-wan'

config device
        option name 'eth1.2'
        option type '8021q'
        option ifname 'eth1'
        option vid '2'

config interface 'protonvpn'
        option proto 'wireguard'
        option force_link '1'
        option private_key 
        list addresses '2a07:b944::2:2/128'
        list addresses '10.2.0.2/32'
        option multipath 'off'
        option delegate '0'
        option mtu '1420'

config device
        option name 'protonvpn'

To do the source based routing you will need pbr or manually set up a second routing table. The firewall rules such as forward guest to wan only define what traffic will be potentially allowed or blocked.

The kernel routing table(s) define how packets will be forwarded. If you only have the single default pair of tables (v4 and v6) all Internet will go to one interface. The route_allowed_ips setting in Wiregard combined with a ::/0 allowed_ip makes wireguard the default. But since the firewall blocks guest -> vpn, guests cannot reach the Internet at all.

It is either or:

Note for IPv6 either

  1. add ::/1 and 8000::/1 as Allowed IPs to create a default route, this has the "benefit" of reinstating default route via wan6 if the interface is disabled

or

  1. Disable Source routing (Interfaces > Network > wan6 > Advanced tab: untick/disable IPv6 source routing and set the wan6 gateway metric to 512 to be the same as your VPN interface (note this looks broken), alternatively set wan gateway metric and WireGuard interface metric both to 256 on the Advanced Interface tab.

So you already have implemented /1 so no need to disable source routing

You do not, the default gateway follows from your settings in Allowed IPs because you have enabled Route allowed IPs.

You followed the easy method.
The only mention for masquerading:

For IPv6 enable IPv6 Masquerading on the wan firewall zone:

(The wan firewall zone already has MSS clamping and Masquerading enabled by defualt what you can see in the picture)

For that you have to use Policy Based Routing.
For Policy Based Routing it is not strictly necessary to alter your current firewall setup but if you want to make absolutely sure that under no circumstances your guest wifi will use the VPN ( not sure why you want that) then you have to use the Advanced Method for the firewall setup and remove the forwarding from guest wifi to vpn.
My advice don't but leave it as is.

It looks good at first glance so kudos

For PBR see:

Many users use the PBR app.

Yeah I understood that with ::/1 and 8000::/1 as allowed IPs, I should leave source routing enabled at an6. But I meant the wan interface, do I enable it or disable it there?

So "use default gateway" should be disabled at all my interfaces?

I actually changed to the advanced method. On my wan firewall zone, IPv4 masquerading is enabled, and IPv6 masquerading is disabled. On my protonvpn firewall zone, IPv4 and IPv6 masquerading is enabled. Is that the correct way?

I managed to set up PBR, I think everything works now as expected. Thank you so much!

If there is no instruction in the guide (and there is none) to touch it then don't
(source routing is for IPV6)

No, if there are no instructions in the guide (and there is none) about doing that you should not touch it.

To determine which interface is default you use Route Allowed IPs if you enable that on the WireGuard peer then WireGuard is the default route, if you disable it the wan is default

For really complicated multi tunnel and site-to-site setup it is sometimes needed to change the default gateway setting but for simple setups there is no need to touch it

I get that, the problem is that I changed these settings I asked about when I tried to make my set up work, so I'm trying to find out what the default for these settings is as I don't remember.

The "use default gateway" checkbox is only relevant for protocol dhcp(6) pppoe etc where the interface pulls IP configuration from upstream. If the box is unchecked, the normal behavior to consider this interface the wan will not be followed. The default route advertised from upstream will not be installed into the main routing table. The setting has no effect on interfaces of proto static, which are typically lans. (In CLI, unchecking the box inserts an option defaultroute 0 into the configuration. If this option is not present, defaultroute 1 is assumed.)

For a Wireguard interface, the setting also has no effect and route_allowed_ips is used instead. Or if there are going to be multiple default routes, pbr takes over all of them.

New problems:

I rebooted my router, and now IPv6 on the guest network doesn't work.

IPv6 also doesn't work on my PC which is connected with the main network via cable. Weirdly IPv6 works on all other devices in the main network...

Could someone help me out?

Could be related to all the changes you have made.

Consider starting over.

Make regular backups so that you can go back to a working solution.

Actually (about 15-30min after reboot) IPv6 started working on my PC again, without me doing anything... Can that be explained? But I'm absolutely fine with IPv6 taking a bit time to get working after a reboot, as long as it then functions correctly.

However, IPv6 still doesn't work on my guest network, could you help me figure out what the problem so I don't have to start all over?

I can try, what is the output of :slight_smile: ifstatus wan6

Thanks

root@nanopi:~# ifstatus wan6
{
        "up": true,
        "pending": false,
        "available": true,
        "autostart": true,
        "dynamic": false,
        "uptime": 7705,
        "l3_device": "pppoe-wan",
        "proto": "dhcpv6",
        "device": "pppoe-wan",
        "metric": 0,
        "dns_metric": 0,
        "delegation": true,
        "ipv4-address": [

        ],
        "ipv6-address": [
                {
                        "address": "2001:16b8:a023:13aa:e9c2:1583:67e4:4a14",
                        "mask": 64,
                        "preferred": 171976,
                        "valid": 258376
                }
        ],
        "ipv6-prefix": [
                {
                        "address": "2001:16b8:b222:fb00::",
                        "mask": 56,
                        "preferred": 165085,
                        "valid": 251485,
                        "class": "wan6",
                        "assigned": {
                                "lan": {
                                        "address": "2001:16b8:b222:fb00::",
                                        "mask": 64
                                },
                                "lan_guest": {
                                        "address": "2001:16b8:b222:fb01::",
                                        "mask": 64
                                }
                        }
                }
        ],
        "ipv6-prefix-assignment": [

        ],
        "route": [
                {
                        "target": "::",
                        "mask": 0,
                        "nexthop": "fe80::9e52:f8ff:fe6c:dfba",
                        "metric": 512,
                        "valid": 976,
                        "source": "2001:16b8:b222:fb00::/56"
                },
                {
                        "target": "::",
                        "mask": 0,
                        "nexthop": "fe80::9e52:f8ff:fe6c:dfba",
                        "metric": 512,
                        "valid": 976,
                        "source": "2001:16b8:a023:13aa:e9c2:1583:67e4:4a14/64"
                }
        ],
        "dns-server": [

        ],
        "dns-search": [

        ],
        "neighbors": [

        ],
        "inactive": {
                "ipv4-address": [

                ],
                "ipv6-address": [

                ],
                "route": [

                ],
                "dns-server": [
                        "2001:1438:0:12::1",
                        "2001:1438:0:12::4"
                ],
                "dns-search": [

                ],
                "neighbors": [

                ]
        },
        "data": {
                "passthru": "001700202001143800000012000000000000000120011438000000120000000000000004"
        }
}

Actually I think I know what causes IPv6 to not work on the guest interface, I added two pbr policies, one for ipv4 and one for ipv6 of the guest interface. But after a reboot, the IPv6 changes... I could use a hotplug script to solve that right?

That looks good you have got /56 PD and your guest-lan already has got an IPv6 address

If the clients connected to your guest wifi do not get an IPv6 addressand they do when connecting to the lan (check that first) then check the settings in /etc/config/dhcp
If lan is working you need the same settings in the guest interface, usually something like this:

config dhcp 'guest'
	option interface 'guest'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option ra 'server'
	option dhcpv4 'server'
	option dhcpv6 'server'
	list ra_flags 'managed-config'
	list ra_flags 'other-config'

For IPv6 and IPv4 you can use the interface (=device as given by ifconfig) preceded with an @ this will take care of both IPv4 and IPv6.
For individual clients use the MAC address that will also take care of IPv4 and IPv6.

Yes that worked! Thank you!