The tunnel connects from a home line and stalls on a hotel or office network, and moving the server to port 443 changed nothing. That result is common enough to have a shape: the port was the easy part, and the rest of the decision belongs to whatever sits between the client and the server. Two questions settle most cases, and neither of them is about ciphers. Does the network accept a TLS handshake to that address, and does the client keep a route to its own wrapper while the tunnel is up?

The handshake gives away more than the number

A native VPN listener on TCP 443 speaks its own protocol from the first packet. A ClientHello has a version field, a random value and an extension list, and a device that reads a few hundred bytes can tell the difference without decrypting anything. Port numbers are cheap to satisfy, and protocol shape is what the filter is actually checking. Rules are usually written per protocol as well, so a policy that inspects TLS says nothing about UDP.

A transparent proxy that insists on a valid TLS session drops the connection during setup, often after the TCP handshake completes. That detail matters later, because it means the client log stops after the socket is established.

Wrapping the stream creates two failure points

A TLS wrapper such as stunnel restores the expected shape: the client connects to a local listener, the wrapper opens a real TLS session to the server on 443, and a second wrapper on the server forwards the decrypted bytes to the VPN daemon. The outer session now looks like any other HTTPS connection. The VPN daemon on the server should listen on loopback only, because nothing outside the wrapper needs to reach it.

Three separate things must line up for that design. The client profile points at the local listener, the server certificate matches the name the client verifies, and the server-side forward targets the port the daemon really uses. Get any one of them wrong and the connection dies before the VPN layer is reached. A certificate mismatch then appears as a wrapper error rather than a VPN error, which is why both logs are worth reading side by side.

The route to the wrapper is the trap

Once the tunnel comes up, the default route points into it, and the outer TLS session needs a path that does not enter the tunnel it is carrying. A plain VPN client protects the address it dials; a wrapped client dials its own loopback, so the wrapper's destination address is invisible to that protection.

sudo ip route add 198.51.100.20 via 192.168.0.1
sudo openvpn --config client.ovpn
sudo ip route del 198.51.100.20

The exact addresses are yours to fill in, and the route has to exist for the whole life of the connection, not just at start-up. A small wrapper script that adds the route before the client and removes it after is more dependable than a remembered command.

On Android, the equivalent of that exception is a per-app setting: exclude the wrapper application from the tunnel so its own traffic leaves through the mobile connection. Without the exclusion the wrapper is routed into the tunnel it is trying to build, and the reconnect loop looks like a server problem.

Read the timing before changing anything

A session that dies after the same interval every time is a policy signature rather than a cryptographic failure, and long-lived flow limits produce exactly that pattern. A connection that resets immediately after the handshake suggests a proxy that did not like the certificate chain.

Compare the certificate issuer of an ordinary HTTPS site from both networks. If the issuer differs on the restricted network, something is terminating TLS in the middle, and no wrapper will survive that interception unchanged. The same comparison tells you whether the block targets your server name or every TLS session at that address.

Write the observed behaviour down: how long the session lasted, whether the socket opened, whether the wrapper logged a handshake. Each of those narrows the next test.

Test one variable at a time

Check UDP first, because some networks drop it entirely and a UDP failure tells you nothing about 443. Then try TCP 443 without the wrapper, then the wrapper on 443. Read the client log at each step and stop as soon as the behaviour changes.

Change one element per attempt. A new port, a new wrapper and a new cipher in the same run leave you unable to say which of the three mattered.

Ebitabo ebifaananyi