Nginx非80端口强制使用HTTPS协议

由于电信封了80端口,我不得不将Nginx默认端口80改为了8081。Nginx的配置文件如下

1
2
3
4
5
6
7
root /var/www/html;

server {
listen 8081;
index index.html index.htm index.nginx-debian.html;
server_name _;
}

在HTTP协议下,http://www.mydomain.com:8081,可以正常访问。但是HTTP协议下信息是透明的,没有任何安全可言,所以需要使用HTTPS协议来提高网站的安全性。

值得庆幸的是,电信没有封锁443端口,所以可以直接使用443作为HTTPS协议的端口。上一篇,我已经讲了如何通过letsencrypt来给树莓派颁发证书。现在我们就要用到这个证书了。修改Nginx配置文件

1
2
3
4
5
6
7
8
9
10
11
root /var/www/html;

server {
listen 8081;
listen 443 ssl;
index index.html index.htm index.nginx-debian.html;
server_name _;
ssl_on;
ssl_certificate /etc/letsencrypt/live/www.mydomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.mydomain.com/privkey.pem;
}

由于letsencrypt颁发的证书是pem文件,注意ssl_certificate对应fullchain.pemssl_certificate_key对应privkey.pem

在HTTPS协议下,https://www.mydomain.com:8081,可以正常访问。也可以写作,https://www.mydomain.com:8081:443,两者是一个意思。但是在HTTP协议下,http://www.mydomain.com:8081报错了400错误

The plain HTTP request was sent to HTTPS port

查遍了网上的解决方案,几乎都是针对80端口和443端口而言的。没有同时使用非80端口以及443端口的HTTPS协议。不是推荐去除Nginx配置文件中的ssl_on,就是推荐listen 443后面加上ssl

我一开始的想法是,非80端口既能支持HTTP协议,又能支持HTTPS协议。但是后来我看到说,当使用HTTPS协议访问非80端口时,就不能再用HTTP协议了。能够支持两种协议共存的,只有80端口。那现在我没法使用80端口,还有别的解决办法吗?答案是有的。

现在的解决方案是,不管是HTTP协议还是HTTPS协议访问非80端口,一律重定向为HTTPS协议。上面的配置在HTTP协议访问的时候不是报错吗?可以通过497这个HTTP状态码,来强制将HTTP协议重定向为HTTPS协议。在上面的配置文件的末尾加一行

1
2
3
4
5
server {
...
error_page 497 https://$host:8081$request_uri;
...
}

上面的配置文件中,$host以及$request_uri都是变量,分别表示当前请求的域名以及请求的后缀。

这一次,不管是以HTTP协议访问还是以HTTPS协议访问8081端口,所有的请求都会变成HTTPS请求。原先400的错误被捕获后,重定向为HTTPS协议,实现思路就是这样。这就是非80端口实现HTTPS协议和80端口实现HTTPS协议的不同之处。网上几乎都是清一色的80端口实现HTTPS协议。更多细节,可以参考Force Redirect From HTTP to HTTPs On A Custom Port in Nginx一文。

avatar

chilihotpot

You Are The JavaScript In My HTML