Wireguard client interface starting before its endpoint can be resolved

I have a router I configured for a road warrior client - so I can plug it into a host router, and it gives me wifi over a VPN as if I was at home.

It worked great for a week, until I just rebooted it. Now there seems to be a race condition. When the router boots up, the wireguard interface is starting and changing the routing to put 0.0.0.0/0 over the wireguard interface before wireguard can actually talk over the WAN interface to resolve the hostname for wireguard's endpoint.

I've temporarily solved the problem by setting the wireguard interface not to start at boot, then bringing it up manually after a delay after checking it can ping out. But I can't think this is the right way to do it. I don't know why it worked before.

What is the right way to do this?

It is probably not dns, but rather time.

1 Like

I figured I'd just add a preup with ntpdate to the wireguard config, but I can't for the life of me figure out how to add my own entries to it. Not without going to heroics.

Was there ever any other solution for this? As it stands, I think I'm going to have to keep the basic form of my current solution. Keep the wireguard interface from auto-starting and manually start it once the script can detect wan access and ensure the clock is set.

full disclosure -- this is on my to-do list for my travel router, but I haven't yet gotten to it, so no experience implementing).

Did you look at the most recent posts on that thread? I think that there are some implementation details that may be useful here... the last one actually has a cool script that is fired off by rc.local. It will look to see if there is connectivity to the internet... if not, it will make sure that the WG tunnel is down and try again. It will wait for the sync to happen and then send ifup to the wireguard interface.

Yes, this is not as elegant as a true 'pre-up' solution, but it should achieve the same thing.

The full thread was interesting. In points I say I was disappointed - I think as a group we need to step away from the expectation that every user should be willing to learn scripting and become networking experts.

There didn't seem to be 100% consensus on what the root problem was. Really, the issue is that as a connectionless protocol, there is nothing to indicate success, which is a problem for any peer that wants to route everything.

In any case, whether it's a time issue or endpoint resolving issue, the solution is basically the same. Set the wireguard interface to not start automatically, then test for connectivity before bringing it up. This is my script:

# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.


(
  # Cool our heels until homefires will give us the time of day
  while ! ping -c 1 homefires.somedomain.ca > /dev/null 2>&1 || ! ntpdate homefires.somedomain.ca > /dev/null ; do sleep 2; done

  # If we're here we know we can ping homefires and that 
  # we have our clock set, so bring up the wireguard interface
  ifup wg0
  # Give wireguard a moment to get going...
  sleep 4
  # Now mount remote storage to a local mountpoint, then start up minidlna
  mount.cifs //someaddress/Trunk /mnt/Trunk -ocredentials=/root/admin/etc/Trunk_credientials && /etc/init.d/minidlna start
) &

exit 0

My "homefires" address is my main home router which has been set to serve up ntp too.

Incidentally, this also contains my solution for not getting smcroute to work for DLNA access across subnets - I just run the DLNA server on the travel router too and point it at the remote storage. Some day I'll tackle smcroute again.

That's a really elegant solution, thanks for sharing @VA1DER.

I found another slightly less clever but kinda easy solution here: Bring up (activate) interface delayed - #5 by reinerotto

Basically it is not checking connectivity like yours, just waiting for some seconds. In my case, waiting for 60 seconds before bringing up the wireguard interface was sufficient.

The solution is just to reference a script '/etc/ifup_delayed.sh' from /etc/rc.local - it just waits for 60 seconds then uses ifup to bring the interface up. For me this works now reliably.

Dont forget if you're using this solution to also disable auto-starting of the wireguard interface (uncheck 'bring up on boot')

On my travel router I use two tunnels in fail over setting, if one fails the next tunnel is started, I do not have failing tunnels often but it happens occasionally.

You can just set one tunnel and then that tunnel is just restarted in case of failure :slight_smile:

See: https://github.com/egc112/OpenWRT-egc-add-on/tree/main/wireguard-watchdog

I implemented WireGuard on another third party firmware and there the interface is only brought up after checking for the correct time to ensure that there is already a valid connection