top | item 30317218

HTTP/3: Everything you need to know about the next-generation web protocol

220 points| homarp | 4 years ago |portswigger.net | reply

156 comments

order
[+] posix86|4 years ago|reply
I'm surprised that a major feature of QUIC isn't mentioned at all: Identification of session solely through connection IDs, unrelated to IP addresses. When you travel & change network, from WIFI to cellular, from one cellular tower to another, your phone / laptop often changes IP address, causing the TCP sessions to be directed into the void. Meaning, they wait until they timeout, then restart with new handshake. QUIC uses connection IDs to identify sessions independent of IP addresses, so a single packet from the new IP is enough to make the server switch to sending to the new IP without having to establish a new session at all. This is again mainly an issue for unstable connections when browsing (and fast travels in old cellular networks), and even then not a major problem, but still, it's pretty cool.
[+] p_l|4 years ago|reply
Funnily enough, technically ISO TP4 did the same (as you could in theory change the NSAPs - ISO network addresses - and keep the same reference numbers (which are used for matching connections)
[+] bogomipz|4 years ago|reply
Would this be the equivalent of MPTC(multi-path TCP) in QUIC then? Can it be used for bandwidth aggregation as well?
[+] nikita2206|4 years ago|reply
I think it’s because it’s a network level session which isn’t very useful for the app level. Those connections are still ephemeral enough that you wouldn’t be able to treat their IDs as application’s session ID, you’d simply get randomly interrupted sessions otherwise.
[+] linkdd|4 years ago|reply
When HTTP/2 came out, I was wondering how long it would take for the billions of websites/APIs/webservices/... out there to migrate from HTTP/1.1

HTTP/2 came out in 2014, and since then I still haven't seen it used in production in the jobs I worked at.

Now, I wonder again, will HTTP/4 be released before we migrate to HTTP/3 ?

The real question here is, what are the arguments in favor of a migration? When starting a new web project, should you really consider anything else than HTTP/1.1?

[+] tashoecraft|4 years ago|reply
I just recently got my company to switch over to http2 and halved our load time across the board. It might go down as the greatest improvement in customer experience for the simplest action I’ll ever do.
[+] jakub_g|4 years ago|reply
If your website has a lot of small files served, H2 and H3 offer dramatic improvements: browser says "gimme those 100 files" and server sends them all over a single connection in a streaming fashion.

Whereas with H1 browser opens up to 6 connections, downloads 1 file on each, then once the response comes it tells "ok now gimme another file" etc. (Another RTT until it comes back). That's many round-trips saved.

This is probably mostly useful when downloading many small images. It can be also useful for splitting JS into smaller bundles to favor cache hits for returning visitors. (An be also useful to serve ES modules without or with minimal bundling; however in practice bundling is still useful given that modern JS apps have 100s/1000s of files and small files overhead still matters at such numbers).

[+] eyelidlessness|4 years ago|reply
It really depends on your deployment, but a lot of us have adopted HTTP/2 without lifting a finger, or with routine dependency updates. It’s possible (probable) that those migrations have not resulted in optimal usage, but neither have specially tailored migrations (see: the sad slow death of Server Push).

As far as whether you should consider migrating, it’s worth doing a quick spike to determine level of effort. I expect the number of use cars which:

- can’t trivially update

- aren’t directly providing HTTP functionality to users who expect that

… is a rather small niche.

[+] jillesvangurp|4 years ago|reply
Anything using Google, AWS, or load balancers from other major cloud providers will likely end up being early adopters for this stuff. In our case, since we were targeting mobile, we actually used nginx with SPDY support before HTTP/2 was even stabilized. It wasn't that hard. We just had to get a recent build and fiddle with a few lines of configuration. That was 2014. HTTP/2 standardization came later, as I recall.

We already have an HTTP/2 and HTTP/3 capable load balancer because we host on GCP these days. Mostly this stuff just happens without intervention. HTTP/1.1 is a fallback for people with crappy network infrastructure.

If you are starting a web project, you should probably use one of the major cloud providers unless you have a good reason not to. You'll use this stuff by default mostly unless you explicitly turn this off. But why would you want to do that?

If you are managing your own load balancers; consider using something modern/up to date that would be able to support this. Also from a security point of view probably not something you should skip. And if you are using something modern, it shouldn't be that hard to turn on the feature.

If you manage some legacy stuff that just doesn't matter; don't bother of course. HTTP 1.1 will continue working just fine. If you have mobile users though, you are not doing them any favors by making things needlessly slow and this would probably be an easy upgrade.

[+] tialaramex|4 years ago|reply
> since then I still haven't seen it used in production in the jobs I worked at

How do you know? Most of the Alexa top 100k web sites are HTTP/2 but I suspect a great many of the people working on those web sites have no idea HTTP/2 exists, it simply has no impact on their work. It probably has no impact on your work.

[+] josephcsible|4 years ago|reply
> When starting a new web project, should you really consider anything else than HTTP/1.1?

This makes it sound like the HTTP version you use is as major of a decision as the programming language you use, but can't you change HTTP versions basically by just flipping a switch?

[+] jiggawatts|4 years ago|reply
That’s because HTTP/2 broke every capability that was not used by Google.

NTLM auth… broken.

Client cert auth (mTLS)… broken.

Etc…

Monopolies are dangerous because they can accidentally lock out their competition without even trying.

They just have to focus on their own problems and ignore other people’s problems… because they can.

[+] xyzzy_plugh|4 years ago|reply
If you use Go or gRPC, then you're probably using HTTP/2. I've seen both used, at least somewhat, by every company I've done work for in the last 5-6 years.
[+] happymellon|4 years ago|reply
We will switch about 6 months after adoption of IP6 is complete.
[+] aseipp|4 years ago|reply
A big thing is that you may be using HTTP/2 or HTTP/3 already if you use something that terminates HTTP for you. This doesn't have to be Cloudflare or whatever; if you run Nginx in front of your Rails server, you can just have Nginx handle HTTP/2 for you. Many deployments or services like AWS, Heroku, S3, etc already enable HTTP/2 for you and it's transparent on the client end.

The widespread deployment of caching utilities and other frontend application middleware was, in a paradoxical way, a huge boon that lead to easy success for HTTP/2 (and now /3) while making it appear a bit bland to everyone else. "Nobody uses this, right? I mean, I've never changed anything." You weren't supposed to! For many purposes this is intended: service providers, operational admins etc can largely tweak this all independently at the caching service layer, for instance. Taken together it's mostly just "free performance" for the case of a user who has a reasonably reliable network.

Now, don't get me wrong, you need to understand caching and the HTTP connection lifecycle. There are aspects of newer HTTP versions that do impact the development experience. For example if you're sure you're using HTTP/2, you can rely on multiplexing. That means that, for instance, if your user has a dashboard with many panels, and each panel is doing independent requests to get metrics data (like Grafana, for instance), then all of those HTTP requests for data happen over 1 TCP connection. If you had to use many connections, you'd either have to throttle/serialize updates, use pipelining, or it might not work at all since the browser will refuse to open too many at once. But you can rely on this working with HTTP/2. If you rely on multiplexing, the penalty of having many small files on a single domain is much smaller. So those user avatars hosted on mybusiness-static-content.net will load much faster for all users too. That's just free performance on the table. But you have to design with it in mind.

So to answer your question: why should you migrate? Well, in general the answer is simple: better performance and better security (HTTP/2 and HTTP/3 both mandate TLS, for example), and HTTP/3 handles flaky mobile connections much better than either v1 or v2. That might really help for something like an API endpoint that mobile device clients access, for instance.

If you start a new project, should you consider anything except HTTP/1.1? Yes! Because HTTP/2 and HTTP/3 are here to stay, so it's not like you're betting the farm on something untested. You do need to consider client library availability; you can't get away with a half-baked "HTTP/2" implementation as easily as you could with HTTP/1.1 (this is the dark side of people who complain about binary-vs-text formats: it was very easy to get HTTP/1.1 very wrong). But they have tangible benefits for end users, and, taken into consideration, can help you do some stuff you couldn't before. Ignoring any claims it's a sign of website bloat, "download a lot of small files" is actually a legitimate, huge use case you couldn't do efficiently before in the browser or otherwise! Some non-browser workloads I've had see incredible performance improvement just from this alone. And if you're writing server software? Well, a good reason is "because it's easy to deploy". You might only need to change a configuration in your existing terminator.

Will there be an HTTP/4? I guess nothing is impossible here but I wouldn't bet on it. HTTP/2 was the big change. HTTP/3 was a "big" change not for HTTP, but because fixing HOL blocking at the TCP layer can only be done by, well, not using TCP! It's otherwise the exact same thing you know already, just in binary form, over a different transport stream. There could of course be other things down the line, but it seems like if anything continues to evolve, it will be QUIC itself, and less-so for HTTP.

[+] throw0101a|4 years ago|reply
> HTTP/3 runs over QUIC – an encrypted general-purpose transport protocol that multiplexes multiple streams of data on a single connection.

Kind of sucks that SCTP, which also allows for multiplexing, never caught on for general use—probably because lack of support in various mid-network network boxen.

I guess we're generally stuck with tunnelling everything over HTTP (TCP and UDP) going forward. Every other kind of protocol implementation is out of the question because of NAT and various proxies.

[+] jrockway|4 years ago|reply
I feel like there is still a lot to learn. I tried rolling out HTTP/3 for jrock.us. It works in Firefox but not Chrome. On https://h3.jrock.us/, I serve the header:

    alt-svc: h3="nodes.jrock.us:31313"; ma=300, h3-29="nodes.jrock.us:31313"; ma=300
Chrome will not request subsequent resources with HTTP/3. Firefox will.

Obviously I am using a super-weird setup. I'm not using port 443 since I use managed Kubernetes which has a nodePort range that doesn't include 443. Then, h3.jrock.us is a CNAME for public-ingress.jrock.us which is an A record for 206.189.254.193. nodes.jrock.us is an A record that is a list of all nodes in my cluster. (This is because DigtialOcean doesn't support UDP load balancing, and I don't want to run my own load balancer, though I probably should. I am also missing out on IPv6 support, which annoys me greatly.) Everything is handled by Envoy; any load balancing is at the TCP level (load balancer) or UDP level (Kubernetes service).

I can't see anything in the standards that should prevent this from working, but it is indeed prevented from working. Sigh! Guess I should just run my own fleet of load balancers.

(Oh, ya know what, I'll interject another piece of annoyance here. I don't really want to use this pattern for non-test traffic, since there is some latency between nodes becoming unavailable and DNS caches noticing that. So if I roll all of my nodes, my website will break through the nodes.jrock.us route in that case. Even if I only roll one, browsers don't really know that they should fall back to another A record. This forces people to do load balancing at the IP layer, instead of at the application layer, which is really annoying. I wish there was a protocol where I could specify retry policies at the DNS layer. So you'd look up "jrock.us", get A 1.2.3.1, 1.2.3.2, 1.2.3.4, and "hey, if any of those fail to connect in 1 second, try the next and use that for 60 seconds". Each browser appears to do their own thing, and in-cluster I have a TON more control with things like xDS.)

[+] smt88|4 years ago|reply
Is this just a static site? Why on earth have you engineered it this way? You could pay like $5/mo. for static hosting and do none of this. The load balancing part is even more surprising to me because even fairly large sites typically don't need horizontal scaling unless they have uptime concerns.
[+] javajosh|4 years ago|reply
Yikes! I don't think I would play with a new HTTP version with such a setup. I would want to keep things as simple as possible, and write the simplest port-binding daemon I could in whatever language I liked best, and invoke it by hand. Test locally then on your local subnet, then public test on a $5/mo Ubuntu VPS. At that point I feel like I'd be ready to start thinking about testing on your setup. :)
[+] sleepydog|4 years ago|reply
> The protocol utilizes space congestion control over User Datagram Protocol (UDP).

