[原创] 为nginx服务器网站添加HTTPS/配置SSL证书

网站使用HTTPS的好处就不用多说了,在当今凶险的互联网环境下,使用HTTP越来越不安全,所以我也决定把网站转成HTTPS。使用HTTPS,首先你需要有一张SSL证书。
曾经,收费的SSL证书很贵,一般人玩不起;随着互联网的发展,免费的SSL证书越来越普及,谁都可以很容易获取到,所以HTTPS的个人网站也越来越多。
其中,现在最流行的就是使用可靠的数字证书认证机构Let's Encrypt提供的免费SSL证书。

下面,我们就来看看,如何一步步把网站变成HTTPS安全链接。
文章来源:https://www.codelast.com/
『1』使nginx支持SSL
首先你得让你的web server支持SSL。如果你的nginx本来就支持SSL,那就当我没说。如果不支持,请参考这个链接。

『2』获取及部署SSL证书
为了简化SSL证书的部署,Let's Encrypt提供了一个叫做Certbot的客户端软件来辅助完成证书部署工作。
首先要安装这个软件,以CentOS系统为例。在Certbot的网站主页上,正确选择web server和OS之后,会跳转到对应的文档章节,指导你怎么做:
certbot select web server and os
如果你不想看官方文档,也可以参照我下面的方法来操作。
下面是一个例子(不同的web server、不同的OS是不同的,仅供参考):

  • 启用EPEL(Extra Packages for Enterprise Linux):
yum install epel-release
  • 如果你使用的是Amazon Elastic Compute Cloud (Amazon EC2),那么可以这样做:
yum -y install yum-utils
yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
  • 安装Certbot:
yum install certbot
  • 生成SSL证书:
certbot certonly --webroot -w /path_to_your_web_root_dir/ -d codelast.com -d www.codelast.com
其中,path_to_your_web_root_dir 是你的web server的根目录,例如,如果你使用的是WordPress,那么这个目录下就应该有WordPress的index.php等一堆php文件。
命令执行过程中,会交互式地要你输入紧急联系人的Email,填自己的邮箱即可。

文章来源:https://www.codelast.com/
『3』配置nginx使得网站可以用https://...访问
在你nginx配置文件 nginx.conf 中的 server {...} 段里,应该有这样一句:

listen 80;

这是http访问的标准端口,把它改成:

listen 443 ssl;

使得nginx可以接受https的访问。但同时,我们还要加上下面的配置:

ssl_certificate      /etc/letsencrypt/live/codelast.com/fullchain.pem;
ssl_certificate_key  /etc/letsencrypt/live/codelast.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/codelast.com/chain.pem;

这几个路径中的pem文件,就是我们之前用certbot工具生成的。
重启nginx,试验一下是否能用https://...访问网站,浏览器的左上角地址栏里应该有绿色小锁图标:
ssl enabled
到现在已经是一个巨大的进步了。
文章来源:https://www.codelast.com/
『4』测试网站的SSL安全性
当你认为“似乎”一切都已经完成,一切看起来都那么完美之后,你需要使用SSL Labs的权威工具来测试一下网站的SSL安全性,搞不好结果会令你失望哦。
如下图所示,输入网站域名然后点击“Submit”就会开始测试:
ssl server test
文章来源:https://www.codelast.com/
测试结果可能会像下面这样:
ssl test result rating c
文章来源:https://www.codelast.com/
SSL安全性得分是C,这是个非常糟糕的分数,它表明我配置的SSL server很不安全!所以需要按照测试结果下方给出的建议来进行修改。从标红的文字知道,得分为C的原因是我没有禁用SSL 3.0协议。为什么要禁用?因为SSLv3已经被发现有严重的安全漏洞,所以不应该再让web server支持它。

『5』禁用SSLv3
在nginx配置文件的 server {...} 段中,添加下面这句,使得nginx只支持TLS协议:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

这样,重启nginx之后SSLv3就被禁用了。再次运行SSL Labs的测试,会发现安全性评分提高到了B:
ssl test result rating b
文章来源:https://www.codelast.com/
『6』配置前向安全性和DHE(Diffie Hellman Ephemeral)
分数B还是比较“惨”的,正如“Grade capped to B”那一句高亮的话所提示的,我的SSL server现在还有DH key交换的安全问题,关于这个问题的详细解释,可以参考这个这个链接。
解决步骤如下:
使用openssl命令生成一个强壮的DH组(前提是你已经安装了openssl软件):

