A VPN inside TLS on port 443: how it works and when you need it
Wrapping a VPN tunnel in TLS on TCP port 443 makes it look like HTTPS, so it connects on networks that filter ports or protocols. How, and what it costs.
A VPN over TLS on port 443 takes an ordinary VPN tunnel and wraps every packet inside a TLS stream on TCP port 443, the port and protocol that HTTPS uses. To a network that filters by port, it is traffic to 443 and passes. To a network that filters by protocol shape, it is a TLS session with a valid certificate and passes. You need it on networks that drop UDP or block recognisable VPN protocols; on every other network it is slower than a plain UDP tunnel and should not be the first choice.
What "looks like HTTPS" means in practice
A network can decide what to let through in three ways, and each one is a layer the transport has to satisfy.
| Filter | What it checks | What the transport must do |
|---|---|---|
| By port | Whether the destination port is on an allowed list | Use TCP 443, which almost every network permits |
| By protocol shape | Whether the bytes look like TLS: a ClientHello, a server certificate, records | Run a real TLS handshake, not just something on port 443 |
| By certificate | Whether the server's certificate chains to a public authority | Present a publicly trusted certificate, for example from Let's Encrypt |
Meeting the first is trivial: any protocol can be told to listen on 443. Meeting the second requires the connection to actually begin with a TLS handshake, which is why simply running WireGuard's UDP packets over TCP 443 does not work on a protocol-aware network. Meeting the third means the VPN server needs a real hostname with a certificate that a browser would accept. A self-signed certificate, or none, is exactly the kind of oddity a filter is built to notice.
Once all three are satisfied, the connection is indistinguishable, from the outside, from a phone loading a website. What is inside the TLS stream is the VPN tunnel, and the network cannot see it. The post on why VPNs use port 443 gives the shorter version of this reasoning.
What goes inside
The tunnel inside the TLS stream can be any VPN protocol. OpenVPN in TCP mode is the classic example, since its control channel is already TLS. A more modern design keeps WireGuard as the tunnel and uses TLS purely as a carrier: each WireGuard packet is written as a length-prefixed record into the TLS stream, and the server unwraps it and hands it to a normal WireGuard endpoint. That preserves WireGuard's one-round-trip handshake, its fixed cryptography and its two-minute rekey, while gaining a transport that gets through. Those properties are worth keeping, and this design keeps them.
The traffic is encrypted twice, once by the tunnel and once by TLS. That is harmless to security and costs a little processing. What it does not do is add any privacy: the network could not read a plain WireGuard packet either. The point of the outer layer is entirely about the connection being allowed.
What it costs
Everything the TLS transport gains comes from running on TCP, and everything it loses comes from the same place.
- Stacked retransmission. The tunnel is a TCP stream carrying mostly TCP connections. When a packet is lost, both layers try to recover it, and the connection stalls in a way a UDP tunnel would not. The UDP vs TCP post explains the mechanism.
- Smaller packets. Each inner packet has to fit inside TLS, TCP and IP headers, so the tunnel's MTU drops to about 1280 bytes, compared with 1420 for WireGuard over UDP. 1280 is the minimum every IPv6 path must carry, which is why it is the safe figure. Smaller packets mean more of them for the same data, and a little more overhead. The MTU post covers what goes wrong when this figure is set badly.
- A slower start. A TLS handshake is one or two round trips before the VPN handshake even begins, so the connection takes longer to come up.
- No roaming for free. The TCP connection is tied to the phone's address. When you switch from Wi-Fi to mobile data, the stream has to be re-established, whereas WireGuard over UDP simply continues.
None of these make it a bad transport. They make it a fallback, worth the cost on a network that would otherwise not connect at all and not worth it anywhere else.
When you need it
You are on a network that filters ports or protocols if a plain VPN sends its handshake and gets nothing back, on every port it tries, while websites load normally in a browser. Hotel Wi-Fi, campus networks, office guest networks and some cafés behave this way, usually because someone configured the firewall to permit only web traffic. The post on Wi-Fi that blocks VPNs covers how to tell this apart from a captive portal or a dead server.
On such a network the sequence is: UDP tries fail within a few seconds each, the TLS transport on 443 connects, and the tunnel comes up with a smaller MTU and a slightly higher latency. When you leave the network, a good app tries UDP again first, because it is the transport you want whenever it is available.
Culvert VPN moves to its TLS-wrapped transport on TCP port 443 automatically after WireGuard over UDP gets no reply on several ports, and back to UDP on the next network where it works, without ever showing a protocol name; it is on Google Play.
Questions people also ask
Is a VPN over TLS more secure than a normal VPN?
No more and no less. The tunnel inside is encrypted the same way. The TLS layer is there to change how the connection looks to the network, not to add protection.
Why does the server need a real certificate?
Because an HTTPS server without a publicly trusted certificate is itself unusual. A certificate from a public authority such as Let's Encrypt makes the connection look like any other website.
Why not use this all the time?
It runs over TCP, so it inherits stacked retransmission and a smaller packet size. On a network that allows UDP it is strictly slower than WireGuard, so it should be the fallback.