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
Host
header 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 theHost
header 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 theHost
header 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
Host
headers. 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.