A campus or hotel network where the browser works and every tunnel dies is not one problem, it is four stacked ones. The path may allow only TCP 443, it may demand an authenticated proxy, it may inspect the handshake, and it may simply forbid remote access by policy. Working them in order stops you from buying a new client to fix a network rule. The runbook below takes about ten minutes and ends with a written answer about which layer refused you.

Prove which layer refuses the connection

Do not start with the VPN client. Start with a plain HTTPS request to the same host and read the timing phases, because the phase that fails tells you which device is responsible:

curl -sS -o /dev/null -w 'connect=%{time_connect} tls=%{time_appconnect} code=%{http_code}\n' \
  --max-time 8 https://vpn.example.net/

No response and no connect time means TCP never completed, so a firewall, a proxy requirement or a wrong destination is in play. A connect time with no tls time means something in the middle accepted the connection and then stalled the handshake, which is what an inspecting proxy looks like from the client side.

Now inspect the certificate you actually receive. This is the fastest way to find out whether you are talking to the server or to a middlebox that re-signed the session:

openssl s_client -connect vpn.example.net:443 -servername vpn.example.net -brief </dev/null

Read the issuer line. Your own CA means you reached the service; a corporate or appliance issuer means a filter terminated the connection and is deciding what happens next. Record both outputs with a timestamp, since the same test an hour later on the guest network may give a different answer.

A proxy-aware client changes the first packet, not the policy

If the network requires CONNECT through an authenticated proxy, your VPN client has to be told about it, or it will try to open a socket to an address it cannot route. Test the proxy separately from the client, so a failure has one explanation:

https_proxy=http://proxy.example.edu:3128 curl -v -o /dev/null https://vpn.example.net/
sudo openvpn --config /etc/openvpn/corp.conf --proto tcp-client \
  --remote vpn.example.net 443 --verb 4

The first command proves the proxy will carry the destination. The second asks the client to use TCP on 443, which is the only transport most web-only paths will forward at all. If the first command succeeds and the second still fails, the proxy is not the obstacle.

Some clients read the operating system proxy instead of an override, and some read neither. Check the application's own documentation before assuming a system-wide setting applies. A client that resolves the endpoint through a resolver the proxy does not serve will also fail here, which is why a DNS change can look like a fix when it is only a detour.

Watch for the steering pattern while you are at it. A filtered network can answer a vendor's detection hostname with something of its own, which changes which proxy profile the client selects. Do not build a process around that quirk. It varies by site, it changes without notice, and it is not something you can support for anyone else.

Port 443 is reachable, not permitted

Wrapping a tunnel in TLS on 443 solves reachability and nothing else. A filter that checks the port will pass it; a filter that fingerprints the handshake will not, and encrypted client hello only hides the server name when both ends support it. Run the test and find out which kind of filter you are behind instead of hoping.

There is also a performance cost that people discover later. A reliable transport inside a reliable transport amplifies loss, because the inner stack retransmits segments the outer stack has already retransmitted. On a clean link nobody notices. On a congested campus wireless network the tunnel becomes unusable exactly when you need it, and the graph looks like packet loss even though nothing is being dropped on purpose.

UDP is usually the first casualty, and that is worth confirming rather than inferring. If WireGuard or default OpenVPN never completes a handshake while TCP 443 works, the network is dropping UDP, and no amount of key regeneration will change it:

sudo wg show
dig +short vpn.example.net
dig +short vpn.example.net @1.1.1.1

An empty handshake timestamp next to a peer that was working yesterday is the UDP answer. The two DNS queries answer a different question: if the local resolver and a public resolver disagree about the endpoint address, you are being steered and the transport argument is the wrong one.

Verify what actually left the machine

Client logs describe what the client believes. A capture describes what the network saw, and the difference between the two is where most of these cases are solved:

sudo tcpdump -ni any -c 20 'tcp port 443 and host 203.0.113.10'
sudo ss -tunp | grep -E ':(443|1194|51820)\b'

If you see SYN packets and no SYN-ACK, the block is upstream and the client is innocent. If you see a completed handshake to an address that is not the server's, you are talking to a proxy or an interceptor. If you see nothing at all, check that you captured on the right interface before concluding anything.

The socket listing catches a subtler case: a second tunnel already holding the default route. Two clients fighting over the routing table produce intermittent failures that look exactly like a blocked network, and the capture will show traffic leaving through an interface you did not expect.

Rollback, and the note worth keeping

Undo the changes in the reverse order you made them. Unset the proxy variables, stop the client you started by hand, and remove any route or resolver override you added:

unset https_proxy http_proxy
sudo systemctl stop openvpn-client@corp
sudo ip route show default

Leaving a hand-started client running is how a laptop ends up with a broken network on the next office visit. Proxy variables left in a shell profile break unrelated tools weeks later, and the person debugging them will not connect the two events.

Then write four lines: the network, the timestamp, the phase that failed, and the issuer you saw. A path that works on one campus and fails on the next is normal, and the next person needs to know whether the difference was the proxy, the resolver or the filter. If the answer is that the network forbids remote access, stop there and ask the administrator for the supported route rather than carrying a workaround into a policy you have not read.

Ingingo zihuye