Openvpn ipv6 via pppoe

Given that with 25.12.x I am finally getting a IPv6 with a /56 PD from my local ISP I thought I might reconfigure my openvpn to use this instead of relying on a he.net tunnel for this.

I knew about the basic issue with openvpn wanting the GUA in the config so I copied the script from the wiki, adapted the names and tried it, nothing happened. So more, logging.

hotplug: USER=root ACTION=ifup SHLVL=1 HOME=/ HOTPLUG_TYPE=iface LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan PWD=/ DEVICE=pppoe-wan
...
hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan

Thing is, wan6 in my case is not active, although configured, and the ipv6 address is held by the pppoe interface directly. The call to network_get_ipaddr6 IPV6_OVPN "vpn" is coming up empty, even running it directly outside from hotplug.

Here is the script itself, after my changes:
("casa-andrea" is the name of the openvpn config)

#!/bin/sh

logger -t hotplug $(env)

# check ipv6 address has changed
if [ "$ACTION" = "ifupdate" -a "$INTERFACE" = "wan" -a "$DEVICE" = "pppoe-wan" -a "$IFUPDATE_ADDRESSES" = "1" ]
then
    ##################
    # PD fix
    ##################
    # reload interface to update PD to downstream interfaces, refer to bug described here https://forum.openwrt.org/t/delegated-ipv6-prefix-not-updated/56135
    /sbin/ifup wan6  

    # wait some time to get IPv6 up
    sleep 30  

    ##################
    # IPv6 OpenVPN assignment
    ##################

    # source network functions
    source /lib/functions/network.sh

    # get IPv6 of openvpn interface
    network_get_ipaddr6 IPV6_OVPN "vpn"
    logger -t hotplug $(IPV6_OVPN)

    if [[ ! -z $IPV6_OVPN ]]
    then
            # get subnet size of OpenVPN interface
            NET_ASSIGN="$(uci get network.vpn.ip6assign)"
            logger -t hotplug $(NET_ASSIGN)

            # set openvpn server-ipv6 option
            uci set openvpn.casa-andrea.server_ipv6="$IPV6_OVPN/$NET_ASSIGN"
            uci commit openvpn

            # reload openvpn
            service openvpn reload
    fi
fi

/etc/config/network: (relevant bits)

config interface 'vpn'
        option proto 'static'
        option device 'tun0'
        option ip6assign '64'
#       option ip6class 'wan' " tried with / without, no changes

config interface 'casa'
        option device 'br-casa'
        option ip6assign '64'
        option ip6hint '2'
        option ip6ifaceid '::00c0:fefe'
        option ipaddr '192.168.2.1'
        option ipv6 '1'
        option netmask '255.255.255.0'
        option proto 'static'

config interface 'wan'
        option device 'wan'
        option ipv6 'auto'
        option keepalive '6 5'
        option password 'redacted'
        option peerdns '1'
        option proto 'pppoe'
        option username 'redacted'

config interface 'wan6'                            
        option device 'wan'                        
        option proto 'dhcpv6'                      
        option auto '1'                            
        option reqaddress 'try'                    
        option reqprefix 'auto'        

By the by, later I would also have to update the "list-push" keyword for the dns in openvpn AND tell unbound to allow vpn clients: any ideas? I'd like to avoid blank allowing any local clients regardless of the address block.

Is it at all doable? Otherwise keeping the tunnel alive just for the (very rarely used) vpn does not seem such a bad deal :slight_smile:

Hi,

could you please post the following outputs?

logread | grep -E "wan_6|wan6|netifd"

ip -6 addr show

uci show network | grep -E "wan6|wan|vpn"

Here is the info, with one quick note: the disconnection at 4am is planned, the ISP will actually force a disconnection if online longer than 24 hrs so I picked a time when it doesn't bother me.

logread:

