全站开启https总结(艰苦历程?)
前言
在搭建完Hexo之后,我就开始思考要不要配置https呢?最后深思熟虑,还是决定上https吧!毕竟现在https已经开始普及,像Chrome、Firfox这些浏览器如果不是https协议的会提示如下图,警告“不安全”什么的。强迫症患者表示看着最不舒服了(逃~
于是我就开始了配置https之路……
2018-12-02更新:添加通配符证书申请方法
SSL证书
选取合适的ssl证书
https = http + ssl,所以要走https协议首先要申请ssl证书。
但是我第一次建站,对ssl证书一点都不懂啊!!哪个ssl证书更好我也不知道,去搜索一翻发现各种说法,最后还是去请教了各位前辈。
经过各位前辈的建议,我了解到了Let's Encrypt,详细介绍我就不说了,这是它在维基百科的资料,然后这是官网
除此之外还有Digicert、SSL For Free、CA Cert。Digicert很贵,但是据某位前辈说似乎大企业喜欢用它的挺多,而且人家还支持签发 .onion 域名的证书(EV)。
看自己需求吧,我最后还是用了Let's Encrypt。
老父亲说这是免费的,但验证过程要在服务器上做,有点复杂。我觉得复杂点没所谓,好用就行。
某群里的前辈说也可以不验证,自签名就好(其实我还没懂哈哈哈,尴尬.jpg);前辈们还说了一种DNS方式验证,不需要架设额外服务;在我问了“Let’s encrypt用standalone还是webroot模式更好”之后(其实这个我也不懂),终于决定用DNS模式,DNS 模式更方便,还可以签通配符证书。
开始获取SSL证书
群里多位前辈介绍了一个在 Linux 上申请let’s encrypt证书的脚本——acme.sh
acme.sh脚本
Linux服务器下使用acme.sh脚本是申请let’s encrypt证书最便捷的方式,比官方推荐的certbot脚本工具要方便强大的多。好处是对环境要求较低,路由器上 busybox ash 都能跑,只需要使用到 curl 等少数几个外部程序
安装文档: https://github.com/Neilpang/acme.sh/wiki/说明
前提条件
- 拥有一个域名,例如 mydomain.com (在国内主机的用的话,还需要通过ICP备案)
- 确定二级域名,并且在域名服务器创建一条A记录,执行云主机的公网IP地址。www.mydomain.com指向xxx.xxx.xxx.xxx的IP地址
- 要等到新创建的域名解析能在公网上被解析到。
- 据说国内的域名提供商对letsencrypt的支持非常差,但是据说现阶段用dnspod解析的域名还没碰到问题。我用的是国外的Cloudflare解析我的域名,但是经常被墙(想骂人…),移动表示大多数都没有体验= =,联通情况好一点。
安装acme.sh脚本
执行一下命令后重新ssh登录服务器即可:
|
|
该命令会把 acme.sh 安装到你的 home 目录下: ~/.acme.sh/,一般会自动创建环境变量,后期直接命令行输入acme.sh即可。
使用DNS API申请证书
(推荐配置使用API的方式,否则每隔三个月,仍然需要重新验证DNS TXT记录)
创建DNS API的Key及Secret
参考:
acme.sh 目前支持 cloudflare, dnspod, cloudxns, godaddy 以及 ovh 等数十种解析商的自动集成.
【例子一】域名由Cloudflare提供解析的网站,使用CloudFlare域名API自动颁发证书
-
以 Cloudflare 为例, 你需要先登录到 Cloudflare 账号才能获得API密钥, 都是免费的。
Cloudflare-Api-1
Cloudflare-Api-2 -
然后在Linux下使用acme.sh命令申请证书:
命令使用参考:Linux 下使用 acme.sh 配置 Let’s Encrypt 免费 SSL 证书 + 通配符证书 先导入密钥和邮箱:
1 2export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" export CF_Email="xxxx@sss.com"我们现在发行一个证书:
1acme.sh --issue --dns dns_cf -d example.com -d www.example.com --accountemail query@goodsrv.com--accountemail是指定帐户电子邮件,仅对--install和--update-account命令有效(待验证,因为我执行命令时并没有带上该参数)。输入命令后回车,需要等两分钟,终端会有倒计时。
倒计时结束后,执行命令:
1acme.sh --renew -d example.com -d www.example.com
补充:获取 Let’s Encrypt 通配符证书
通配符证书,英文 Wildcard Certificate 国内黑话叫做野卡,经过一个月的跳票后,Let’s Encrypt 目前已经支持通配符的证书,同样 acme.sh 也是支持的,和多域名证书不同,通配符证书必须使用 DNS TXT 记录验证方式,我们以 example.com 和 *.example.com 为例
|
|
记得
*.example.com加单引号
如果你的 DNS 提供商支持 API,你也可以直接使用 API 而不需要手工修改 TXT 记录,详细用法请见这里
以 CloudFlare 为例:
|
|
生效后给证书续一秒
|
|
然后后面你想要一个二级域名(如:abc.example.com)的时候就不用再申请了,只需要在DNS添加A记录等它生效就可以用了。当然,下面的安装证书和配置站点(Nginx)步骤还是要做的😂
安装证书
|
|
注意:
/etc/ssl/example.com/的所有者以及用户组必须为当前用户,否则后面installcert的时候会提示没有权限,可执行如下命令,后面可更改回原来的所有者和用户组:
1 2 3 4 5#更改所有者和用户组 sudo chown $USER:$USER -R /etc/ssl/example.com/ #查看指定文件夹的权限、所有者和用户组 ls -l /etc/ssl/ ls -l /etc/ssl/example.com/- (一个小提醒, 部分服务器系统用的是
service nginx force-reload, 不是service nginx reload, 据测试,reload并不会重新加载证书, 所以用的force-reload)- Nginx 的配置
ssl_certificate使用/etc/nginx/ssl/fullchain.cer,而非/etc/nginx/ssl/<domain>.cer,否则 SSL Labs的测试会报Chain issues Incomplete错误。--installcert命令可以携带很多参数, 来指定目标文件. 并且可以指定 reloadcmd, 当证书更新以后, reloadcmd 会被自动调用,让服务器生效.- 值得注意的是, 这里指定的所有参数都会被自动记录下来, 并在将来证书自动更新以后, 被再次自动调用.
mkdir的-p参数解释: -p, –parents 可以是一个路径名称。此时若路径中的某些目录尚不存在,加上此选项后,系统将自动建立好那些尚不存在的目录,即一次可以建立多个目录; mkdir命令参考:https://www.linuxdaxue.com/linux-command-intro-mkdir.html
更新证书
目前证书在 60 天以后会自动更新, 你无需任何操作. 今后有可能会缩短这个时间, 不过都是自动的, 你不用关心.
更新 acme.sh
目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此 acme.sh 也经常更新以保持同步.
升级 acme.sh 到最新版 :
|
|
如果你不想手动升级, 可以开启自动升级:
|
|
之后, acme.sh 就会自动保持更新了 你也可以随时关闭自动更新:
|
|
应用实例
配置Nginx使用证书开通https站点
- 生成Perfect Forward Security(PFS)键值
Perfect Forward Security(PFS)是个什么东西,我也不清楚,中文翻译成
完美前向保密,反正是这几年才提倡的加强安全性的技术。如果本地还没有生成这个键值,需要先执行生成的命令。
|
|
生成的过程还挺花时间的,据我查到的资料,据说参数为2048的要4分钟左右,还受服务器性能影响,此时不妨做点其他东西。
(时间一分一秒的过去…)
好了,PFS键值生成了,我们用ls命令来确认一下目录下是否生成了dhparam.pem文件,确认完毕就可以执行下一步了。
特别说明: 一定要确认文件是否已经生成!!!在这一步我原本是执行
openssl dhparam 2048 -out dhparam.pem,不知道为什么执行了多次都无法生成dhparam.pem文件,后来换了个目录执行了多次openssl dhparam -out dhparam.pem 2048才成功,这是后面配置完Nginx后无法重新启动Nginx服务了,我输出日志才发现的,具体后面会说。
-
nginx配置使用证书。 编辑你的Nginx配置文件,如:
/etc/nginx/sites-available/<your-nginx-config>☆☆修改配置文件前建议先备份☆☆ 可以通过Mozilla SSL Configuration Generator自动生成对应的参考配置修改http对应的server模块:
1 2 3 4 5 6 7 8 9 10 11server { listen 80; listen [::]:80; server_name example.com; #return 301 https://example.com$request_uri; if ( $scheme = http ){ return 301 https://$server_name$request_uri; } root /var/www/html/example.com; index index.html index.htm; }return 301 https://$server_name$request_uri;是强制http跳转https在配置文件中添加https的server模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28server { listen 443 ssl; server_name example.com; #charset utf-8; location / { root /var/www/html/example.com; #index index.html index.htm; } #root /var/www/html/example.com; index index.html index.htm; access_log /var/log/nginx/example.com_access.log; error_log /var/log/nginx/example.com_error.log; ssl_certificate /etc/ssl/example.com/fullchain.cer; ssl_certificate_key /etc/ssl/example.com/example.com.key; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_dhparam /etc/ssl/example.com/dhparam.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 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:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK'; ssl_prefer_server_ciphers on; }总的样例内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40server { listen 80; listen [::]:80; server_name example.com; #return 301 https://example.com$request_uri; if ( $scheme = http ){ return 301 https://$server_name$request_uri; } root /var/www/html/example.com; index index.html index.htm; } server { listen 443 ssl; server_name example.com; #charset utf-8; location / { root /var/www/html/example.com; #index index.html index.htm; } #root /var/www/html/example.com; index index.html index.htm; access_log /var/log/nginx/example.com_access.log; error_log /var/log/nginx/example.com_error.log; ssl_certificate /etc/ssl/example.com/fullchain.cer; ssl_certificate_key /etc/ssl/example.com/example.com.key; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_dhparam /etc/ssl/example.com/dhparam.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 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:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK'; ssl_prefer_server_ciphers on; }
配置文件没有问题的话执行systemctl reload nginx,然后在浏览器打开http://example.com, 如果正常跳转到https://example.com,就算成功了。 如果是chrome浏览器,在地址栏点击绿色小锁的图标,可以查看证书的详情,如图。
此步骤遇到的难题
-
这里要注意的是如果你是
Nginx+Cloudflare,那么Cloudflare的"Crypto—SSL"要设置成Full(strict),否则会导致example.com将你重定向次数过多的情况,默认是Flexible。CF设置如图:
cloudflare config of starting https with nginx -
这里还有个坑就是前面说的无法生成
dhparam.pem文件导致无法重载Nginx。一开始我还没发现,一直在以为Nginx配置文件哪里错了,后来sudo journalctl -xe输出日志才发现Nginx找不到dhparam.pem文件: 用
nginx cannot found dhparam.pem-1 ls命令可以发现目录下并不存在dhparam.pem文件: 于是我又执行了几次
nginx cannot found dhparam.pem-2 openssl dhparam 2048 -out dhparam.pem,结果还是一样,而且过程竟然只需要1分钟不到。如图: 察觉到不对劲之后我马上去找了跟
nginx cannot found dhparam.pem-3 dhparam的资料,后来在一个博客上发现他的命令顺序跟我不一样,这个文件存放目录也跟我不一样,于是我就把命令改成openssl dhparam -out dhparam.pem 2048和改目录到example.com(此时该目录权限还是$USER的)再试了几次,第一次是不行的,执行多几次后突然就成功了。如图: 可以发现此次执行命令时间十分的长,我等了大概5分钟才执行完毕。 然后我们再用
nginx cannot found dhparam.pem-4 ls来看看目录下的文件,可以发现文件已经生成:
nginx cannot found dhparam.pem-5
测试证书
如果是网站的话,可以使用第三方网站工具测试自己网站的HTTPS配置的安全性
-
SSL Lab就是个不错的选择: https://ssllabs.com/ssltest/analyze.html?d=example.com 这是我的测试结果,都是A哦!!
SSL Lab Server Test -
也可以在Linux下使用openssl命令查看证书的过期时间
1openssl x509 -noout -dates -in /etc/ssl/example.com/example.com.key