Two home routers, no forwarded ports, and a VPN that sometimes connects anyway. UDP permits that, because a firewall will admit a packet it can match against a flow the machine already started. It is a conditional trick rather than a feature, and the conditions are easy to state once you know what the firewall is comparing. They are also the reason identical profiles behave differently on different networks.

The comparison a firewall makes

Every outbound datagram creates a short-lived entry: source address, source port, destination address, destination port. Anything arriving that matches the entry is treated as an answer and let through. Nothing about inbound rules enters into it.

So the question is not whether the firewall allows the peer in. It is whether the peer's packet looks like the reply the entry is waiting for. Change one field of that four-part tuple and the packet becomes a stranger. That is why a working setup can break when only the port number changes, and why the same port can work on one router and fail on the next.

Fix the local source port, and the same number appears on both sides of the exchange. That is the entire mechanism, and it explains why the trick is fragile rather than mysterious.

Pinning one port at each end

OpenVPN's default UDP port is 1194, and lport sets the source port it sends from. Pin both peers and each one's outbound tuple points at a port the other is listening on:

# peer A
lport 1194
remote 198.51.100.20 1194
# peer B
lport 1194
remote 203.0.113.10 1194

That works only while no router between them rewrites the source port. When packets appear in a capture but no tunnel comes up, the rewrite is the first suspect.

Where the tuple stops matching

A NAT that maps per destination hands each peer a different external port. The address your peer was told to use is not the address that reaches it, so the incoming packet matches nothing and is discarded silently.

Carrier-grade translation, stacked NAT and port randomisation all end the same way. So does any middlebox that rewrites ports while leaving addresses alone.

Stream transports are worse off. A TCP handshake is tracked step by step, so a TCP-based VPN cannot be punched this way at all and needs a listener somewhere on the path.

One side usually fails first

In practice the two networks rarely behave alike. One router may hand out a predictable mapping while the other hands out per-destination ports, and the result is a configuration that works between two homes and fails from a mobile network. Reports that contradict each other are usually describing two different pairs of routers. Neither author is wrong, and neither result generalises.

Find out which side dropped the packet before touching the profiles. Captures at both ends settle it in one attempt: datagrams that leave A and never reach B mean the flow was rewritten in transit, while datagrams that arrive at B with no answer coming back mean the firewall did not accept them as related.

Two peers with public IPv6 addresses sidestep the whole problem. With no translation there is nothing to match, so a firewall rule naming the peers is enough and the design stops depending on router behaviour.

When to stop trying

A host with a public address is the dependable answer. It can terminate the tunnel for both peers, or simply help them discover each other's current external address, and both arrangements work whatever the NATs do. A managed overlay provides the same coordination if policy permits it.

What none of these need is a disabled firewall. Turning protection off to win the direct connection discards the reason the direct attempt was attractive, and it leaves the machine open for the duration of the test.

Try the direct arrangement first, then record what you saw. The NAT behaviour and the capture that showed it are worth more than the port pair you ended up using, because the next network will be different. The OpenVPN 2.6 manual documents lport and the remote options this depends on.

Artaigilean co-cheangailte