Tue Mar 24 04:01:19 2026 user.notice firewall: Reloading firewall due to ifup of wan6 (wan)
Tue Mar 24 04:01:21 2026 user.notice hotplug: USER=root ACTION=ifup SHLVL=1 HOME=/ HOTPLUG_TYPE=iface LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan6 PWD=/ DEVICE=wan
Tue Mar 24 04:01:21 2026 user.notice nlbwmon: Reloading nlbwmon due to ifup of wan6 (wan)
Tue Mar 24 04:05:00 2026 daemon.notice netifd: radio0 (1948): wifi-scripts: Tearing down phy0
Tue Mar 24 04:05:01 2026 daemon.notice netifd: Network device 'phy0-ap1' link is down
Tue Mar 24 04:05:01 2026 daemon.notice netifd: Network device 'phy0-ap0' link is down
Tue Mar 24 04:05:01 2026 daemon.notice netifd: radio1 (1969): wifi-scripts: Tearing down phy1
Tue Mar 24 04:05:02 2026 daemon.notice netifd: Network device 'phy1-ap1' link is down
Tue Mar 24 04:05:02 2026 daemon.notice netifd: bridge 'br-guest' link is down
Tue Mar 24 04:05:02 2026 daemon.notice netifd: Interface 'guest' has link connectivity loss
Tue Mar 24 04:05:02 2026 daemon.notice netifd: Network device 'phy1-ap0' link is down
Tue Mar 24 04:05:02 2026 daemon.notice netifd: radio0 (1985): wifi-scripts: Starting
Tue Mar 24 04:05:03 2026 daemon.notice netifd: radio0 (1985): command failed: Not supported (-95)
Tue Mar 24 04:05:05 2026 daemon.notice netifd: radio0 (1985): wifi-scripts: Configuring 'phy0' txantenna: 4294967295, rxantenna: 4294967295 distance: 0
Tue Mar 24 04:05:05 2026 daemon.notice netifd: radio0 (1985): wifi-scripts: Preparing interface: phy0-ap0 with MAC: redacted
Tue Mar 24 04:05:05 2026 daemon.notice netifd: radio0 (1985): wifi-scripts: Preparing interface: phy0-ap1 with MAC: redacted
Tue Mar 24 04:05:05 2026 daemon.notice netifd: radio1 (2012): wifi-scripts: Starting
Tue Mar 24 04:05:05 2026 daemon.notice netifd: radio1 (2012): command failed: Not supported (-95)
Tue Mar 24 04:05:07 2026 daemon.notice netifd: radio1 (2012): wifi-scripts: Configuring 'phy1' txantenna: 4294967295, rxantenna: 4294967295 distance: 0
Tue Mar 24 04:05:07 2026 daemon.notice netifd: radio1 (2012): wifi-scripts: Preparing interface: phy1-ap0 with MAC: redacted
Tue Mar 24 04:05:07 2026 daemon.notice netifd: radio1 (2012): wifi-scripts: Preparing interface: phy1-ap1 with MAC: redacted
Tue Mar 24 04:05:16 2026 daemon.notice netifd: Network device 'phy0-ap0' link is up
Tue Mar 24 04:05:16 2026 daemon.notice netifd: bridge 'br-guest' link is up
Tue Mar 24 04:05:16 2026 daemon.notice netifd: Interface 'guest' has link connectivity
Tue Mar 24 04:05:16 2026 daemon.notice netifd: Network device 'phy0-ap1' link is up
Tue Mar 24 04:06:33 2026 daemon.notice netifd: Network device 'phy1-ap0' link is up
Tue Mar 24 04:06:33 2026 daemon.notice netifd: Network device 'phy1-ap1' link is up
Tue Mar 24 04:40:09 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan
Tue Mar 24 05:00:19 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan
Tue Mar 24 06:20:59 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan
Tue Mar 24 06:41:09 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan
Tue Mar 24 07:01:53 2026 daemon.notice netifd: Network device 'lan1' link is down
Tue Mar 24 07:01:56 2026 daemon.notice netifd: Network device 'lan1' link is up
Tue Mar 24 07:02:28 2026 daemon.notice netifd: Network device 'lan1' link is down
Tue Mar 24 07:02:31 2026 daemon.notice netifd: Network device 'lan1' link is up
Tue Mar 24 08:01:49 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan
Tue Mar 24 08:21:59 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan
Tue Mar 24 10:22:59 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan
Tue Mar 24 10:43:09 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan
Tue Mar 24 16:00:00 2026 daemon.notice netifd: Network device 'lan1' link is down
Tue Mar 24 16:00:05 2026 daemon.notice netifd: Network device 'lan1' link is up
Tue Mar 24 16:00:42 2026 daemon.notice netifd: Network device 'lan1' link is down
Tue Mar 24 16:02:47 2026 daemon.notice netifd: Network device 'lan1' link is up
Tue Mar 24 16:03:10 2026 daemon.notice netifd: Network device 'lan1' link is down
Tue Mar 24 16:03:12 2026 daemon.notice netifd: Network device 'lan1' link is up
Tue Mar 24 18:26:59 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan
Tue Mar 24 18:32:34 2026 daemon.notice netifd: Network device 'lan2' link is down
Tue Mar 24 18:32:46 2026 daemon.notice netifd: Network device 'lan2' link is up
Tue Mar 24 18:47:09 2026 user.notice hotplug: USER=root ACTION=ifupdate SHLVL=1 HOME=/ HOTPLUG_TYPE=iface IFUPDATE_PREFIXES=1 LOGNAME=root DEVICENAME= TERM=linux PATH=/usr/sbin:/usr/bin:/sbin:/bin INTERFACE=wan_6 PWD=/ DEVICE=pppoe-wan

ip -6 addr show:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
    inet6 ::1/128 scope host proto kernel_lo 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 fe80::f2b0:14ff:fef6:8203/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
7: wan@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 fd5c:f6d9:6cb6:0:f2b0:14ff:fef6:8203/64 scope global dynamic noprefixroute 
       valid_lft 6702sec preferred_lft 3102sec
    inet6 fe80::f2b0:14ff:fef6:8203/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