I'm assuming they meant "user space congestion control" ? Even so, there's nothing about the protocol that says congestion control has to occur in user space.

[+] detaro|4 years ago|reply
But unless you push QUIC in the kernel, which afaik nobody is really doing yet, it will be. And it's not necessarily seen as a bad thing - opinions about that generally depend on how you think about apps "knowing better" than the OS.
[+] tyingq|4 years ago|reply
I wonder if the various corporate MITM nanny gateways and firewalls will keep up with this. And not just the manufacturers, but the device owners that don't keep them up to date.

I know Chrome had to implement a race between tcp and quic to detect various forms of broken firewalls, content filtering devices, etc. Maybe it would be better just to let things break and force the issue?

[+] userbinator|4 years ago|reply
I personally run a MITM proxy and force everything on the network through it.

If you can't inpect --- and alter --- what your devices are sending and receiving, it's not yours.

Big Tech seems to be on a race to own the Internet through increasing complexity and "upgrade treadmilling", and I block everything except HTTP 1.1 and 1.0 as a form of protest.

[+] sgift|4 years ago|reply
> Maybe it would be better just to let things break and force the issue?

I think it would be better, but unfortunately it won't happen. Too much money riding on it. I still hope newer versions of http continue to be designed to be more resistant against these garbage tools.

