return in server block
The Securely Deploy a Django App With Gunicorn, Nginx, & HTTPS uses the following HTTP-to-HTTPS redirect block:
# Redirect HTTP to HTTPS
server {
server_name .supersecure.codes;
listen 80;
return 307 https://$host$request_uri;
}
I interpret this to do a 307 redirect for every HTTP request on port 80 where the Host HTTP header matches.
return in location
The Mozilla SSL Configuration Generator uses the following block to do the same HTTP-to-HTTPS redirection (for example here):
server {
listen 80 default_server;
listen [::]:80 default_server;
location / {
return 301 https://$host$request_uri;
}
}
I presume it is put in a location block in case someone wants to serve other things (e.g., static assets) via HTTP then it is less work to add it.
return in if block
This one is from an old server in production:
server {
if ($host = some.org) {
return 301 https://$host$request_uri;
}
listen 80;
server_name some.org;
return 404;
}
I can only guess why the if block, so I presume that the Host HTTP header is explicitly checked for the right domain, and if it doesn't match, then a 404 is returned. Otherwise, it is kicked over to the server block where TLS is set up.
Are there any merits to use this form?
edit: Found the Security issue with redirects added by Certbot's Nginx plugin post in Let's Encrypt's forum giving a rationale how a return inside an if block is more secure. Still don't understand why exactly, but it's a start. There is also the open certbot issue #9705 asking the same.
edit-2: The relevant paragraph explaining why a "bare" return 301 is harmful is posted below. (@Esa Jokinen: The reason I opted not to create an answer is because I don't understand this.)
The way Certbot creates an HTTP to HTTPS redirect in Nginx is through the following configuration directive:
return 301 https://$host$request_uri;The potential problem with this is it relies on the value of the
Hostheader for where to redirect the request. If a directive like this is added to the default server block for HTTP traffic in your Nginx configuration, users can modify theHostheader of their request to have it redirected to an arbitrary domain. On its own, this isn’t a problem because the redirect to an arbitrary domain is only sent to user who put that domain in theHostheader of their request.The problem occurs if an attacker can trick a cache somewhere to store this redirect from Nginx and serve it to users who attempt to connect to the server through normal means with unmodified
Hostheaders. If this could be done, an attacker could redirect traffic from users of that cache to a domain of their choosing.Due to the prevalence of virtual hosting, a cache that would do this would have to have its own bugs or be misconfigured. The redirect added by Certbot is not exploitable on its own, but when coupled with other software with its own bugs, exploits, or misconfiguration, it can become a security problem.