前言
本文记录了为Nginx配置HTTPS的心得。心血来潮,为了符合最佳实践,决定在服务器上弄上HTTPS。为了得到那个代表HTTPS的网页小锁,我也是费尽了心力。不过好在,借着之前在Apache成功配置HTTPS经历,很快也就给我的Nginx服务器配上了HTTPS。
注:本文的HTTPS使用的是免费SSL证书,只能支持单个郁闷,所以无法直接支持多子域名的WP Multisite。关于如何在Nginx里为子域名同时配置多个HTTPS,请参考这篇文章。
1. 申请SSL证书
首先的首先,当然是申请HTTPS的SSL证书。SSL证书可以自己签发,也可以在各大云服务提供商(腾讯、阿里云、华为云是目前国内的头部云服务提供商)免费申请。
当然为了避免中间人攻击,建议还是不要自己签发SSL证书。去各大云服务商上买免费的证书是一个很好的选择!我申请的是免费证书。目的除了保护通信安全,自然就是那个小锁的标准!
有一点需要注意,免费的SSL证书是只支持单域名绑定的。即,subdomain.example.com 和 example.com 是需要两个不同的免费SSL证书的。但是就 www.example.com 和 example.com 而言,一般它们默认是会自动一起绑定的。不过对于二级域名 subdomain.example.com,对它申请SSL证书是不会自动绑定 www.subdomain.example.com 的,因为一般二级域名是不会带 www 的。但是我们可以通过申请 www.subdomain.example.com 的证书来让它顺带绑定 subdomain.example.com。
具体的申请流程就不细说了,按照各大网站的标准流程点点点就好了。但是再次注意,为了方便地让example.com和www.example.com都能使用HTTPS,需要能将带www的和不带www的都绑定在同一个SSL证书下。这样配置起来会方便非常的多。
在申请好SSL证书后,将证书下载到本地。一般证书都已经按照Web Server的种类分好了。这里我们找出专门给Nginx用的证书就好啦!
2. 上传证书至服务器
对于Nginx而言,需要的是”.crt”和”.key”证书文件。我们需要将他们上传至服务器。
为了方便起见,建议将所有上传的文件都上传至当前用户的主目录 ~
中,然后再登录服务器移动文件。
这里使用的是scp上传。命令如下:
$ sudo scp -i pathToSSHKeyFile -r pathToFile userName@IPorURLAddress:~/.
上传完成后,利用ssh登录服务器:
sudo ssh -i pathToSSHKeyFile userName@IPorURLAddress
并将上传好的两个文件移动到Ngxin的默认配置文件夹中。
然后,我们就可以开始配置nginx了。
3. 修改nginx.conf
通过修改nginx.conf,我们可以让Ngxin利用我们之前申请的SSL证书用HTTPS的方式为网站通讯加密。
3.1 修改Server的block
找到服务器上nginx.conf的位置(可以用nginx -t
),用编辑器打开它后,将里面的Server按下面的示例代码进行修改。修改后应该与下面类似:
server { listen 443 default_server ssl; # 这里将这个Server设置成了默认的Server。所有没有成功匹配的443访问都会使用该Server server_tokens off; keepalive_timeout 5; root pathToYourWordpressFolder; # 输入Wordpress的根目录地址,将当前server的根目录设置成wordpress的根目录。默认的话一般是/var/www/example-com index index.php index.html; access_log logs/wordpress.log combinediox; #或者可以将其替换成其他的想要保存log的文件地址 error_log logs/wordpress.error.log; #或者可以将其替换成其他的想要保存log的文件地址 server_name example.com; # 输入你的server的名字(这里可以输入多个。比如server_name example.com www.example.com *.example.com。但是请注意Nginx的server选用顺序。具体请见下文。) ssl_certificate pathToYourCrtFile; # .crt文件的路径名。如果放在同一文件夹下,直接输入.crt文件的文件名即可 ssl_certificate_key pathToYourKeyFile; # .key文件的路径名。如果放在同一文件夹下,直接输入.key文件的文件名即可 ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; location ~* \.php$ { fastcgi_pass 127.0.0.1:9000; #这里因为使用了fastCGI所以有此配置。如果不使用删去即可 include fastcgi.conf; client_max_body_size 20m; fastcgi_connect_timeout 30s; fastcgi_send_timeout 30s; fastcgi_read_timeout 30s; fastcgi_intercept_errors on; } location / { try_files $uri $uri/ /index.php?$query_string; } }
请参看其注释决定如何相应的修改。因配置因人而异,绝对不要直接复制黏贴以上。只需要将与SSL相关的片段放上即可。
注:这里假设证书文件与nginx.conf在同一文件夹下。如果不在一个文件夹下,记得添加相应的路径。
注:虽然查阅的腾讯的document [1] 里面要求在HTTP block也添加ssl_certificate_key和ssl_certificate信息,但是查阅官网文档 [2] 后并未发现有此要求。实际操作后也确实不需要修改HTTP block。
3.2 强制开启https
https是443端口,而普通的网站访问默认是80端口。因此,为了强制所有的访问均为HTTPS访问,我们需要为80端口做个转发。
找到80端口的Server,并根据以下代码进行修改:
server { listen 80 default_server; server_name example.com www.example.com# 输入你的server的名字(这里同样可以输入多个。同时可以输入你服务器的IP地址。这样即使别人用IP访问也能被导到正确的地址) return 301 https://example.com$request_uri$request_uri; # 例如(https://fredpan.cn$request_uri) }
3.3 端口转发规则及wp自带的转发
某些情况下,可能我们希望不管是否访问www.example.com或者example.com,最终都能访问到www.example.com或者example.com。为此,我们可以在最终的server里添加以下字段(假设要求全部访问到example.com):
if ($host != "example.com") { #这里输入你想要的URL的样式(不带"http://"或"https://") return 301 https://example.com$request_uri; #这里输入你想要的完整URL$request_uri }
以上可以将所有流量入口都永久重定向到同一个希望的URL下。
注意:以上永久重定向的目标URL必须要与wordpress里设置的域名一致。否则可能会造成无限重定向。比如,wordpress设置的域名是https://example.com。这里如果想将https://example.com重定向到https://www.example.com,就会导致Nginx与Wordpress无限次的重复重定向。因为Nginx会将example.com重定向到www.example.com,而Wordpress会重新将www.example.com重定向到example.com。
4. 重启服务器
利用一下命令重载/重启Nginx:
$ sudo systemctl reload nginx
$ sudo systemctl restart nginx
如果无任何错误则配置成功!
References:
[1] https://cloud.tencent.com/document/product/1207/47027
[2] http://nginx.org/en/docs/http/configuring_https_servers.html
后语
谨以此文纪念我一天内将自带镜像删除改用Nginx然后再改用Apache的两次重装经历和这爱折腾的劲儿!
2021.06.09 于上海兴荣温德姆隔离酒店…