似乎不少使用国外主机的站长都想弄个 https:// “玩”,但是许多人对 SSL/TLS、HTTPS、证书等概念了解有限,而中文互联网上相关的教程也不是很完备,各种杂乱。正好,本人这几天花了点时间研究了一下,给自己的站也部署了 HTTPS,写成这篇《Apache + WordPress + SSL 完全指南》,以飨中文读者。本文较长,但是我会尽量写得清楚明白的。 一、基本术语及证书原理介绍本部分有点枯燥,不愿意读的读者可以直接跳过。以下出现的缩写鼠标悬浮于上可查看全称。 HTTPSHTTPS 就是“超文本安全传输协议”,通俗地说就是建立在 SSL/TLS 上的 HTTP。 SSL/TLS理论上讲这是两个协议,后者是前者的继任者,但其实 SSL 3.0 和 TLS 1.0 的差异很小,所以两者很多时候是混为一谈的……这两个都是传输层协议,在他们的基础上可以建议应用层的协议如 FTP 和 Telnet,上面说的 HTTPS 就是建立在 SSL/TLS 基础上的 HTTP。 证书这里的证书主要指使用公私钥对加密的证书。下面主要会涉及到两种证书,一个是 S/MIME 证书,另一个就是 SSL/TLS 证书了。前者可以用在电子邮件上,这里用作“服务器身份识别”,可以理解为取代传统的“用户名+密码”的认证方式的一把“钥匙”。后者一般用于服务器加密(网页、邮件服务等),也就是我们部署 HTTPS 时所必须的。 本文出现的证书都是用公私钥加密的证书。这涉及到 [[非对称加密]] 技术,每张证书都由一个公钥和一个私钥组成,两个拼在一起才是一套。其中,正如它们的名字所暗示的,公钥是可以随便发给别人看的,而私钥一定是要保密的,如果私钥被偷了,后果很严重。 信任链与 CACA 就是“数字证书认证中心”,是证书的签发机构。证书的世界里有一套信任体系,信任了一家机构之后,此机构签发的证书都是受信的。在我们的操作系统和浏览器中,内置了几家靠谱的 CA 的根证书,并列为可信任的证书。而这些 CA 签署的证书,由于信任链的关系,也是默认被信任的。比如中国招商银行的网银页面就是用的 VeriSign 签署的的证书。由于 VeriSign 是一家老牌的靠谱 CA,大部分操作系统和浏览器默认都是信任 VeriSign 的根证书的,当然也就默认信任招商银行用的证书了。 如果有一家 CA,比较年轻,发展得还不够大,那么就会面临有的地方信任,有的地方不信任的问题。比如 CACert.org 就是这样一家 CA。这是一家靠社区驱动的 CA,它的根证书受到 Arch Linux 等一些 Linux 发行版的信任,但是却不受 Windows 和 OS X 的信任(完整的受信任列表见这里),所以它的网站(用了它自己的证书)若是用 https:// 浏览的话(点击这里),一些 Linux 用户会毫无压力地进入,而 Windows 和 OS X 用户则会看到证书警告说该网站的证书不受信任。以下两张截图便显示了这一点: 而如果有一家 CA 完全就像街头的“办证”广告那样完全胡来,那自然是没有任何一家去信任它的证书了,比如下面这个: 大家都懂的…… 不过需要说明的是,如果你使用自签名证书的话,对用户来说默认都是不受信任的。 二、部署 HTTPS 的前提条件以下是部署 HTTPS 的前提:
三、自签名证书虽然不一定受信,但是证书的确是人人都可以自己制作的。有的时候,我们使用 HTTPS 只是为了数据的加密,仅供自己使用,不用管别人信任与否,这时候就可以用到自签名证书。在这种情况下,你可以把自己创建的证书加入到自己的桌面电脑的信任列表,这样就不会再有错误提示了。 Apache 的文档中有 Creating self-signed certificates 这一节教你怎么创建自签名证书,简单明了,十分傻瓜:
用包管理器安装
命令,按照提示输入一个 Common Name(CN,保持和主机名相同),便能按照
前面那段是私钥,后面那段是证书信息和公钥。这份证书默认的有效期是 3650 天(十年)。 其实刚才那个傻瓜式的命令实质上是执行了这个:
各参数的意义:
执行这个命令会让你输入一系列信息,比如 Common Name (CN)、公司名、地理位置、联系方式等,除了 CN 必须要和网站域名匹配之外,其他可以按照你的喜好自由填写。
证书生成好后,便是在 Apache 的配置文件中指定它了。具体的配置文件写法可以参考它自带的
并且如果按照上文,把公钥和私钥放在同一个文件里的话,那只要提供 SSLCertificateFile 就好了,后面的 KeyFile 不用填(保持它们的注释状态)。
保存配置文件后,用 四、第三方签名证书虽然自签名证书默认是不受操作系统或浏览器的信任的,但是这并不影响它能够加密传输内容的本质。自签名证书给自己用是足够了,如果嫌证书警告烦人的话,自己添加为信任就好了,甚至在一小撮人中用也是足够了——你把证书发给你的朋友们,让他们也设为信任,这样他们访问你的网站的时候也不会弹警告了。但是如果要全世界大部分人访问你的网站的时候都不会弹证书警告的话,就要找一些靠谱的第三方 CA,让它们帮你签名证书,由于大部分人的操作系统或浏览器都是信任这些靠谱 CA 的,所以由他们签名的你的证书也是受信任的,这样访问你网站的时候就不会弹证书警告了。 注意:第三方签名证书不代表比自签名证书的加密更强悍更可靠!TLS 的加密强度由加密的位数决定,与证书是谁签名的无关。找第三方签名只是为了不弹证书警告。如果你只是自己用或是一小撮人用的话(思路提醒:twip),用自签名就足够了。 要使用第三方签名证书,首先同样要创建私钥:
各参数含义:
生成好了之后用一些图形化的证书查看器查看大概是这个样子的(当然,指纹肯定不一样……)
然后你也得告诉第三方 CA 你的 CN、地址、联系方式等,这时需要使用 Certificate Request,就是“证书请求”,它是私钥和证书信息的整合,把它交给第三方 CA,他们可以读取这个文件中的私钥和证书信息,然后帮你签名。这个 Certificate Request 文件的扩展名一般用 在刚才私钥的基础上生成证书请求的命令是这个:
执行了之后也会要求你输入证书的信息,然后把最终生成的结果放到 ssl.csr 中。如果用文本编辑器打开这个文件,看到的是类似这样的东西:(我省略了一部分字符)
把这个文件传给 CA,他们签名之后会给你颁发公钥证书,然后把它添加到 Apache 的配置文件中了:
因为这是第三方 CA 签名的,所以要有一个把你的证书和它的根证书相连接的过程。如下图: 那个 ChainFile 就是中间那一环。当然了,正如 KeyFile 可以和主证书文件合并一样,这个 ChainFile 也是可以和主文件合并的,这三个全部首尾相连地并成一个文件也是没有问题的,这样就只要填一个 SSLCertificateFile 就好了。 改好配置之后,像上面自签名那样,也重启一下 Apache,就可以用 https:// 协议访问了。并且,由于是大家都信任的靠谱 CA 签名的,这样的证书是不会弹证书警告的。 五、WordPress HTTPS 免插件部署指南解决“混合内容”问题这一节主要讲一下 WordPress 的 HTTPS 实现。在 WordPress 的插件库中,有一个叫 Force SSL 的插件,它的作用是当用户用 https:// 访问的时候,实时解析页面中所有的 URI,把 http:// 换成 https://。本来我觉得那插件还是不错的,后来我把 php 的内存限量稍微改小一些,就大量出现 500 错误,一看错误日志,竟然全是那个插件“试图分配超过限额的内存”,这才觉得这插件实在太耗资源了!所以我果断删除了那个插件,开始尝试无插件实现 WordPress 的 HTTPS 访问。 如果按照上面的教程,把证书什么的都设置好了的话,这时候 WordPress 已经可以通过 https:// 协议访问了,但是有问题:页面中的图片、CSS、JavaScript 的 URI 都是 http:// 的,所以会有“混合内容”的问题,在 Chromium/Chrome 里是一个难看的红叉叉(高危内容,如 JavaScript)或灰色的锁上有个黄三角(低危内容,如图片),在 Internet Explorer 里则是显示为“混合内容”,弹出大量烦人的警告窗口。那个 Force SSL 插件的两大作用之一就是把这种资源的 URI 改成 https:// 的。 但是,让我们手工来改吧。这里要介绍一下“协议级相对路径“,例子可以见 Google HTML/CSS Style Guide 的建议:
把资源的 URI 省略掉协议,就可以实现“相对协议”了,比如把一个链接写成: 具体怎么实现呢?很简单,改主题……看看你的博客首页的源代码的头部和尾部,一般那些 CSS、JavaScript 就放在这里,认准它们的样子,再到主题文件里去找到它们对应的代码,比如源代码中有这样的:
在主题的 header.php 中可以发现对应的代码:
那么直接把它改成这样就好了:
没错,就是这样,把 URI 由动态的 PHP 函数换成静态的协议级相对链接。当然,由于 WordPress 的主题千变万化,可能还有其他的资源如 JavaScript 甚至糟糕的 swf 等,要根据不同主题的实际情况进行修改。 除了主题自带的资源,还有一些插件可能会引用一些 JavaScript 什么的,这也需要在插件的文件中进行修改。大致思路也是根据 HTML 源代码,去找 PHP 代码,然后把里面的函数换成带有实际地址的“协议级相对链接”。
改完了 CSS、JavaScript 等“高危内容”之后,Chrome/Chromium 的协议图标会从 变成 ,不过,依然是有提示“混合内容”的标识,这主要是页面中的一些图片元素还是使用的 http:// 的 URI。如果你的目标是让它变成 的话,那就必须要解决这个问题。要解决这个问题,比解决 JavaScript 和 CSS 要复杂一些。插件中的图片什么的,可以通过把插件中的函数改掉,使其变成“协议级相对路径”来解决。但是已经发表的文章中的图片,就只能一篇篇改了。文章中图片不多的话,只需一篇篇编辑,然后在图片的属性中把 强制跳转?选择性跳转?如果顺利完成了上面的步骤,那么现在你的 WordPress 是既可通过 http:// 访问,也可通过 https:// 访问,但是,如果希望 http:// 的访问跳转到 https:// 呢?这就需要用到 mod_rewrite 了。由于这篇文章是针对 Apache 用户的,所以 nginx 的规则就不提了。
首先要确认 Apache 开启了 mod_rewrite(默认安装是不开的),如果没有开启的话,需要使用
如果有服务器的完全权限的话,可以在服务器的配置文件中加入以下代码,如果不能编辑配置文件的话,那在站点的目录中添加 .htaccess 文件加入以下代码也行。当然,站点配置中要设置 AllowOverride,才能使站点目录中的 .htaccess 起作用:(请把
这段代码的意思是说:当检测到 HTTPS 未开启( 现在再访问 http:// 的 WordPress 的话,全部会自动跳转到 https:// 版本的了。但是这样做有两个小问题:
对应的解决方法自然也是有的,比如这样:(这段代码参考了 LvWind 的博客。请注意把
这段代码比刚刚那段多加了一个判断条件,即判断访客的 User Agent 是否是搜索引擎或者 IE 用户,如果不是,那才跳转到 https:// 版的页面。注意,这里面是不包含 Google Bot(Google 的爬虫)的,在因为 Google 本身就是能抓取 https:// 站点的,没必要重定向。而 IE 用户则是像其他的非 Google 的搜索引擎一般看待了,保持不跳转。 另外,使用 FeedBurner 的用户也需注意,FeedBurner 是不支持 SSL 的,所以上面的 UA 判断中也有 FeedBurner 的身影。 六、申请 StartSSL 免费证书虽然自签名证书和第三方靠谱 CA 签名的证书都能起到加密的作用,但是自签名的最多自己用用,而 WordPress 上用自签名证书就不太好了。这就需要第三方 CA 签名的。但是大部分靠谱 CA 签名的证书都是收费的,而且价格不是很低。好在,还是有人想打破这个垄断的,CACert.org 和 StartSSL 就是两家提供免费 SSL/TLS 证书签名的 CA。前者是开源社区弄的,所以不少 Linux 发行版都承认这个证书,但是在 Windows 里什么的就比较悲剧,比如一台 Windows 7 的电脑访问 https://cacert.org/ 就会提示证书错误,但是一台 Ubuntu 12.04 LTS 的电脑就没有问题。 而 StartSSL 受到承认的范围就稍大一些了,现在主流的操作系统和浏览器中,只有 IE6 不支持,所以比较适合我等穷人来部署 HTTPS。 StartSSL 是以色列公司 StartCom 旗下的 CA。申请免费的证书并不复杂,甚至比上面介绍的自己生成还要简单,因为它甚至提供了在线生成私钥的功能,连自己生成私钥都免了。 至于 StartSSL 的申请流程么,网上似乎是有很多的,但是不知是不是年代久远的关系,都用要审核的一条路子,太麻烦,以下是免审核申请 StartSSL 免费证书的方法。 使用 Chrome/Chromium 或者 Firefox(其他浏览器可能会有问题)打开 StartSSL Control Panel,这里有三个选项,分别是 Authenticate、Sign up 和 Express Lane。第一个是登录认证用的,第二个是注册账号,第三个是“捷径”。如果选择 Sign up 的话是要人工审核的(可能会被拒绝),而如果你只是想申请一个免费的 SSL/TLS 证书的话,直接点 Express Lane 就好了。点进去之后会让你填一张个人信息表,这个要真实填写。完成之后就会提示你安装一个证书,注意,这个证书是 S/MIME 证书,而不是我们要申请的 SSL/TLS 证书。这个证书是安装到浏览器里的,是用户登录 StartSSL 网站用的,只是一个登录网站时的凭据,和最终我们要用在服务器上的证书完全无关。该网站不是用传统的用户名 + 密码的方式登录的,而是用这个证书进行登录,如果丢了这个证书的话,就相当于把用户名密码忘了,得要重新申请才行。StartSSL 会提示你备份这个证书的,从浏览器中导出就可以了。如果要在别的电脑上或是别的浏览器里登录这个 StartSSL 网站的话,需要把这个导出的证书复制到那个电脑上才行。 接下来是登录,登录的时候会提示选择证书: 当然是确认了,然后就可以登录到 StartSSL 的控制面板了。 首先需要在 Verification Wizard 中选择 Domain Name Verification 添加、验证域名,证明这个域名是属于你的。填写域名的时候只能填顶级域名,二级域名是不被支持的,但是证明顶级域名归你所有之后,你可以随意添加二级域名。验证的过程也很简单:StartSSL 会检查这个域名的 Whois 信息,读取其中填写的所有人邮箱,然后外加 webmaster、postmaster、hostmater 等常见的域名邮箱的收件人,让你任选一个邮箱,发送验证码。哪个邮箱能收到邮件就选择哪个喽: 收到邮件之后,把里面的验证码复制粘贴进去,就验证成功了,StartSSL 就知道这个域名是属于你的了。注意,这个域名验证的有效期是三十天,三十天后要重新验证,但是三十天之内不需要再次证明这个域名归你。接下来就是去选择 Certificate Wizard 开始准备生成证书!在下拉列表中,选择你需要生成的证书类型,当然是 Web Server SSL/TLS Certificate 了。接下来是生成私钥: 这个是在线生成了,你也可以自己用 OpenSSL 生成。不过用它的也一样。这里需要填一个临时密码,输入一个 10 字符以上,32 字符以下的密码即可,这个密码临时使用,十分钟后就可以忘掉了。至于下面的加密方式和强度什么的都可以保持默认。 下一步是保存这个私钥:
把图中文本框中的东西全部复制下来,然后保存成一个纯文本文件,比如 ssl.key 。由于牵扯到 Windows/DOS 和 Linux/Unix 的换行符问题,建议还是在 Linux 环境下操作,比如在 SSH Shell 用 Vim 来保存这样一个文件。保存好之后把它解密: 接下来是添加子域名: 图中填的域名将会被作为最终的 Common Name,而裸域则是作为 Alternative Name 出现的。 再次确认之后,生成证书: 把图中文本框里的内容也保存成一个纯文本文件,比如 ssl.crt。(还是建议在主机上直接用 Vim 等保存,否则可能会有换和符问题)然后图中还有一个 intermediate 证书,那个也要下载保存一下,那个就是上文中所说的 ChainFile 了。至于那个 root 证书,由于大家的电脑里都有,所以就没必要下载。 现在你已经集齐了证书的三个要素了:ssl.crt 是证书信息和公钥,ssl.key 是证书的私钥,而那个 sub.class1.server.ca.pem 则是 ChainFile。把这三个文件放到服务器里的合理的目录下,再在 Apache 配置文件里指定它们,大功告成! 此外,StartSSL 还发给过你一个 S/MIME 证书,那个是你登录 StartSSL 网站的唯一凭据,把它弄丢了的话就无法登录 StartSSL 的网站了(只能重新申请了),所以也要备份好。Firefox 和 Chrome/Chromium 的证书备份都不复杂,在此不再赘述。 七、尾声本文原载于 wzyboy's blog,原文以 CC BY-NC-SA 3.0 释出,有修改。 补充1:经实验证明,FeedBurner 是不能识别 https:// 链接的,所以上文中判断 UA 的一节添加了 FeedBurner 的 UA。不使用 FeedBurner 的用户可以不加。 (责任编辑:IT) |