The problem:
I cannot get OpenWRT acting as a Wireguard client (interface protonvpn1) to connect to a server/peer. The behavior I observe is:
- When I have no peers or only disabled peers, the network interface is created, but without peers, it is useless.
- When I have an enabled peer, the
protonvpn1interface is NOT created, and the UI statesNetwork device is not presentwhile its trying to use the nonexistent device/interfacewireguard-protonvpn1. Because of this, I also think the VPN IP isn't getting added to the OS's routing table (ip route). I find its attempt to use a different interface when peers are present to be particularly odd.
What I've tried so far:
- Reading/following OpenWRT's documentation on wireguard setup.
- Restarting my OpenWRT device.
- Configuring using
ucicommands before runninguci commitandservice network restart. - Configuring using the web interface after installing the
luci-proto-wireguardpackage. I've tried both manual entry as well as uploading the Wireguard config file provided by my VPN provider. - Performing a system-wide update of all packages.
- Running
tcpdump -i any port 51820to see any attempts at VPN traffic (there has been none). - Disabling peers (so that the interface comes up) and running the command
wg addconf protonvpn1 peer.confworks; a handshake is successful and I am able to verify my IP is the VPN's IP, but this configuration does not persist across restarts of thenetworkservice.peer.confis a copy-paste of the[Peer]section in my VPN provider's supplied config.
Setting up wireguard (via uci) has previously worked for me using an older (and probably snapshot) version of OpenWRT, but something triggered a kernel panic during maintenance a couple of days ago, so I started fresh. The configuration in /etc/config/network looks much the same as what it was previously, but I did not restore from a proper backup.
Other information about my setup:
- Raspberry Pi 5 Model B Rev 1.0 w/ an Ethernet hat connected via PCIe.
- OpenWrt 25.12.3 r32912-6639b15f62
Relevant parts of /etc/config/network (populated from uploading my VPN provider's config):
config interface 'protonvpn1'
option proto 'wireguard'
option private_key '<redacted>'
list addresses '10.2.0.2/32'
list addresses '2a07:b944::2:2/128'
list dns '10.2.0.1'
list dns '2a07:b944::2:1'
option multipath 'off'
config wireguard_protonvpn1
option description 'Imported peer configuration'
option public_key '<redacted>'
list allowed_ips '0.0.0.0/0'
list allowed_ips '::/0'
option persistent_keepalive '25'
option endpoint_host '<ip>'
option endpoint_port '51820'
Output from wg showconfig protonvpn1 with no peers enabled:
[Interface]
ListenPort = 56764
PrivateKey = <redacted>
Systemlog after restarting interface with peers enabled:
[May 12, 2026, 12:47:22 AM UTC] daemon.notice: hostapd: Set MLD config: [ ]
[May 12, 2026, 12:47:22 AM UTC] daemon.notice: hostapd: Reload all interfaces
[May 12, 2026, 12:47:22 AM UTC] daemon.notice: wpa_supplicant[850]: Set MLD config: [ ]
[May 12, 2026, 12:47:22 AM UTC] daemon.notice: netifd: Interface 'protonvpn1' is setting up now
[May 12, 2026, 12:47:22 AM UTC] daemon.notice: netifd: Interface 'protonvpn1' is now down
[May 12, 2026, 12:47:22 AM UTC] daemon.notice: netifd: Interface 'protonvpn1' is setting up now
[May 12, 2026, 12:47:22 AM UTC] daemon.notice: netifd: Interface 'protonvpn1' is now down
Syslog after restarting interface with no peers enabled:
[May 12, 2026, 12:49:17 AM UTC] daemon.notice: hostapd: Set MLD config: [ ]
[May 12, 2026, 12:49:17 AM UTC] daemon.notice: hostapd: Reload all interfaces
[May 12, 2026, 12:49:17 AM UTC] daemon.notice: wpa_supplicant[850]: Set MLD config: [ ]
[May 12, 2026, 12:49:17 AM UTC] daemon.notice: netifd: Network device 'protonvpn1' link is down
[May 12, 2026, 12:49:18 AM UTC] daemon.notice: netifd: Interface 'protonvpn1' is now down
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: reading /tmp/resolv.conf.d/resolv.conf.auto
[May 12, 2026, 12:49:18 AM UTC] daemon.notice: netifd: Interface 'protonvpn1' is setting up now
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using nameserver 1.1.1.1#53
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using nameserver 1.1.1.1#53
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for test
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for onion
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for localhost
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for local
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for invalid
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for bind
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for lan
[May 12, 2026, 12:49:18 AM UTC] daemon.notice: netifd: Interface 'protonvpn1' is now up
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: reading /tmp/resolv.conf.d/resolv.conf.auto
[May 12, 2026, 12:49:18 AM UTC] daemon.notice: netifd: Network device 'protonvpn1' link is up
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using nameserver 1.1.1.1#53
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using nameserver 10.2.0.1#53
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using nameserver 2a07:b944::2:1#53
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using nameserver 1.1.1.1#53
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for test
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for onion
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for localhost
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for local
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for invalid
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for bind
[May 12, 2026, 12:49:18 AM UTC] daemon.info: dnsmasq[1]: using only locally-known addresses for lan
[May 12, 2026, 12:49:18 AM UTC] user.notice: firewall: Reloading firewall due to ifup of protonvpn1 (protonvpn1)