The tunnel comes up on mobile data and then sits at connecting at home, with the same profile, the same peer key and no configuration change in between. The difference is the trip: a request from inside the LAN to the router's public address is not the same journey as a request that arrives from the internet. Most home gateways either do not implement the return path or implement it only for certain protocols. That makes the symptom look like a broken key when nothing about the key has moved. Establish which path failed before touching a key, a port forward or a client profile.

One address, two different paths

From outside, a packet reaches the router's public address and a port-forward rule hands it to the WireGuard listener on the internal host. From inside, the client dials the same public address, so the packet leaves the client, arrives at the router, and has to be turned back towards the LAN. That return turn is where the two paths diverge, because the router must translate a flow that both leaves and re-enters the same interface. Many implementations drop it instead of translating it, and the client then waits for a handshake that was never sent.

The behaviour is usually called NAT loopback or hairpinning, and it belongs to the router rather than to WireGuard; RFC 4787 sets out the translation cases in which a gateway may or may not support it. WireGuard itself holds no opinion about the path, because it only sees packets that reach its interface. When the router drops the flow, the daemon never receives anything, the client reports a handshake timeout, and the server log stays empty. An empty log is therefore a clue about where the packet stopped, not evidence that the server is down. It is also why a reinstall changes nothing.

The converse matters too: a server log that shows a handshake attempt from the LAN address proves the packet arrived and the path is fine, which moves the investigation to keys and allowed addresses. Read the log for what it proves rather than for what you hoped to see.

Reproduce it before you change anything

Test from an authorised external network with the same device and the same profile, then repeat the test inside the LAN without editing anything. A completed handshake outside and a client that never leaves the device inside reproduces the condition instead of guessing at it. Both attempts have to use the same profile, or the comparison proves nothing.

Then look at what the endpoint name resolves to for this device. These three commands also show which address the client actually dialled:

wg show wg0 endpoints
dig +short vpn.example.net A
resolvectl query vpn.example.net

The first command reports the endpoint the interface is currently using, and the other two show what the name resolves to on this machine. A client dialling a public address while sitting on the same network as the server is exercising the hairpin path. A client dialling the LAN address is not, and a failure there belongs to a different investigation. That distinction decides whether the next section applies at all.

Supported ways to reach a nearby server

The cleanest arrangement is a split-horizon answer: the public name resolves to the public address for the internet and to the server's LAN address for clients inside. The profile keeps one endpoint name and the resolver picks the path. That needs control of the internal DNS answer, which a home router usually offers and an organisation can arrange deliberately. Without that control, the remaining choices are a router feature or a second profile.

The router feature is reflection: the gateway translates the internal-to-public flow and sends it back inside. Where it works it needs no client change, and where it does not work no client setting will rescue it. Test it by watching the server log during an internal attempt rather than by reading the router's feature list.

Editing the profile to a private address is a diagnostic, not a design. It proves the server answers on the LAN, and it breaks the same profile the moment the laptop leaves the house.

ApproachWhat it depends onWhere it fails
Split-horizon nameControl of the internal DNS answerClients that resolve through a server outside the zone
Router reflectionGateway support for hairpin translationRouters that drop the flow silently
Private address in the profileNothing beyond the LANEvery network except the one at home

Keep the profile usable away from home

Whichever path you choose, leave the identity check alone. The endpoint address is not the peer identity, and a change of address never justifies accepting an unrelated public key that happens to answer. WireGuard authenticates by key, so a wrong host fails the handshake rather than granting access to something unexpected.

If the public address moves, dynamic DNS is what keeps the name useful, and the client's refresh behaviour decides how quickly the change lands. Test that from outside after an address change, because the LAN case cannot validate it. Watch for a resolver that caches the old answer past the record's lifetime. A name that still points at the previous address looks exactly like a server that went down.

Write down which name the profile uses and what it resolves to on each side of the boundary. A profile that depends on a router feature nobody recorded is a support call waiting for the next firmware update. The note is also what tells the next person whether an internal failure is the known hairpin case or something new.

Makomi ya ndenge moko