openssl dhparam -out dhparams.pem 2048
命令执行后,命令行会打印出如下信息:
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
正如这句话所描述的,经过漫长的等待结束之后,会在当前目录下生成一个 dhparams.pem 文件。

然后我把这个文件移到 /etc/ssl/certs/ 目录下(其实你放哪里都可以):

mv dhparams.pem /etc/ssl/certs/

最后在nginx中的 server {...} 段中添加这么几句配置:

ssl_dhparam /etc/ssl/certs/dhparams.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;

然后再重启nginx,此问题就解决了。再次运行SSL Labs的测试,会发现安全性评分提高到了令人欣慰的A:
ssl test result rating a
文章来源:https://www.codelast.com/
『7』兼容原有的HTTP访问
经过上面的配置,我们已经可以用 https://... 来访问网站,并且网站的SSL安全性也比较高了,但是,网站的老用户可能并不知道我们使用了安全链接,他们仍然会使用 http://... 来访问网站,所以要保证用户使用这个链接访问网站的时候,会自动跳转到 https://... 网址,从而使用安全链接。
nginx配置方法是,在 http {...} 段中添加一个独立的 server {...} 块,如下:

server {
  listen 80;
  server_name codelast.com www.codelast.com;
  return 301 https://$server_name$request_uri;
}

重启nginx之后,试一下用 http://... 来访问网站,应该就能自动跳转到 https://... 的对应链接了。
文章来源:https://www.codelast.com/
『8』配置HSTS(HTTP严格传输安全,HTTP Strict Transport Security),进一步提高安全性
事实上,前面的nginx配置还有一个安全性漏洞,填补上之后,评分A还可以进一步提高为A+!
这个配置就是所谓的HSTS

HTTP严格传输安全(英语:HTTP Strict Transport Security,缩写:HSTS)是一套由互联网工程任务组发布的互联网安全策略机制。网站可以选择使用HSTS策略,来让浏览器强制使用HTTPS与网站进行通信,以减少会话劫持风险。

不启用HSTS的潜在问题,也可以参考这个链接。
nginx开启HSTS的方法是,在SSL相关的 server {...} 段中添加这么一句话:

add_header Strict-Transport-Security "max-age=31536000;includeSubDomains";

然后重启nginx,再次运行SSL Labs的测试,会发现安全性评分终于达到了A+:
ssl test result rating a plus

图下方那句绿色高亮的信息表示我已经启用了HSTS。
文章来源:https://www.codelast.com/
『9』自动更新证书
Let's Encrypt提供的免费SSL证书只有90天的有效期,过期之后,如果你不更新证书,那么访问网站的时候,浏览器就会提示证书的安全问题,如果发生这种情况,会对访客造成极大的困扰。
Certbot提供了非常简便的自动更新证书功能,我们只需要执行1个命令,就可以完成证书的更新,所以,把这个命令加入crontab中自动执行,我们就不用担心证书过期问题啦。
测试自动更新证书(实际上并不会更新,只是测试):

certbot renew --dry-run

如果你看到打印出类似于这样一句话:

Congratulations, all renewals succeeded. The following certs have been renewed:

那就说明测试成功了。下面,你需要做的就是把这个命令加入crontab,让其周期性执行:

certbot renew

这个命令的作用是更新证书(不是测试),但是在你的证书到期之前,它并不会产生什么实际的效果。为了保险,Certbot建议每天运行这个命令两次,所以我在我的 /etc/crontab 中添加了下面这几句配置:

# renew Cetbot SSL certificate
59 23 * * * root certbot renew
59 11 * * * root certbot renew

它表示在每天的23:59和11:59时会执行证书更新命令。这样就可以高枕无忧了。
文章来源:https://www.codelast.com/
▶▶ 更新
2020.02.01:收到Let's Encrypt官方邮件,通知说certbot程序必须要更新到最新版,否则到2020.06.01就不能用了,于是用 yum install certbot 命令来更新它,更新之后再用 certbot renew --dry-run 命令来测试一下,如果打印出成功的提示,就说明更新没有问题了。

文章来源:https://www.codelast.com/
➤➤ 版权声明 ➤➤ 
转载需注明出处:codelast.com 
感谢关注我的微信公众号(微信扫一扫):

wechat qrcode of codelast

《[原创] 为nginx服务器网站添加HTTPS/配置SSL证书》有1条评论

  1. httpclient请求https接口时似乎不需要做什么特殊处理,难道httpclient会自动和三方证书机构通讯来获取key吗?

    回复

发表评论