[+] FridgeSeal|4 years ago|reply
I'm really interested to know how far we could push performance, encryption/security, features, etc if we didn't care about legacy systems or breaking current setups.

What are we missing out on, because of the refusal to let go of pointless legacy systems?

[+] kmonsen|4 years ago|reply
I helped out with implementing quick in chrome, letting things break was never an option that was considered.
[+] elchief|4 years ago|reply
I was scraping an HTTP/2 site the other day, and discovered that Python requests library does not support it :S

HTTPX and Hyper didn't work either (probably due to ALPN?)

Had to call Curl from Python to make it work

[+] tyingq|4 years ago|reply
The bundled urllib doesn't even support HTTP/1.1 properly. It sends "Connection: close" and uses a connection-per-request model.

I suppose since it's hard to scrape anything without a headless browser these days, the http[s] scraping libraries are stagnated.

[+] samwillis|4 years ago|reply
Slight aside but in many ways I wish HTTP2 had been closer to John Graham-Cummings suggestion here:

“Speeding up HTTP with minimal protocol changes”

https://blog.jgc.org/2012/12/speeding-up-http-with-minimal-p...

It’s basically HTTP2s out of order pipelining but implemented as a simple extension to HTTP1.1 text protocol.

I think it would have been nice to maintain and improve the text protocol in that way.

