在自己的网站中启用HTTPS服务

看着身边的网站一个个在地址栏都有了小锁的标志,自己也是心痒痒呀。正好今天手头的事情不多,就来搞了一下这个东西。

一、SSL证书平台选择

首先,提供SSL证书的平台有很多,各种云计算平台也都有提供的。不过他们提供的免费证书大部分都是有时间限制的,三个月到一年不等,到期就要自己手动续期。

本着一劳永逸的原则,我开始了寻找SSL证书平台之旅。结果并没有找到自己想要的结果,不过中途却发现了有些平台用的就是Let’s Encrypt这个平台的证书,就是做了一个中间商,只不过不赚差价而已。而我生平,最讨厌中间商。

于是我直接找到了“厂商”,点击Get Started,就开始了探索CentOs下Nginx服务器安装SSL证书的旅程。

剧透一下结果:证书同样需要续期,不过可以安装工具自动续期,相当于永久的证书了。

在快速入门章节,可以看到有两种方式可以获取到SSL证书。而我的情况,适用于第一种,拥有命令行访问权限。

摘自https://letsencrypt.org/zh-cn/getting-started/

我们建议大多数具有命令行访问权限的人使用 Certbot ACME 客户端。它可以在不下线您的服务器的前提下自动执行证书颁发和安装。对于不需要自动配置的用户,Certbot 还提供专家模式。它易于使用,适用于许多操作系统,并且具有出色的(注:英文)文档。访问 Certbot 官网 以获取针对于操作系统和 Web 服务器的订制文档。

所以接下来,就是如何使用certbot的问题了。

二、配置环境并安装CertBot

Let’s Encrypt的快速入门页面中,可以找到CertBot官网的链接。

进入CertBot官网后,首先它让我们检查自己的网站是否已经有了HTTPS访问的功能。很显然,我的并没有,于是就需要安装CertBot了。

点击右边的Get Certbot instructions来查看Certbot的使用说明。

在新的页面里,会让你选择自己的服务运行环境,我这里就是Nginx运行在CentOS7上面,所以按下图这样选择。

然后向下滚动页面就可以看到适用于自己系统的安装方式了。

第一步是通过SSH连接到服务器,第二部具体是在干嘛的不太清楚,就按它的要求开启这个东西就行了。开启方法如下:

1
yum install epel-release

第三步是开启可选模块,我当时啥都没想直接就开启了,现在想想似乎并不需要开启这个,因为那啥Oracle Linux应该和我无关吧。不过保险起见还是把命令列出来吧,下次再安装的时候万一就用到了呢。

1
2
3
yum -y install yum-utils

yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional

接下来就是安装本篇文章的主角Certbot了。

1
sudo yum install certbot python2-certbot-nginx

三、修改nginx配置文件并启用SSL证书

接下来,就到了第五步了。这时,它又让我选择安装方式,那看了说明自然是第一种简单呀,一键自动化配置,爽!

1
sudo certbot --nginx

爽不过一秒,命令行就报错了。

这里还要说一下,如果是第一次执行这个命令,会让你输入自己的邮箱,输入一下即可。

看上面说的,再去搜索了一下相关问题,大概知道是自己在nginx配置文件中用了中文注释的原因。删掉后再次运行,又卡在了服务器验证这一步,看来安装SSL服务并没有想象中那么简单啊。

然后在一番乱搜之后,在这两篇文章的帮助下我完成了SSL服务的搭建。

How To Secure Nginx with Let’s Encrypt on CentOS 7
Secure Nginx with Let’s Encrypt on CentOS 7

在第一篇文章里,我用一下命令更新了一下自己的防火墙配置

1
2
3
4
5
6
7
8
# 允许http和https和重定向访问
sudo firewall-cmd --add-service=http
sudo firewall-cmd --add-service=https
sudo firewall-cmd --runtime-to-permanent

# 允许外网访问80端口和443端口
sudo iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT

这样做了之后,还是没有效果(以前曾经把80端口放开过),然后又参考第二篇文章,终于成功了,具体步骤如下:

1、生成强Dh (Diffie-Hellman)群(并不懂在说啥,敲代码就是了)

1
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

这个步骤需要花费一段时间,屏幕中会有大片英文逗号出现。

2、创建存放证书的目录

我猜是这么回事。进行HTTPS访问时,总会有一个额外的操作用来获取证书内容,那证书从哪里来呢?当然要找个地方存起来才能让浏览器获取。

1
2
3
4
5
sudo mkdir -p /var/lib/letsencrypt/.well-known
sudo chgrp nginx /var/lib/letsencrypt
sudo chmod g+s /var/lib/letsencrypt

sudo mkdir /etc/nginx/snippets

目录创建好之后,将下面两个文件创建到/etc/nginx/snippets目录下面:

/etc/nginx/snippets/letsencrypt.conf

1
2
3
4
5
6
location ^~ /.well-known/acme-challenge/ {
allow all;
root /var/lib/letsencrypt/;
default_type "text/plain";
try_files $uri =404;
}

/etc/nginx/snippets/ssl.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ssl_dhparam /etc/ssl/certs/dhparam.pem;

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;

add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

看到上面的文件内容基本可以知道,这是Nginx配置文件的格式。把这个配置文件单独拿出来存放应该是为了在Nginx主配置文件中复用上面的配置内容(每个不同的域名均需要配置SSL证书)。

3、修改Nginx配置文件

这时,我们需要在Nginx配置文件中的server区域内加入下面这句话:

1
include snippets/letsencrypt.conf;

这时,这个配置文件就大概应该是这个样子的:

1
2
3
4
5
6
server {
listen 80;
server_name example.com www.example.com;

include snippets/letsencrypt.conf;
}

然后重启Nginx服务器:

1
systemctl reload nginx

然后教程中的下一步是以certbot certonly开头的一段命令,用于获取对应域名的证书。而我运行这个命令死活不成功,会报No valid IP addresses found for aqzscn.com的错误。

万念俱灰之下,我又回到Certbot的说明文档,执行了一下sudo certbot --nginx,结果一路畅通无阻,中间还提示我是否要将HTTP请求重定向为HTTPS请求,那当然OK呀。

下面是我生成证书成功后提示的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/www.aqzscn.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/www.aqzscn.com/privkey.pem
Your cert will expire on 2020-03-17. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

证书生成成功之后,还需要做的就是自动更新证书,在命令行中敲以下命令即可:

1
echo "0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew" | sudo tee -a /etc/crontab > /dev/null

四、测试结果

这个时候,就到了检验结果的时候了。

在浏览器地址栏输入自己的域名后,预期的网页终于出现了。不过奇怪的一点是,如果我不加HTTPS,它并不会给我重定向到HTTPS的请求。

因为我这个域名下面还有几个子域名,于是我将其也加入了HTTPS访问。但这次我在地址栏输入care.aqzscn.com时,它又确实给我重定向到HTTPS请求了。很奇怪很奇怪,应该是有哪里没有搞好把。

此时又出现了一个问题就是我的后台服务没有开启HTTPS服务,好难啊。。

总结

总的来说,这次是实现了在网站中添加SSL证书的功能,其中还是有一些不足需要完善,不过还是留到下次再说吧,到时候研究一下能不能把相同的证书用在没有域名的服务器上,或者说就用自己生成的证书来提供HTTPS服务,反正API请求的地址用户也看不到了。

Godbobo wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
坚持原创技术分享,您的支持将鼓励我继续创作!