FastCGI: 30 Years Old and Still the Better Protocol for Reverse Proxies
54 points by fs111
54 points by fs111
I have previously argued that FastCGI should have used HTTP as its protocol but I must admit ~agwa’s arguments are solid.
FastCGI still gets quite some use in PHP deployments at least. And even CGI got some positive notes recently, given that its not quite unlike "edge function" or whatever the clever cloud kids are doing, never mind its utter simplicity.
Meanwhile, SCGI sits crying alone in a corner.
SCGI is a simpler and cleaner protocol with support in a fair number of web servers. FastCGI has a bunch of features (i.e. request multiplexing, authorizers/filters, in-protocol stderr) that complicate the protocol and aren't used very often.
My Gemini server supports both CGI and SCGI. I took a look at the FastCGI specification and noped right out of that.
Its true, FastCGI is a ton better for a ton of use cases however most web servers have intentionally made their client implementations worse to deal with poorly written servers, so stuff like multiplexing isn't really available.
FastCGI was super cool as an accelerator in its day, and is still a legit way to run PHP behind nginx, as it’s the common connecting denominator between the two. But it’s not without its own issues, namely it's a fairly complex binary protocol with no flow control and some interesting design choices - check out this comment in an old Twisted implementation for more, uh, commentary.
I think there is a lot of merit to this argument, however, FastCGI defers to CGI/1.1 for PATH_INFO, etc., which is lossy as it must be URL-decoded and therefore cannot represent encoded slashes, %2F. (Some implementations also collapse // to / in path, but this is an issue in various HTTP implementations too.)
It is less expressive than HTTP in ways that may or may not be important to your application; I prefer accurate URL handling.
My current solution actually attempts its best to follow the end-to-end protocol, although I haven't updated all my infrastructure to use it yet.
In most cases, I do not want a cache or anything magical other than just a reverse proxy at the web server level, so why have a reverse proxy? My model does not use ECH, so essentially I use a TLS SNI router to route virtual hosts to the correct application backend and let them handle their own TLS.
I totally agree. That's my preferred model too, and I use it wherever possible: https://www.agwa.name/blog/post/using_sni_proxying_and_ipv6_to_share_port_443
Unfortunately, Past Me unwisely put a bunch of unrelated stuff on the same hostname, so now I'm forced to use path-based routing to find the right backend, and that means an HTTP reverse proxy. Hopefully I can untangle that someday. In the meantime, I can tolerate proxying over FastCGI.
Thanks! Interesting approach that you use here. Unfortunately my IPv6 infrastructure is close to broken due to reasons outside of my control, and publishing DNS records is actually more annoying for me, so I currently use a more naïve TLS SNI proxy
How does it compare to the HAProxy Proxy protocol? (https://github.com/haproxy/haproxy/blob/master/doc/proxy-protocol.txt)
FastCGI seems to allow arbitrary "trusted headers", while the proxy protocol has a fixed state. On the other hand, the proxy protocol can forward arbitrary tcp streams (like websockets or end-to-end encrypted connections).