Comment by acdha

6 hours ago

The saving grace here is that people are most commonly doing this for reasons other than as a defense - serving static files efficiently, combining multiple services, caching, DDoS protection, etc. There are certainly some directly exposed FastAPI instances but it’s been against the grain for decades.

Or probably the most straightforward one, which is SSL termination. Most backend software usually has very bad support for HTTPS communication, while it's typically extensively documented for something like nginx. It also catches some other strangeness like making it easier to update the certificate.

The biggest risk is incorrect usage of the default_server directive, the proper way in which to handle it isn't usually taught in most "here's how you use nginx" tutorials. Most usually just have you edit the default server blocks.

Tldr that covers 99% of all cases: you want 2 default server blocks, one on port 80 and one on port 443. The one on port 80 should only return 444 (an internal nginx status code that stops the connection immediately with no response), while the one on port 443 should use ssl_reject_handshake to terminate the SSL connection as quickly as possible without causing strange errors (you also need a self-signed certificate because otherwise openssl refuses to do protocol negotiation correctly, but the cert doesn't actually do anything). After that, specify your actual domains as separate server blocks using server_name (including a separate one for each to do the port 80->443 redirect).

Arguably this should be the default configuration shipped by distros, but it isn't for some reason, which doesn't help matters.