14: br-casa: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2a00:a520:1116:d202::c0:fefe/64 scope global dynamic noprefixroute 
       valid_lft 204866sec preferred_lft 118466sec
    inet6 fdcf:87a:51fb:2::c0:fefe/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::f2b0:14ff:fef6:8203/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
15: br-guest: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2a00:a520:1116:d203::c0:fefe/64 scope global dynamic noprefixroute 
       valid_lft 204866sec preferred_lft 118466sec
    inet6 fdcf:87a:51fb:3::c0:fefe/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::f2b0:14ff:fef6:8203/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
154: pppoe-wan: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1492 state UNKNOWN qlen 3
    inet6 2a00:a520:1001:1729:e897:4422:faae:ac6b/64 scope global dynamic noprefixroute 
       valid_lft 258087sec preferred_lft 171687sec
    inet6 fe80::e897:4422:faae:ac6b peer fe80::200:5eff:fe00:101/128 scope link nodad 
       valid_lft forever preferred_lft forever
163: ifb4pppoe-wan: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 32
    inet6 fe80::1c45:2aff:fef0:6e05/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
165: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 500
    inet6 fdcf:87a:51fb::1/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 2a00:a520:1116:d200::1/64 scope global dynamic noprefixroute 
       valid_lft 204866sec preferred_lft 118466sec
    inet6 fe80::ed32:f40b:2f5f:2684/64 scope link stable-privacy proto kernel_ll 
       valid_lft forever preferred_lft forever

(interesting: with manual testing I didn't get a real address on tun0....however /etc/config/openvpn still points to the local address I entered)

uci:

network.vpn=interface
network.vpn.proto='static'
network.vpn.device='tun0'
network.vpn.ip6assign='64'
network.wan=interface
network.wan.device='wan'
network.wan.ipv6='auto'
network.wan.keepalive='6 5'
network.wan.password=redacted
network.wan.peerdns='1'
network.wan.proto='pppoe'
network.wan.username=redacted
network.wan6=interface
network.wan6.device='wan'
network.wan6.proto='dhcpv6'
network.wan6.auto='1'
network.wan6.reqaddress='try'
network.wan6.reqprefix='auto'
network.modem.device='wan'

Perfect! This confirms it's the same bug as #72 https://github.com/openwrt/netifd/issues/72

The problem:

Your hotplug script checks for INTERFACE=wan, but the system triggers with INTERFACE=wan_6 (the dynamic interface created by DHCPv6). That's why your script condition never matches and never executes.

The wan_6 triggers every 20-40 minutes are DHCPv6 prefix renewals.

The solution:

In your hotplug script /etc/hotplug.d/iface/30-ipv6pdchange change the line:

bash

if [ "$ACTION" = "ifupdate" -a "$INTERFACE" = "wan" -a "$DEVICE" = "pppoe-wan" -a "$IFUPDATE_ADDRESSES" = "1" ]

to:

bash

if [ "$ACTION" = "ifupdate" -a "$INTERFACE" = "wan_6" -a "$DEVICE" = "pppoe-wan" -a "$IFUPDATE_PREFIXES" = "1" ]

Note: Changed IFUPDATE_ADDRESSES to IFUPDATE_PREFIXES because your logs show prefix updates, not address updates. The proper fix should be in netifd itself to prevent the wan6 vs wan_6 conflict.

1 Like

Change applied but still no luck: interface gets IP but openvpn config still has local address.

The more I think about it, however, the more I am convinced that re-activating the tunnel for the purpose of the vpn is not such a bad idea: simpler config AND it also fixes the issue with a host in the lan which must be exposed (good luck updating the firewall to point to a moving target).

Thanks for the suggestion, I subscribed to the bug report to keep up to date.

Could you please try one more time? There are two things missing in your config:

1. Add ip6class to your vpn interface:

In /etc/config/network:

config interface 'vpn'
        option proto 'static'
        option device 'tun0'
        option ip6assign '64'
        option ip6class 'wan6'    # ← Add this line

2. Fix the interface name in the script:

You named your interface vpn, but the script checks for LANvpn. Change:

bash

network_get_ipaddr6 IPV6_OVPN "LANvpn"

to:

bash

network_get_ipaddr6 IPV6_OVPN "vpn"

Without ip6class 'wan6', your vpn interface won't get a subnet from the delegated prefix.

I already reverted all changes, sorry. But one thing I can tell you: in order to segregate the ISP prefix to the main networks and the tunnel prefix to the vpn I had to use "ip6class wan_6", not "wan", not "wan6".... so that might have helped, indeed.

Also, the script had been adapted to take into account the interface name being "vpn", see above.

Thanks for the feedback! The fact that you needed ip6class 'wan_6' (not wan6) confirms the bug - the system works internally with wan_6 instead of the configured wan6.

I'll add this information to the bug report.

1 Like

Also, I was getting the address assigned to the bridge interface on the router but no delegation to my desktop... until I switched off "wan6".