这样一篇技术向文章,为什么非要写个序呢?

HTTPS ,不就是“申请张证书然后让服务器使用它”的事吗?

刚接触建站时,我也这样认为过,随着姿势解锁和经验累积,发现整个过程存在非常多要考量的细节,最后的完成着实消耗了不少精力和时间。

于是考虑后决定写成一个系列,内容分为三部分:「配置 HTTPS」、「加强 HTTPS」、「启用 HTTP/2」

这是第一篇,本文的章节如下:

  • HTTPS 简介和麻烦的地方
  • 全站 HTTPS 的条件
  • 免费 SSL 证书申请和推荐
  • 公私钥、证书链的格式和作用
  • Apache 下的配置方法
  • Nginx 下的配置方法
  • CDN 的选择和 SSL 证书上传细节
  • 后续工作(重要,百度分享本地化等)

HTTPS 简介和麻烦的地方

近段时间 HTTPS 越来越受到关注,苹果从 IOS 9 开始规定 App 内访问的网络必须使用 HTTPS 协议,刚上线不久的微信小程序也做了强制 HTTPS 的要求,今年 2 月,一个叫做 EFF(Electronic Frontier Foundation))的非营利组织发布报告称, 2016 年全球已有过半的 web 流量通过 HTTPS 传输,所以 HTTPS 还颇有点“山雨欲来风满楼”之势。

HTTPS 是 HTTP 协议的安全升级版,以前 HTTP 明文传输的内容将通过 SSL 层变为加密传输。

每次写文章,都想尽可能地把所有“坑”盘一遍,所以在这一节,先归集那些弄 HTTPS 麻烦的地方:

1. HTTPS 比起 HTTP 多出了 SSL 证书验证环节,会增加客户端和服务端的握手次数,当 HTTPS 开启之初,你可能会发现网站的访问速度,比起 HTTP 慢了很多;

2. 由于多了加解密工作,会增加服务器资源负担,尤其是 CPU 占用;

3. 流行的云存储 HTTPS 流量比 HTTP 贵;

4. 并不是启用了 HTTPS ,传输就不会被劫持,老旧的浏览器多只支持不再安全的加密协议,比如 SSLv2 SSlv3 ,“安全、高效、兼容性好”是个无法定量的标准,为了尽可能靠近它,启用 HTTPS 后还有许多优化工作要做;

5. 另外 CDN ,HTTPS 下的稳定性、节点服务器安全程度、以及是否需要支持 HTTP/2 ,都需要考量和试用,比如腾讯 CDN,虽然安全评分较高(SSLLABS 测试 A-),但还没有开放 HTTP/2;再比如 VeryCloud ,虽然支持 HTTP/2 ,但安全评分超低(F)。

总之,启用全站 HTTPS 紧跟着成本考量和后期优化

全站 HTTPS 的条件

申请一套受各大浏览器信任的 SSL 证书是首当其冲的一环,过程并不复杂,所以就跟证书推荐一起就放到下节,这一节先说服务端的要求。

要启用全站 HTTPS,所有页面加载的资源必须符合 W3C 的 Mixed Content(混合内容)规范。不知道看官对 IE 询问用户是否加载的安全提示,或者 Chrome 左上角的黄色小锁有无印象。

现代浏览器(包括移动端)对 HTTP 来源的图片、视频资源,一般是默认允许加载,但是如果不是 HTTPS 来源的 js、css 等资源不会加载;如果是 IE ,无论是早期的还是较新的,只要出现非 HTTPS 的资源都会弹出不安全提示,然后交由用户决定是否加载。

这种情况就是浏览器识别到了自身认为不安全的 HTTP 资源,而不同时期不同的浏览器又有不同的要求,即使当前图片、视频类资源可以加载,在 HTTPS 日益普及的未来也说不准。

所以,为了避免这里提示安全那里又提示不安全的尴尬境况,让所有的资源请求都走 HTTPS 才是稳妥的办法,即全站 HTTPS。

从 HTTP 过渡到 HTTPS,网站的管理者就可能会面临大量的资源替换工作,最常见的比如:文章里的图片引用、从站外通过 HTTP 引用的 js、css 。

除此之外,HTTPS 使用的是 443 端口,注意开放;

最后用命令 openssl version 检查下 OpenSSL 的安装情况,HTTPS 、HTTP/2 都需要它的支持。

