rosu 的博客

启用 HTTPS 札记

2016-08-11

1.0 什么是 HTTPS?

  1. HTTPS == HTTP + SSL

  2. 数字证书认证机构 数字证书

1.1 客户端通过 HTTPS 和服务器通信过程

经过上面的一些资料的补充,相信你已经对 HTTPS 有了基本的认知了,下面我简介一下 HTTTPS 通信、证书和认证的一些细节

  1. CA(数字证书认证机构)和你服务器的关系

    • 你向 CA 递交你域名的证书申请;
    • CA 验证你对你的域名和服务器有控制权:可能是发邮件或在你的服务器绑定证书
    • CA 向你发放证书
    • 将证书保存在服务器上(针对于 VPS)
    • 当用户访问你的网站时,你的服务器会先向用户(的浏览器)发送你的证书以及公钥
    • 你用户的浏览器根据保存在浏览器中的 根受信任的颁发者列表 查询你网站的可信任信息并验证
      请看下图:
      201012272252173749.png
      图片来自 浅谈 https\ssl\ 数字证书
  2. 通信过程(SSL 加密过程)//假设用户为 A,你的网站 B

    • B 生成私玥和与之对应的公钥(不同用户生成不同公玥)
    • A 使用 B 的公钥加密信息发送给 B
    • B 使用密钥解密
      值得注意的是,上述中,只有与之对应的密钥才能解密,而又因为不同客户端得到了不同的公钥,故而别人无法使用其他密钥进行解密。
      如果你有一个疑问,那就是『HTTPS 能否被劫持吗?』
      那么我们假设黑客(他的服务器为 C)想要获取我们的加密信息内容,他大概可以这么入手(肯定有其他方式,然而我不是黑客我想不到…):
  • 获取私玥

    • 反向解密出私玥:目前基本不可能做到…
    • 拿下 CA: 获得所有其名下的证书、私玥。基本不可能,但是还是该选一家靠谱的 CA 才行…
  • 欺骗服务器和浏览器

    • 第一种方式:C 作为中间人,替换服务器发下的公钥为 C 的假公钥;C 接受客户端利用假公钥加密的信息并使用自己的私钥解密。
    • 第二种方式:大致同上,但是此时 C 和服务器形成 HTTPS 然而客户端和 C 只是 HTTP,也就是剥离 ssl 层。
  • 解密(一定需要私钥)
    我就不班门弄斧了,总之就是现在,比较安全就是了。
    你可以参看下面的资料:

  1. https 可能被这样劫持吗
  2. 使用 HTTPS 的网站也能被黑客监听到数据吗?
  3. 基于 SSLStrip 的 HTTPS 会话劫持

部署 HTTPS

部署 HTTPS 有简单也有稍显麻烦,更有一劳永逸的;我尝试 雨露均沾 一下…
同时,我下面写的一般都是 DV 证书,也就是域名核准证书。
这一类证书 只验证域名所有权,加密链接;并不会验证申请者的真实身份或组织
这是比较简单的一种方式。一般来说,个人网站并不太在意(如果你的网站需要交易除外)。但是也有一些 CA 不看好 DV 证书,因为这样的证书降低了犯罪成本(罪犯们可以随意申请证书以增加页面的可信度)。
但是另一方面,这样也可以普及 HTTPS 的使用,有利有弊。
最重要的原因,这是免费的…
而且,主流浏览器的状态栏都会显示小绿锁。
DV 和 OV 型证书在用户查看证书的详情是,OV 型证书会在证书的 Subject 中显示域名 + 单位名称等信息;DV 型证书只会在证书的 Subject 中显示域名。

2.1 商业 CA 的免费 DV 证书申请

这一类算是比较简单的,步骤都可以简述出来:

  1. 递交申请
  2. 验证域名所有权
  3. 服务器绑定证书
    比较常见 DV 证书提供方有 沃通 Strat sslLet’s EncryptCOMODO

update 2016-11-11:

谷歌和火狐相继宣布停止信任沃通和 StartCom 的证书,在 2016 年 10 月 21 日后被签发的证书都将不被信任

  • 现在阿里和腾讯都有赛门铁克的一年免费 DV 证书,推荐使用这一个,很简便
  • 或者使用 Let’s Encrypt 申请证书

2.2 利用 CloudFlare 部署 HTTPS

