Two sites on cellular uplinks have the same problem in both directions: neither can accept an unsolicited IPv4 connection, so neither can play the server in a direct tunnel. The architecture that works puts a reachable third party in the middle, with each site dialling outward and the middle forwarding only the traffic you approve. That middle can be a router you operate or a product that introduces peers, and those are not the same thing. The steps below are ordered so that each one produces evidence before the next depends on it.

Neither site can be dialled, so both must dial out

Confirm the constraint before designing around it. If the carrier hands the WAN interface a private address, no port forward on the site's own router will make it reachable, because the translation happens upstream. A public IPv6 address can exist on the same uplink and change the design entirely, which is why the check covers both families. Write the answer down per site, because the two rarely have identical constraints even when they share a carrier.

The ordinary cellular case looks like an address from the carrier's translated range with a default route through it. That is not a fault to be repaired; it is the reason the hub exists. What you are looking for is any address a third party can reach without the site having spoken first.

Two commands answer the addressing question for the site you are standing in front of. Run them on the site router, not on a laptop behind it:

ip -4 addr show scope global
ip -6 addr show scope global

Who introduces peers, and who carries the packets

Introduction and transport are separate jobs that products often bundle without making the line visible. A rendezvous mechanism helps two peers find a candidate path; a relay carries their packets when no direct path exists. Buying a service that introduces peers does not give you a router, and that difference decides whether the design needs a hub at all.

Traversal has its own vocabulary, and the words describe roles rather than guarantees. The ICE specification describes candidates and connectivity checks, STUN describes one way to learn about address translation, and TURN describes relayed transport for applications that implement it. None of those mechanisms appears in a conventional gateway because you pointed it at a discovery address. Verify traversal as a product capability, and assume relay until a test shows otherwise.

One route per site, owned by a peer

The hub needs one tunnel per site, a distinct LAN prefix behind each, and a route for each prefix that names its owner. In the example the hub is 10.61.0.1, site A is 10.61.0.11 with LAN 10.60.10.0/24, and site B is 10.61.0.12 with LAN 10.60.20.0/24. Each route below points at the peer that owns the prefix rather than at the tunnel interface:

ip route add 10.60.10.0/24 via 10.61.0.11 dev wg0
ip route add 10.60.20.0/24 via 10.61.0.12 dev wg0
sysctl net.ipv4.ip_forward
ip route get 10.60.20.55 from 10.60.10.77

Forwarding has to be enabled, or the packets stop at the hub with no error that points at the cause. The last command answers the real question, because it asks which path a packet would take from site A's LAN to site B's LAN with the source included in the lookup. Treat a lookup that names the tunnel interface as evidence and one that falls back to the default route as a missing route rather than a mystery. Then restrict transit deliberately, since a hub that forwards between every peer turns two sites into a flat network and the access policy you thought you had stops applying.

Decide where encryption ends as well. When the hub holds both tunnel terminations, the operator of that machine and its workload join the trust and availability model, and its bandwidth becomes part of the path.

Keep each mapping alive through the carrier

Each site initiates its own tunnel, and each has to keep the translation mapping alive or the carrier forgets it. A keepalive on the initiating side preserves that mapping between handshakes. Scope the allowed prefixes to the hub address and the remote LAN, so a compromised peer cannot claim a prefix it does not own:

[Peer]
PublicKey = <hub public key>
Endpoint = 192.0.2.10:51820
AllowedIPs = 10.61.0.1/32, 10.60.20.0/24
PersistentKeepalive = 25

Mirror the block on the other site with its own remote prefix, and resist the urge to allow the whole tunnel range. A handshake that stops and resumes from a new source port is the signature of an expired mapping, and the handshake timestamps are the evidence that it happened. An interval shorter than the carrier's timeout prevents the expiry instead of repairing it afterwards. When the carrier changes its translation behaviour, expect those timings to change with it.

Prove both directions, then prove recovery

Verification is directional, so a ping from A to B proves half the design and nothing about the return route. Check the reply path with the same source-aware lookup on the hub, then repeat the test from the other side. Fresh handshakes belong in the evidence too, because a tunnel idle for an hour may be testing an old mapping:

wg show wg0 latest-handshakes
ping -c 3 10.60.20.55
traceroute -n 10.60.20.55

Then test the failure you expect rather than the success you want. Restart one site's uplink and confirm the tunnel returns without a human touching either end, because a design that needs an operator after every carrier change is unfinished. Record the primary path, the IPv6 alternative when one exists, and the behaviour when the hub is unavailable. The hub is now part of your availability model, so write that down instead of discovering it during an outage.

Akụkọ ndị metụtara ya