Wireguard: ipv4 is routed but not ipv6

I'm not the only who had that problem, and each time the solution seems really complicated.
I found out and that can be solve it very easily. I think it's a "bug" of OpenWrt, or at least default value problem, but I'm sure. Maybe there's a reason for this.

Let me explain.

Let's say you configured your router to connect to a wireguard server. Your router is the 'client'. In my case, the server was another OpenWrt somewhere else in the world.
Like this, for axample.

config interface 'vpn'
	option proto 'wireguard'
	option private_key '[Private key of the client router. This router.]'
	list addresses '10.x.x.10/24' 
	list addresses 'fdx:y:z:t::10/128'
	list dns '8.8.8.8'
	option auto '0' # easier for testing to disable at boot and start stop this interface in luci, I think. But not relevant to this problem.


config wireguard_vpn 'wgserver'
	option public_key '[Public key of the wireguard server.]'
	option endpoint_host '[IP of the wireguard server]'
	option endpoint_port '51820'
	option persistent_keepalive '25'
	option route_allowed_ips '1'
	list allowed_ips '0.0.0.0/0'
	list allowed_ips '::/0'

When you start this interface, you'll find that ipv4 go through the tunnel, but ipv6.

I spent quite a decent amount of time to dig around and understand what's going on, until I finally noticed that the ipv6 gateway was created with a metric of 1024.
Enter ip -6 route show | grep default and you'll see something like:

default via fe80::267e:12ff:fef1:5819 dev wan  metric 512 <- route to my ISP
default dev vpn  metric 1024 <- route to wireguard

No wonder why the new route is not used with a metric of 1024.

Going to the interface advanced settings in Luci, I noticed a field "metric". In it, there is a gray '0'. Supposed to be the default value, right ? Here is why I think there is a 'bug'. Obviously, the default is 1024. Which is wrong because we want all traffic going to the tunnel.

Let's type in 0 in that field. Stop and Restart the interface and voila! The metric is still 1024!!

Ok, let's type in 1 in the metric field. This time it works. Well..., almost.
Now, the ipv6 is routed, not the ipv4 anymore!!! What gives.
Let's have a look at the ipv4 routing table: ip route show | grep default. You'll get:

default via [some ip from your ISP] dev wan  src [some ip from your ISP] 
default dev vpn scope link  metric 1

Ok, metric 1, that's what we configured. But the ISP default gateway has a metric of 0. So of course, the ISP gateway is used first.
Go to your wan interface advanced settings. Change the gray '0' to more than 1. Like 2048. Stop the wan interface. It'll restart by itself.

And this time: VOILA bis. Both ipv4 and ipv6 are routed through wireguard.

To make the story short, I'll suggest this improvement to openwrt:

  • the wan default gateway metric should be the same as the wan6. For example 512.
  • when you set the wireguard interface metric to 0, it ends up being 1024. It's a bug or a limitation. If it's a limitation of wireguard, let's default to 1.

Thank you for your attention. Hope this help.

This is outside Wireguard, it is an OpenWrt thing. The route_allowed_ips functionality is in netifd scripts.

A v4 default route at least used to be installed by splitting the whole Internet into two /1 subnets like OpenVPN does. These have priority over any existing /0 route regardless of the metric. It could also be done with v6.

I would go for using metric as @Jief suggested.

Not sure why you're talking about route_allowed_ips.

I still think that having a default metric to 0 that ends up being 1024 should be taken care. How and where, I don't know.

I also think that having a metric 0 for ISP gateways is not the best. Wouldn't that make more sense to have a higher metric by default ?

In the end, setting up a new default gateway (when I start my wireguard interface) that will be completely ignored should at least warn the user so he won't waste a full day digging around, isn't it ?

Enabling route_allowed_ips causes OpenWrt to insert routes for the configured allowed_ips into the kernel default routing table. If you set route_allowed_ips to zero then you can use config route statements or pbr to set up the routing manually.

Wireguard in the kernel is just a tunnel which encrypts / decrypts packets and presents the cleartext version as an interface. (the cyphertext is also dispatched or received with destination-based routing like any other process does) If the tunneled packets are going to be firewalled or forwarded beyond the router's internal use, the kernel does it conventionally using the same netfilter and routing tables as everything else.

Ok, thanks for clarification.

But would you agree that allowing 0 in the metric field that silently become a 1024 should be taken care of ?