前言
https在这个时代普遍性就不说了,最关键的是只要不乱装证书,带上这个可以让中间设备都无法获取通讯信息,对于网络会被审查的环境其实还是比较有用的。
之前的SSL服务商基本证书价格都恐怖的吓人,哪怕我的blog访问数再多2个0我也完全不会考虑加证书,现在因为Let's Encrypt的出现,一下子就让https变得非常亲民,所以当然要来鼓捣一下~
主要内容
本文主要介绍在CentOS7下是用Certbot进行证书申请,安装以及自动续期的过程。因为这方面的教程很多,所以不会特别详细,给自己做个记录。在Typecho上面套SSL的教程也不少,所以也不细说了,会稍微说下我自用的Gogs版本控制平台如何套SSL(主要是自动续期,Let's Encrypt似乎不支持靠更改DNS解析的txt解析来进行自动续期,这里来说下Gogs怎么办),然后就是阿里系的机器用自带的镜像无法运行Certbot该怎么办
正文
前提条件
已经在服务器上部署好了网站,nginx等,并且能够通过80端口对网站进行正常访问,能够使用SSH工具连接服务器执行命令
1.安装EPEL源
对于部分CentOS系统来说,直接在bash里面使用yum安装cetbot是找不到的,所以要先装这么一个东西——EPEL (Extra Packages for Enterprise Linux)是一个基于Fedora的项目,为“红帽系”的操作系统提供额外的软件包,适用于RHEL、CentOS和Scientific Linux。可以简单的认为就是自动配置yum的软件仓库用的...当然可以手动配置不装这个,不过没找到教程所以没试,并且有现成的当然更好,命令只有这一行sudo yum install -y epel-release
执行就好
2.安装Certbot
有了仓库,装Certbot,同样一行搞定sudo yum install -y certbot
3.初次是用Certbot申请证书
命令如下certbot certonly --webroot -w /opt/www/demo.mydomain.com -d demo.mydomain.com -m [email protected] --agree-tos
关于这条命令的解释是certbot certonly --webroot -w [Web站点目录] -d [站点域名] -m [联系人email地址] --agree-tos
站点目录,站点域名按照自己实际情况来,不要直接抄上去,email的话可以考虑填写真的,因为他们会在证书即将过期之前发信到这个邮箱进行通知。不过如果接下来的自动续期可以配置成功其实倒也没太大关系了~
最后那个agree-tos当然要有,要是不同意人家怎么可能给用
注意如果这一步出现
ImportError: cannot import name UnrewindableBodyError
,说明urllib3库有问题了,需要重装。pip uninstall urllib3
pip install urllib3
如果遇到这个问题的你使用的是阿里系主机
emmm,附上一点额外的东西吧
当然虽然我嘴上说着换工具,但是内心还是偏向Let's Encrypt推荐的Certbot...所以我就就这这个坑直接跳进去了Orz
所以来说说阿里系遇到这种问题的解决方法,错误方案和中间过程因为尝试次数过多就不记录了,直接记解决方法...
上面我已经使用
pip uninstall urllib3
把
urllib3
卸载掉了,重新安装的时候发现还是不行...所以干脆彻底了一点...把另两个也卸了...pip uninstall requests
pip uninstall chardet
然后再用这条命令装回来
pip install --upgrade --force-reinstall 'requests==2.6.0' urllib3
安装发现报错
又给卸载了...既然这样,那就重来一遍改下命令直接忽视报错吧pip install --upgrade --force-reinstall --ignore-installed 'requests==2.6.0' urllib3
这下安装完就可以啦,然后回去certbot那行命令应该就没什么问题啦
4.继续第3步
如果没什么问题返回应该是、
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:
大概就是要不要往你的邮箱里发点推送邮件用的,随意选择即可,选择之后,非常智能化的会自动验证,然后生成证书(比windows上我用的那个软件好多了,虽然那个提供多种验证方式,可是...对于英语水平不高的我一点也不友好...这个至少能直接都看懂)
Obtaining a new certificate
Resetting dropped connection: acme-v02.api.letsencrypt.org
Performing the following challenges:
http-01 challenge for blog.winer.website
Using the webroot path /data/php73mysql56/sites/blog.winer.website/www for all unmatched domains.
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/dome.mydomain.com/fullchain.pem
Your key file has been saved at: /etc/letsencrypt/live/dome.mydomain.com/privkey.pem
Your cert will expire on 2020-04-10. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal.
- 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
生成的证书等文件存储路径是/etc/letsencrypt/live/dome.mydomain.com/fullchain.pem
/etc/letsencrypt/live/dome.mydomain.com/privkey.pem
建议不要移动这两个证书位置,在修改nginx配置文件的时候直接指向这个路径就可以了,因为这里certbot是把证书统一进行管理的,看到其它一些大佬说会自动留存每次更新申请的证书,类似于版本控制的感觉,可以随时恢复到申请的任何一个证书,因为我这是第一次申请,暂时没遇到证书续期的事情,所以不太清楚不过个人也不建议改
关于gogs的申请方式
其实说白了certbot就是在网站根目录路径放置一个文件进行验证的,自动放文件自动验证和移除。要想给gogs装,无非就是要找到它的根目录究竟在哪里。
这个最开始我也是陷入误区了,看gogs的介绍文档里有放robots.txt文件的位置git.youdomain.com/custom/
,以为就是放到这里,结果怎么都不对...
后来看文件夹名字,又实验才知道...其实是public文件夹git.youdomain.com/public/
然后改下上面的命令就可以了,还是自动验证,搞定
5.配置nginx
因为开启之后会发现虽然目前可以正常访问,打开配置原文却会看到证书路径被改动了,复制了一份到他们自己的路径下,然后进行的导入Orz,这样自动续期了也不会有什么作用...因为还是要手动导入
(其实appnode之前是有自动使用Let's Encrypt签发证书并且自动更新和导入的功能的,但是因为Let's Encrypt去掉了他们之前使用的自动验证方式,所以暂时不能用了。appnode表示正在修复,不过...截止到发文已经咕咕咕了好几个月了...你们自己看着来)
①确定自己的nginx地址
如果知道的话直接跳过,不知道的话用下面这个行命令来确定(特别是面板用户...)whereis nginx
确定路径之后,配置文件是下面一个叫做nginx.conf的,打开编辑
②修改nginx配置增加https
找到自己的配置文件后在其中的server{}里面首先加上listen 443 ssl http2;
开启对443端口的监听并选择使用的协议...
在下面再加上这一大段
ssl_certificate /etc/letsencrypt/live/demo.yodomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/demo.yodomain.com/privkey.pem;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:5m;
ssl_session_timeout 5m;
只需要把ssl_certificate和ssl_certificate_key这两行的值改成自己生成的证书以及密钥文件就可以了~其他的都没什么必要去改~
③重启或重载nginx服务
修改过配置文件必需重启nginx服务或者让nginx重载配置文件从才能生效
命令分别是
service nginx restart
service nginx reload
两个任选一个执行就ok,然后最基础的配置SSL就结束了,可以直接使用https访问自己的网站,或者使用下面这个网址来检测自己的网站安全状态
ATS(App Transport Security)检测检测")
其实这个网站是用于检测更加严格的https的,不是所有带着https的网站安全性就足够高,某些网站比如苹果在调用的时候,要求HTTPS使用的TLS协议版本在1.2及以上,被称为App Transport Security(ATS)检测
④关于HTTP跳转HTTPS
尽管有了HTTPS,还是因为用户习惯等各种原因有时会访问80端口的HTTP,这时候最好不要关闭80,而是做一个http跳转https的配置
两种方法,第一种是在只开着443的时候,默认80会返回状态码497497 - normal request was sent to HTTPS
这对普通用户明显不友好,所以在nginx配置文件里面对于497错误返回的页面进行重写,加上下面这个,但凡遇到497全部返回https的页面
error_page 497 https://$host$uri?$args;
第二种是同时开放80和443,允许两个协议同时使用,但是所有请求80端口的都会在nginx里不经过错误页面直接重写到443,下面这么写,但是不要去掉listen 80;
if ($scheme = http) {
return 301 https://$host$request_uri;
}
记得做完也要重载或者重启nginx服务才行。
⑤关于一个网站使用多个域名时的SSL配置
如果有多个域名同时解析了一个网站,仅仅按照上面的方式进行配置时会出现一个问题:仅申请的那个域名在访问的时候显示的https安全 - 安全
用其余的域名访问不但不会显示没有https时候的 - 信息或不安全
并且会变成这个 - 不安全或危险
点开那个提示就能看到这样的原因,浏览器发现证书签发的域名和实际访问的域名并不一样,所以它认为,尽管你访问的网站是新域名的那个,但是却被原来的那个域名劫持和篡改了内容,并且签发了自己的证书...当然会提示不安全。
尽管我们自己知道,那个域名指向的其实也是这个网站,可是对于大多数人来说这样是不行的...所以,要为另一个同样指向该网站的域名申请自己的证书,并且需要nginx根据情况返回对应证书才行。
申请方式没什么太大区别,还是那个命令,换成新域名去申请就可以了。配置nginx的时候,配置文件里要把一个段落分成两个
比如原先是这个样子
server {
listen 80;
listen 443 ssl http2;
server_name demo1.youdomain.com;
server_name demo2.youdomain.com;
charset utf-8;
ssl_certificate /etc/letsencrypt/live/demo1.youdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/demo1.youdomain.com/privkey.pem;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:5m;
ssl_session_timeout 5m;
keepalive_timeout 75s;
keepalive_requests 100;
if ($scheme = http) {
return 301 https://$host$request_uri;
}
location / {
index index.html index.htm index.php;
}
}
要是申请了两个证书要改成这样
server {
listen 80;
listen 443 ssl http2;
server_name demo1.youdomain.com;
charset utf-8;
ssl_certificate /etc/letsencrypt/live/demo1.youdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/demo1.youdomain.com/privkey.pem;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:5m;
ssl_session_timeout 5m;
keepalive_timeout 75s;
keepalive_requests 100;
if ($scheme = http) {
return 301 https://$host$request_uri;
}
location / {
index index.html index.htm index.php;
}
}
server {
listen 80;
listen 443 ssl http2;
server_name demo2.youdomain.com;
charset utf-8;
ssl_certificate /etc/letsencrypt/live/demo2.youdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/demo2.youdomain.com/privkey.pem;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:5m;
ssl_session_timeout 5m;
keepalive_timeout 75s;
keepalive_requests 100;
if ($scheme = http) {
return 301 https://$host$request_uri;
}
location / {
index index.html index.htm index.php;
}
}
以此类推,申请了几个证书复制几次改下请求域名和证书位置就可以了。然后保存,重载。
6.测试证书续期
尽管Let's Encrypt免费给大家提供证书,可是缺点就是他们的证书有效期只有3个月,每次都进行手动申请实在是太麻烦了。
不过certbot为大家提供了自动续期的方案。首先先来执行下面的命令模拟一下申请证书续期的情况certbot renew --dry-run
等待这条指令结束,会看到它自动模拟更新了所有的证书,模拟结果会在屏幕上显示
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates below have not been saved.)
Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/demo1.yodomain.com/fullchain.pem (success)
/etc/letsencrypt/live/demo2.yodomain.com/fullchain.pem (success)
/etc/letsencrypt/live/demo3.yodomain.com/fullchain.pem (success)
/etc/letsencrypt/live/demo4.yodomain.com/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IMPORTANT NOTES:
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
根据结果可以看到模拟续期成功了。另外说一下,在正式进行证书续期的时候,使用的命令是下面两个里的任意一个certbot renew
certbot renew --quiet
因为,certbot为了节能~会自动检测证书的有效性,会跳过没有被吊销并且剩余有效期大于30证书,不进行更新。上面的命令是为了怕出问题做的测试,有点强制的意思在里面。(不过哪怕你想强制更新也不要用那个命令,尽管它强制申请了,但还是不会保存,下面会说该怎么办)
7.添加定时任务自动续期
成功之后把证书续期和重载nginx的命令加到cron里面去。
先是都知道的crontab -e
然后按照你想要的频率添加进去,比如下面就是每周一的1:30自动进行证书更新,然后再同理加个重载即可30 1 * * 1 certbot renew --quiet
不过建议用每周固定的那天或着每月固定的哪天这种方式添加,不要添加成隔多少天更新一次的那种。因为那样的话,服务器一关机重启,crontab的计数会重新开始,隔的周期太长会错过更新证书失效。
如果你嫌麻烦可以直接抄走我下面这条,意思是每周一凌晨2点30检查一次证书更新,删除上次日志,并且把更新记录写成新的日志存储,再重载服务有错误同样记录在日志里
30 2 * * 1 rm -f /etc/letsencrypt/renewal_log.txt && echo "$(date)" >> /etc/letsencrypt/renewal_log.txt && certbot renew >> /etc/letsencrypt/renewal_log.txt && service nginx restart >> /etc/letsencrypt/renewal_log.txt
添加完毕后...可以crontab -l
查看下已有任务。
如果不放心cron有没有执行,可以写个每分钟输出一次时间的任务试试看,记得删除就好*/1 * * * * echo "$(date)" >>/var/log/datecron.txt
8.强制更新证书
对于某些不喜欢节能设定的人,或者是意外情况必须要更新证书时,可以用下面这条命令certbot renew --force-renewal
不过注意频率,Let's Encrypt是有配额限定的,超过移动频率会被封IP或着这个域名,不再发证书,详细配额见下方官网链接
https://letsencrypt.org/docs/rate-limits/