← back to blog

QUIC and HTTP/3 traffic that never touches your proxy

quic http3 proxy-leaks udp

QUIC and HTTP/3 traffic that never touches your proxy

I had a price monitoring job running through a socket level redirector for months, because pointing one thing at a proxy was easier than configuring every tool separately. It looked healthy the whole time. Then one of its targets started handing the job a different page than the same target handed a browser going through the same line.

The tcp requests were arriving from Singapore. The http3 requests were arriving from the box itself. Nothing errored, nothing retried, nothing showed up in a log, and I only caught it because a number downstream looked strange weeks later.

That is the character of this failure. It succeeds, from the wrong address, and waits for you to notice on your own.

Every proxy you have ever bought is a TCP product

An http proxy using the CONNECT method opens a tcp connection on your behalf and shovels bytes through it. SOCKS5 negotiates first, then does the same thing. In both cases a client hands over a destination and the proxy opens a stream, and a stream in this business has always meant tcp. The assumption is so old that nobody bothers to state it. It sits under every proxy dashboard and every library that takes a proxies argument.

HTTP/3 stopped using tcp. It runs on QUIC, and QUIC runs on udp. In practice that means udp on port 443, to the same servers, carrying the same requests, in datagrams instead of a stream.

So when your browser decides to speak HTTP/3 to a site, it produces packets your proxy has no mechanism to carry. What happens next depends on what sits between the browser and the network.

The timing is what stings

Your browser has no idea a site speaks HTTP/3 until it asks. The first connection to a new origin goes out the ordinary way, over tcp, through your proxy, exactly as you intended. The response comes back with a header attached that says, roughly, I am also reachable over HTTP/3, on this port, for the next while.

The browser writes that down. And it keeps it.

The next time you touch that origin, it tries udp first.

Sit with the shape that produces. The first request of the session left from Singapore. Everything after it left from the machine on your desk. Same browser, same cookie jar, same logged in account, two different addresses arriving in the exact order that makes them trivial to connect.

A plain leak looks like somebody who forgot a setting. This looks like an account that logged in from Singapore and then, moments later, from somewhere else entirely, which is precisely the pattern fraud systems were built to notice. You gave away more than your location. You handed over the mapping between the address you were renting and the address you were hiding.

Who is actually exposed

There is a scaremongering version of this story and I have no interest in selling it.

Type a proxy into Chrome’s own proxy setting and Chrome switches QUIC off for that traffic. It knows the proxy cannot carry it, so it stops trying. Firefox behaves the same way. The browser vendors thought this through properly. If your setup really is a browser with a proxy in the browser’s own setting, you are probably fine, and the checks below will prove it in a couple of minutes.

Few real setups look like that.

The leaky family is everything where the proxying happens underneath the browser. A socket level hook that catches outbound connect calls and redirects them. A local listener that grabs tcp and forwards it on. A firewall rule that transparently redirects traffic to a port on the same box. Those tools grew up in a tcp world, most of them leave udp completely alone, and the browser above them has no idea it is being proxied. Nothing ever tells it to switch QUIC off, so it never does.

PAC files are the second family. One that returns direct for certain hosts, or falls back to direct when the proxy looks unreachable, is doing exactly what somebody told it to do, and the traffic it releases is unproxied.

Then there is everything on the machine that is not your browser. A desktop app built on a browser engine ships its own network stack and its own opinion about QUIC. The operating system does its own talking. A phone or an emulator with a proxy set on the wifi connection is the worst of the group, because on Android that setting is closer to a suggestion and plenty of apps ignore it outright.

One narrowing fact. This only matters on sites that speak HTTP/3, and plenty of the internet still does not. The catch is that the big content networks do, which means the targets people actually care about are exactly the ones where it fires.

Proving it in about ten minutes

Three checks, cheapest first.

Open developer tools on the misbehaving page and find the network panel. There is a protocol column, switched off by default. Right click the column headers, tick it on, then reload. The values are h2, h3, or the older 1.1. Anything reading h3 went out over udp. If your proxy carries tcp only, that request never touched it, and whatever came back arrived at your real address.