Previous discussions:

2012: https://news.ycombinator.com/item?id=4931837

2013: https://news.ycombinator.com/item?id=6012660

[+] minus7|4 years ago|reply
> Nearly 8% of the top 10 million websites support HTTP/3, according to the latest figures from W3Techs.

Let me guess: those are all behind Cloudflare

[+] philip1209|4 years ago|reply
Great - now Heroku will be two versions behind on HTTP.
[+] jpambrun|4 years ago|reply
Meanwhile the company I work for installs root certs on our machines and pass everything through a proxy that blocks http/2. I doubt I will ever see http/3..
[+] john567|4 years ago|reply
I'm interested in using HTTP/3 for bi-directional communication.

Anyone with more experience on this care to weigh in?

I know there's WebSockets but that's typically implemented over HTTP/1.1 with durable TCP connections.

Let's say I wanted to do near real time (lowest possible latency preferably) synchronization in a server/client architecture, can HTTP/3 make sense here?

[+] Matthias247|4 years ago|reply
HTTP/3 pretty much performs like HTTP/2 there. You kind of have 2 options:

1. Make as many requests/responses as you require, and let the mulitiplexing of the protocol level do the job for you. Still might mean extra latency for sending another request to get the next chunk of data, but you might be able to send it ahead of time (long-polling style).

2. Make a single request, and stream all data bidirectionally in the request and resopnse body. bodies can be almost infinite and if you are using a custom library you can use them however you want. E.g. put small delimited messages into it in either direction - which is what gRPC streaming is doing. This will require libraries which actually support streaming, and not just Request->Response. Especially browsers are tricky here.

All those options have in common that you get reliability and flow-control in them. If you don't want to have that - because you maybe e.g. rather want to skip outdated data - then building on a lower layer like directly on QUIC makes more sense. This capability might come to browsers with WebTransport.

[+] egberts1|4 years ago|reply
Not going to open UDP ports at the home gateway firewall. Just not worth the associated baggage that UDP brings outside of HTTP/3-QUIC.
[+] BenjiWiebe|4 years ago|reply
Do you block all UDP including outbound?

I guess DNS works over TCP (and TCP/HTTP) these days...

[+] hrdwdmrbl|4 years ago|reply
I’m still waiting for everyone to support http/2!
[+] otabdeveloper4|4 years ago|reply
No, not everything. "When will this bullshit die" isn't answered.
[+] 1vuio0pswjnm7|4 years ago|reply
"Nearly 8% of the top 10 million websites support HTTP/3, according to the latest figures from W3Techs."

And 100% support HTTP/1.1. HTTP.1.1, while not new, sounds quite useful.

Being a mostly non-commercial, text-only web user, I only request resources from the host domain. The browser does not automatically follow URLs sourced in a page nor does it process Javascript to fetch or make XHR for additional resources. Often I do not use a browser to make HTTP requests, preferring to use smaller command line utilities instead, as for me this can be faster and more flexible. There is never any delay for a website to "load". For example, if I request the resource "index.html" from the host example.com, I do not make connections to any third party host domains, e.g., doubleclick.net. Thus, "head-of-line blocking" is generally not an issue.

