wireguard "destination address required" when trying to communicate from client-to-client rather than client-to-server

Solution 1:

Let's follow what happens:

  • Client1's routing table tell it that 192.168.64.11 is reachable through wg0.
  • Client1's wg0 cryptokey-routing settings tell that 192.168.64.11 is reachable through 2nd Peer (with a key starting with mRjd9) aka Client2.
  • payload is ready to be tunneled to 2nd Peer's current endpoint... except there's no Endpoint defined to reach the 2nd Peer and as there was never traffic received in the other direction (for the very same reason) no endpoint exists. That's different for Server which on receiving the first packet from Client1 will set the current Client1's source address as the endpoint.

The same happens in the other direction from Client2 to Client1: there's no Endpoint defined and no traffic was received to have an endpoint set.

So the tunnel being currently incomplete, fails. wireguard sends the error EDESTADDRREQ/Destination address required when this happens. Just because it's more difficult to specify what is this other side, doesn't mean omitting it will magically make it work.

As both are NATed you get the usual NAT connectivity issues between two NATed devices.

To solve this you can either:

  • Use Server as a STUN-like server (maybe even running an actual STUN server, but outside of the tunnel) to synchronize the method for Client1 and Client2 to attempt UDP hole punching with WireGuard tunnels, assuming there's no Symmetric NATs or CG NAT in the way. That's beyond the scope of this WireGuard question to do this properly, but that should be what to favor to avoid needing Server for all traffic.

    Note that using 0.0.0.0/0 in AllowedIps on each client makes no sense as soon as there are two peers defined each with values in AllowedIps. 0.0.0.0/0 will be silently discarded from the cryptokey route in the end and should not be used. One IP address can resolve (ie: be cryptokey-routed) to exactly one Peer (or none) but never more than one.

  • or, as it appears was intended in OP, relay traffic through Server which requires to set Server as router on its wg0 interface (used both for ingress and egress) and change configuration on Client1 and Client2. There's no "dynamic cryptokeyrouting" protocol, the change must be done manually or with scripts on both clients (until some routing daemon able to do this for WireGuard appears). For example (here just using 0.0.0.0/0 instead of explicitly stating all the routes would have be fine, there's now only one actual Peer):

    • Client1

      [Interface]
      PrivateKey = <secret key>
      ListenPort = 50001
      
      [Peer]
      PublicKey = 2VtQ/...
      Endpoint = wg.example.com:50001
      AllowedIps = 192.168.64.1/32, 10.0.0.0/8, 192.168.64.11/32
      PersistentKeepalive = 30
      

      The part below becomes useless: Client1 never has Client2 as peer, only Server. But it can still be kept in the configuration:

      [Peer]
      PublicKey = mRjd9...
      AllowedIps = 
      PersistentKeepalive = 30
      
    • Client2

      [Interface]
      PrivateKey = <secret key>
      ListenPort = 50001
      
      [Peer]
      PublicKey = 2VtQ/...
      Endpoint = wg.example.com:50001
      AllowedIps = 192.168.64.1/32, 192.168.1.0/24, 192.168.11.0/24, 192.168.13.0/24, 192.168.64.10/32
      PersistentKeepalive = 30
      
      [Peer]
      PublicKey = 1cML7...
      AllowedIps = 
      PersistentKeepalive = 30