That column is usually the entire investigation.

The second check runs underneath the browser. Look at whether udp on port 443 is leaving the machine at all while you browse. A socket listing on the box will show open udp endpoints, and a packet capture filtered to that port will show the datagrams themselves. If your setup works the way you believe it does, that traffic should be absent. If it flows while you load the site you are worried about, you have your answer without trusting any tool’s opinion of itself.

The third is a comparison. Run the same request with curl through the same proxy. curl speaks tcp. If curl comes back reporting the Singapore address while the browser is still being treated like your home machine, the difference between the two is the protocol, because you held everything else constant.

And the check everybody reaches for is the one that will not help. An ip check page is close to useless here. Those pages are small and plain, and it is usually the first thing you have ever asked that origin for, so the request goes over tcp, through your proxy, and reports the proxy address correctly. It passes cleanly while the site that matters keeps failing. A standard leak routine has the same blind spot. It catches dns, it catches webrtc, and its checker answers you over tcp, confirming the exact request that was never in question.

Switching it off

The obvious fix is to turn QUIC off in the browser. Chrome has a flag for it and a policy for managed installs. Firefox has a preference that disables HTTP/3. An antidetect browser might expose it in the profile settings, and if it does not, you are on the second fix whether you like it or not.

One thing people miss. The browser remembers which origins advertised HTTP/3, and that memory lives in the profile. Switching the setting off stops new attempts without reliably clearing what is already written down. Do it on a fresh profile, or clear the browser’s stored network state afterwards, and then confirm with the protocol column rather than assuming.

The fix I actually trust is blunter. Block outbound udp on port 443 at the operating system.

This works because it depends on nothing honouring anything. Every piece of software on that machine tries QUIC, gets nowhere, and falls back to tcp, which is the thing your proxy carries. Browsers do that fallback automatically and quietly. They were built to, because plenty of corporate and mobile networks block udp 443 for their own reasons and the web still has to work.

Reject the packets rather than dropping them. A silently dropped packet leaves the application firing its handshake into nothing and waiting out a timer before it concedes, and you pay that wait on every new origin you visit. A rejected packet gets an immediate unreachable back, and the fallback to tcp happens straight away. Identical protection, far less waiting.

Be specific about the port while you are in there. Blocking udp wholesale is a bad afternoon, because dns lives on udp and so does plenty else on that box.

The SOCKS5 suggestion

Somebody always suggests SOCKS5, because SOCKS5 can carry udp. The specification does contain a command for it, udp associate, and it has been sitting there for decades.

Almost nothing implements it. Most proxy servers never built it, and mine is one of them. Browsers do not use it for QUIC under any circumstances, so a proxy that supported it flawlessly would change nothing about what your browser does. The design also sits badly on a mobile line, because the udp relay is a separate address and port the client has to keep reaching, which is awkward when the exit lives behind carrier nat.

There is a proper standards answer for tunnelling udp through a proxy. It is written down and it works. You will struggle to find a commercial provider in this market who speaks it, and I do not.

The half I cannot fix

This is a client side problem from end to end. Those datagrams never arrive at my gateway. There is nothing on my side to see, nothing to log, nothing to repair, because from where I sit that traffic does not exist. I can tell you your tcp came from Singapore. I have no visibility into the requests that did not.

So when a provider tells you their proxy prevents QUIC leaks, ask which packet they intercepted. Unless the answer is a client they wrote and you installed on your own machine, the claim has nowhere to stand.

A customer once sent me two screenshots in the same message. The first was an ip check page showing a Singapore mobile address on Singtel, the exact line he was renting from me. The second was an email from a platform asking him to confirm a login from the city where he actually lives. Nothing was misconfigured. The proxy was set, the credentials were right, the leak check passed, and the one site he cared about was still seeing his home address in the same session.

The protocol column would have told him in one glance.

If you want Singapore mobile lines from somebody who will tell you plainly which half of a problem is his, real Singapore carrier SIMs are what I run.

Get new guides and videos first — join the Telegram channel.

ready to try Singapore mobile proxies?

24-hour free trial. no credit card required.

start free trial
message me on telegram