Hi, thanks so much for wireguard, it is awesome. Is there any way to test if a peer is reachable at a particular ip:port endpoint, without disturbing an existing, working exchange of packets with that peer at some other ip:port? Sort of like a "wireguard ping" that avoids modifying the kernel's wg_peer.endpoint field the way "wg set peer endpoint; /bin/ping" would.
The use case here is a mobile client like a laptop that knows how to reach a server via either a preferred LAN IP (when the laptop is on the LAN) or via a less-desirable public internet address for the server. In a perfect world packets from the LAN to the server's public internet address wouldn't be trombone-routed. Sadly, in real life they usually are -- for reasons beyond the control of the endpoints' administrators. With a primitive "wg ping" it would be possible to write a userspace tool to opportunistically upgrade a peer to a more-preferred endpoint or fall back to a less-preferred endpoint when connectivity is lost. More complex policies are possible too, along with improvements on the wireguard-tools/contrib/nat-hole-punching tool. In terms of implementation, one possibility is to allow an ICMP socket to mark its outbound packets "hey wireguard, if you find yourself encrypting this packet, after doing so send the resulting encrypted packet [and MESSAGE_HANDSHAKE_INITIATION it might provoke] to $IP:$PORT regardless of wg_peer.endpoint." If the peer does not currently have a valid handshake (e.g. the timer just expired) then the ping will provoke a MESSAGE_HANDSHAKE_INITIATION, and the peer's MESSAGE_HANDSHAKE_RESPONSE will cause wg_socket_set_peer_endpoint_from_skb() to be called, which will update wg_peer.endpoint. It would be nice if there were a way to prevent this, but I don't see any easy way to accomplish it. - a