为什么要把这个单独出来讲呢?因为我觉得 CloudFlare 确实比较良心和方便…(以至于我一直被坑…

  • 此处的 CF 颁发的证书属于自签证书,只被 CF 自己认可
  • 如果你不是使用 CF 的 CDN 的话,这个证书的没法使用的

// update 2017 年 7 月 7 日 10:34:07

推荐直接使用 Let’s Encrypt 申请证书,可以自签也可以选择一键脚本

// end

2.2.1 利用 CloudFlare 签发并部署 DV 证书

  1. 把域名托管在CloudFlare

  2. 进入『Crypto』
    sp160812_183102.png

  3. 把『ssl』选项设为『FULL』或者『FULL(strict)』
    sp160812_183327.png
    注意:在这里解释一下三个选项的意思

    • Flexible
    • 浏览者到 CDN 是使用 HTTPS 的,但是 CDN 到你的服务器则是 HTTP
    • 注意!此时 CND 会强制使用 HTTP 访问,意味着如果你在你的服务器使用 301 跳转到 HTTPS,就会导致无限的重定向!
    • FULL
    • 浏览者–>HTTPS–>CDN–>VPS
    • CF 不会验证你的证书
    • 一般适用于自签证书
    • FULL(strict)
    • 浏览者–>HTTPS–>CDN–>VPS
    • CF 会和 CA 验证证书
    • 一般适用于 CA 签发的证书

    无论你选择了是『Full』或是『FULL(strict)』
    如果你在添加域名 (add site) 的时候,选择了他的 CDN 加速服务比如下图:
    sp160813_110954.png
    此时你在浏览器的证书详情里,显示的会是他的 CND 的域名。你是看不到你的域名的:
    sp160812_100948.png
    而且此时,你去 SSL 评分 的时候,也只会显示此 CND 的评分:
    sp160812_102305.png

  4. 选择『Create Certificate』

如果你选择的是 CF 的证书(如下图),是一种 CF 自己发行的 TLS 证书,安全系数并不高。最好自己购买上面说的那些。

sp160813_112021.png

  1. 选择『ECDSA』算法,并且选择你的服务器类型。这里我选了 Nginx。

sp160813_112245.png
sp160813_112344.png

那个证书期限默认就行,你也可以自己定义一个日期。无所谓。
接着你会得到一个根证书 (Original Certificate) 和一个私钥(Private Key)。文件格式选择 PEM 即可:

sp160813_115249.png
复制里面的字符,保存到名字相对应的 pem 文件中,或者直接下载也行。
然后上传文件到你的 nginx 服务器
接着进行:

  1. Nginx 服务配置

思路就是,

  • 把原来的网站端口(默认 80 端口)改为 443 端口
  • 开启 SSL
  • 设置证书和私钥
  • 将 80 端口重定向至 443 端口,强制开启 HTTPS
    实施:
    由于我的网站配置是在单独的配置文件中的,位于/usr/local/nginx/conf/vhost/www.rosuh.me.conf,所以我直接修改这个文件。如果你是把网站服务写在 nginx 的主配置中的,那就修改/usr/local/nginx/conf/nginx.conf
  • 修改端口
1
2
3
4
5
6
7
8
9
10
11
#原来的配置 
server{
listen 80;
server_name ...
...
}
# 修改之后
server{
listen 443;
server_name ...
}

原来通过 80 端口(http)的访问已经失效了,必须指定 443 端口访问才行。

  • 开启 ssl 并进行基础配置
1
2
3
4
5
6
7
8
9
10
11
#从上面的配置接下去,而不是重新写一个 server
server{
listen 443;
#如果你还想你的 http 能正常使用的话,可以加上 80 端口并存
# listen 80;
server_name ...
ssl on;
ssl_certificate /home/www/ssl/OriginalCertificate.pem;
ssl_certificate_key /home/www/ssl/PrivateKey.pem;
...
}

这只是基础配置,评分不高,但是先测试是否可行。

1
service nginx -t &&service nginx -s reload
  • 重定向 80 端口
    完成至此,也只是让 https 可用,也就是用户必须再你的域名前面加上 https 才行,这样很不友好并且不安全。同时此时你的 http 不可用哦,因为我们把 80 端口删掉了,你也可以加上 80 端口,这样会保证 https 不可用的时候 http 还能正常使用。
    如果是不需要 80 端口,想强制 HTTPS 访问的,就需要
    配置重定向:
1
2
3
4
5
6
7
server {
listen 80;
server_name www.rosuh.me rosuh.me;
location / {
rewrite ^/(.*)$ https://rosuh.me/$1 permanent;
}
}

至此,基础配置 HTTPS 就算完成了。照道理现在应该可以的了。
下面介绍另一种方法:

2.2.2 使用 Let’s Encrypt 证书部署 HTTPS

这一步和上述有所不同,你需要自行创建私钥和证书申请文件。

动手能力强的可以选择下面的教程中的自签,如果想省事可以直接使用 amce.sh 一键脚本。

acme.sh

对于自己动手,我们的思路是:

  1. 创建私钥和申请文件
  2. 验证所有权
  3. CloudFlare 设置
    注意:在进行之前,我假设你已经把域名托管在 CloudFlare,为什么要这样做呢?后面我会解释的。

这些步骤网上教程很多,我也是从网上的前辈那里学习的,尚不能自己完整地写出来。为了避免写错,耽误各位,还是请诸君务必自行移步到下面的网址查看
Let’s Encrypt,免费好用的 HTTPS 证书
这位作者的教程很详尽,并且很完整;同时他的博客内有很多文章都是很棒的,对我们的此次行动有很多指导意义。
我狗尾续貂一下,关于上面文章中有讲过两个可能发生的错误的一些解决方法:

  • 『提示没有找到 openssl.cnf』
    由于环境配置不一,可以使用 find 命令进行查找:
1
find / -name openssl.cnf

然后替换原来教程的命令行中即可

原作者也说了,是因为域名在国外无法解析。我发现也是这个原因,所以我才在开头说,要把域名托管在 Cloudflare 上。并且由于域名 DNS 服务器换了之后,需要一定时间更新缓存,所以需要耐心等待才行…

  • 『crontab not found』
    crontab 没有安装的缘故,使用下面命令进行安装:
1
yum install cronie

接着我们要进行 Cloudflare 的设置才能正常访问,并且获得测试的正确结果。
或者在申请完证书之后,就把域名 DNS 修改为其他的服务商,比如阿里。

  • 进行 ssl 评测的必要条件
    • 没有使用 CDN
    • Cloudflare 的 ssl 选项选择『off』
      具体可以参照我前面的图片。
  • 正常访问
    • 可以开启 CDN
    • SSL 选项不能选择『Flexible』,此时无论如何你都无法使用 HTTPS 访问你的网站,会造成 301 重定向循环
    • 最好开启 HSTS,如果你的 DNS 修改了,那就自行在 nginx 配置中加入
      sp160813_150841.png
      HSTS 指的是,只要该用户曾经使用过 HTTPS 链接你的网站,那么以后就会一直使用 HTTPS 链接。如果你证书过期了…就不能连上了。
      注意:在 Cloudflare 的『OverView』选项中:
      sp160813_151241.png
      如果你不需要 Cloudflare 的其他功能,只想让他实现一个 DNS 的功能,那就选择『Pause』,该选项会停止他的其他服务。

现在,大致可以了。你可以先去评分,然后完善你的配置。
可以同样参看 Jerry Qu 的配置:
本博客 Nginx 配置之完整篇


一些额外的补充:
如果你是用的是 wordpress 的话,相信你需要迁移一些文件,并且修改一些设置。
你可以参看:
WORDPRESS 全站开启 HTTPS 方法


年轻时犯的错误

最初作为一个连 nginx 是什么的年轻人,折腾这个小绿锁确实用了一些时间,吃过一些苦头…

  1. 不知道什么是 HTTPS
  2. 不理解 CA、证书、公钥和私钥之类的基础知识
  3. 不懂 nginx 配置里都是什么意思
  4. 不理解 DNS 服务商、CDN 和一些常识

不过解决的方法归结起来就一句话?

『不会就谷歌』


一些你可能有用处的参考资料:

  1. 浅谈 https\ssl\ 数字证书
  2. 关于启用 HTTPS 的经验分享
  3. SSL 的公钥、私钥、证书都有些啥后缀?

此片博文是我自己的经验总结,难免有所缺漏和错误,敬请指正,在此先行谢过。

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章