尤其是对于 HTTP/2 ,更应该尽可能把 OpenSSL 升级到最新(截止到本文发布,OpenSSL的最新版是 1.0.2K

免费 SSL 证书申请和推荐

免费 SSL 证书一般是 DV 等级,属于基础级,只验证域名所有权。

但证书被不被浏览器信任,并不是只看收费与否,比如之前一度流行的沃通和 StartCOM 签发的新证书就已经相继被 Moziila ,Google ,苹果封杀。

这里推荐几个 2017 年初认可度比较高的免费证书:

1. 腾讯云可以免费申请 TrustAsia 证书,1 次签发有效期 1 年,传送门

2. 阿里云可以免费申请 Symantec 证书,1 次签发有效期 1 年,传送门

3. 还有拥有众多粉丝的 Let’s Encrypt 免费证书,1 次签发有效期 3 个月。

我还没来得及尝试 Let’s Encrypt(现在用的 TrustAsia),不过仍想重点介绍下。

Let’s Encrypt 是一个发展迅猛的公益组织,它的证书是已得到各大主流浏览器和权威机构支持的,并且不像很多免费证书只包含根域名和 www 二级域名,Let’s Encrypt 允许在一张证书里添加更多域名。

虽然一次签发最多只有 90 天有效期,但有自动续期脚本,配置好后一劳永逸,还有很关键的一点:

Let’s Encrypt 支持加密算法更安全的 ECC 证书签发。

这种证书也有缺点,先进的加密算法牺牲了一些老环境下的兼容性,比如 Window XP、Android 4.x 以下版本就不支持,有关 ECC 证书的详解,我推荐一篇 Jerry Qu 的文章:传送门

Apache 下的配置方法

先上传证书,放置路径自由决定;

找到 Apache 的配置文件 httpd.conf ,如果不知道文件位置,可以用命令 # find / -name httpd.conf 查找。

编辑 httpd.conf ,在大约 411 行找到 #Include conf/extra/httpd-ssl.conf 去掉前面的 # 号;

然后进入 httpd.conf 同目录的 extra 文件夹,找到并编辑 httpd-ssl.conf 文件:

在大约77行找到 DocumentRoot ,把后面的路径修改为网站的目录

在大约78行找到 ServerName ,把后面的网址修改为 你的网址:443;

在大约117行找到 #SSLCertificateFile ,去掉前面的 # 号,后面填上公钥的路径;

在大约125行找到 #SSLCertificateKeyFile ,去掉前面的 # 号,后面填上私钥的路径;

在大约135行找到 #SSLCertificateChainFile ,去掉前面的 # 号,后面填上根证书的路径;

最后重启 Apache,命令 # service httpd restart

Nginx 下的配置方法

先上传证书,放置路径自由决定;

找到网站的 Nginx 配置文件,一般在 Nginx 安装目录的 /conf/vhost 路径下,文件名为:域名.conf

编辑该文件,在原配置的第一行: listen 80; 下,插入如下配置:

listen 443 ssl;
server_name 域名;
if ($server_port = 80 ) { 
return 301 https://你的域名$request_uri; 
} 
ssl on;
ssl_certificate 公钥路径;
ssl_certificate_key 私钥路径;

上面的语句同时还开启了 Nginx 下的 HTTP → HTTPS 301 跳转。

当然,单独写个 443 端口的 server 也是可以得,记得把 301 跳转的语句 return 301 https://你的域名$request_uri; 放在 80 端口的 server,if 的判断句就不要了。

Apache 下的 HTTP 强制 301 跳转 HTTPS 可以在文章「配合CDN进行301跳转完美隐藏源站IP」里找到,就不重复写了。

CDN 的选择和 SSL 证书上传细节

看到这里,也许你已经为爱站申请到了证书,但可能还是一脑子懵逼,因为:

“哪个是私钥哪个是公钥啊?”

“这个 .pem 文件又是干嘛的?”

“为什么这个 .pem 有两组密文啊,内容还是跟两个 .crt 重复的?”

“CDN 叫我上传证书,我上传 .crt 还是 .pem 啊?!”

“麻蛋,只有两个地方可以上传啊,可是我有四个文件,上传哪两张啊喂?!!!”

解决这些疑惑,我推荐一篇言简意赅生动形象的文章,通俗易懂地解释了证书体系,也许文章的比喻不够严谨,但值得一读:传送门

如果实在不想看,伸手党们你就按下面这样搞:

CDN 提供了三个上传入口,分别上传 私钥 .key 、公钥 .crt 、根证书链 .crt,

CDN 只有两个上传入口,那么一个上传的是 私钥 .key ,一个上传的 .pem 文件,即公钥+根证书链。

然后,我们来盘点下当前国内流行的支持 HTTPS 的 CDN 方案:

七牛云,HTTPS 不免费,但提供了云存储服务,可以用来做图床,HTTP/2 ;

又拍云,申请又拍云联盟,免费 1 年,每月 15/GB 流量,超出的费用和七牛相近,HTTP/2 ;

腾讯CDN,新用户赠送 6 个月 50 GB  月流量,HTTP 1.1,HTTP/2 内测中,对网站规模有信心可以尝试工单申请,腾讯的工作人员会进行评估,评估标准未知;

VeryCloud,现在用的,赠送 50 GB 月流量,HTTPS 不稳定,SSLLABS 安全评级低,HTTP/2 ;

360 的 CDN,已被我拉进黑名单,对接后自家浏览器和搜狗浏览器打不开网站,具体可以看我 TTFB 那篇文章,而且也不稳定。

综合来说,如果你不需要 HTTP/2 ,腾讯 CDN 靠谱;

如果想加入次世代协议 HTTP/2 的弄潮大军,又拍云比较合适,就是要手持身份证拍照特别麻烦,我已经准备转战又拍了,毕竟 HTTP/2 才是最吼的 8)

后续工作(重要,百度分享本地化等)

WordPress 的网站启用 HTTPS ,一定要把后台「WordPress地址(URL)」和「站点地址(URL)」中的 URL 起头也改成 https

开启全站 HTTPS(附百度分享本地化)-极客飞船

你可以先在 WordPress 后台改完再去配置服务端和 CDN ,但此时网站就无法访问了;

建议先把混合内容、服务端配置、CDN 弄好后,再通过数据库修改,修改的表项在「wp_options」。

开启全站 HTTPS(附百度分享本地化)-极客飞船

最后,是许多人关心的百度分享本地化。

由于百度分享的资源加载地址 http://bdimg.share.baidu.com/* 不支持 HTTPS ,根据上文提到的 Mixed Content 规范,直接使用会出现问题。

我们要做的是:把原本从外部加载的资源放到自己的服务器上。

这里我已经把本站的百度分享资源打包了,需要的话请自行:百度网盘

下载后解压到网站根目录,然后如下修改百度分享的引用代码:

src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)

把上面原本的这部分改为

src='/static/api/js/share.js?cdnversion='+~(-new Date()/36e5)