Perhaps if I were requesting multiple resources, e.g., index0001.html through index1500.html, from example.com, then HTTP/3 might be faster than HTTP/1.1 pipelining, but I have not seen any evidence to support that idea. I have been using HTTP/1.1 pipelining to request multiple resources from the same host for a long time. Year after year it keeps working, and in some cases working better than ever before. In the years before Nginx was popular, when Apache was the most popular web server, it was common to see maximums set at 100 HTTP requests per TCP connection. Today, in some cases, maximums seem to have no upper bound. I have made thousands of HTTP requests over a single TCP connection.

The so-called "head-of-line blocking" problem seems to be restricted to "complex" websites that use resources from multiple hosts, especially trackers and ad servers. Those are often websites with lots of advertising, distractions and annoyances.

I enjoy using the web without invoking the "complex" website model. Nearly 100% of websites look great in the text-only browser, meaning I can read all the text and glean the information conveyed. For me, most "complex" websites can still be treated as if they were "simple" websites without losing information. When I visit example.com, I only request index.html from example.com. Nothing more. I do not make additional connections to third party domains, and, as such, there are no "blocking" problems to worry about.

HTTP/3 may be optimised for certain types of websites, i.e., complex ones, and a certain type of web usage, i.e., consumption of "complex" websites that include third party "content" and/or hidden elements. The biggest push for "HTTP/3/" comes from companies with vested interests in "complex" websites, the proliferation of online advertising and the attraction of "eyeballs".

HTTP/1.1 feels less corporate, from a time before Google et al.'s takeover of the web.

I do like the idea of QUIC (though I do no think Google was the first to implement the idea of reliable transmission over UDP), and I look forward to potentially using other (less web browser-centric, advertising-oriented) protocols over QUIC "connections".

[+] xyzzyz|4 years ago|reply
The so-called "head-of-line blocking" problem seems to be restricted to "complex" websites that use resources from multiple hosts, especially trackers and ad servers. Those are often websites with lots of advertising, distractions and annoyances.

Huh, what? The resources from different hosts are on different HTTP/1.1 connections, so they cannot head-of-line block one another.

[+] jayd16|4 years ago|reply
>The so-called "head-of-line blocking" problem seems to be restricted to "complex" websites that use resources from multiple hosts, especially trackers and ad servers. Those are often websites with lots of advertising, distractions and annoyances.

Multiple hosts? You mean like in a app level proxy so its actually over the same connection?

I think its more relevant for multiple multiplexed requests to an API server in the B2B setting. Now the connection isn't bogged down by slow responses.

[+] 1vuio0pswjnm7|4 years ago|reply
s/(complex)|("complex") websites/complex web pages/g

Perhaps a better way to explain why "head-of-line blocking" is a problem for "complex" web pages is that this model of a web page is one where the page is built from various components. They could come over different connections or the same one. HOL blocking may only apply to the second case. Regardless, the HOL problem arises because the page is not deemed "complete" until all the needed resources have been retrieved. Further, one retrieval might need to precede another. This gives rise to this idea of "loading" a web page. Please wait... (for header bidding to finish)

This delay while a page "loads" was used to thwart competition as part of "Jedi Blue" as alleged in the Texas, Arkansas, Idaho, Indiana, Mississippi, Missouri, North Dakota, South Dakota and Utah v Google, LLC., based on internal documents produced by Google: https://www.texasattorneygeneral.gov/sites/default/files/ima...

The way I do HTTP pipelining does not require mutiple components to "complete" a page. There is no "loading". There is no header bidding. We treat a complex page as "simple". No external resources. No Javascript. No CSS. The process is simply a sequential downloading of one page then another, catenated them into one HTML file. Some HN commenters loathe this usage of HTTP because it is useless for building complex web pages and inserting resources hosted by third parties into the page, namely, advertising. It restricts the ability to create highly artistic pages. This type of web use is basic. Boring. Rudimentary. Efficient. It works consistently. It's fast. (Yes, even when we have to wait for one request to finish before the next one begins, it is still fast. Plus, we do not have to worry about putting the responses into the correct order. They come back ordered correctly.) Catenated HTML pages look great in a text-only browser. Plaintext information for rapid consumption. No ads. No BS.

If one is not building a "complex" web page, then HTTP/1.1 works well. As I mentioned I have not seen any proof that HTTP/3 is superior for this type of web usage. Until such proof is presented, I will be sticking with HTTP/1.1, which works on 100% of websites, not 8% of the top 10 million.

[+] quasarj|4 years ago|reply
Everything I need to know? Hardly!

How is it to debug? How do I troubleshoot? How do I dump a stream and see what is going on?

And that's just the tip of the iceberg of what I need to know before I can consider using it...