为什么要给网站启用SSL

什么是 SSL?

SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层: SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。 SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。

SSL

SSL 作为 HTTPS 的基础最早由网景于 1994 年提出。虽然 HTTP 协议本身提供了基本认证和摘要认证(后来提出)两种客户端认证方案,但是毕竟除了用户名和密码外的所有数据仍然是明文传输的(甚至基本认证只对密码信息做了 Base64 编码),要保证传输的安全性还得依靠 SSL。SSL 本身是一种二进制协议,避免了随随便便一个代理就能读取/修改数据的问题。

随着技术发展,SSL 本身也在不断改进。从 SSL 1.0、SSL 2.0 到 SSL 3.0,再到标准化后的 TLS(目前 TLS 1.3 刚刚定稿),这个协议本身也在完善当中。在本文中,我们按照一般惯例使用 SSL 一词同时指代 SSL 和 TLS 两种协议。


什么是 HTTPS?

首先我们把A 看作客户端,通常情况下也就是浏览器,B 看作服务器,E 看作网络链路上某台邪恶的代理,C 是一位公正的第三方,顺便,我们把 C 交给 B 的那段含有一些基本信息和 B 的公钥的密文叫做数字证书。现在,我们可以把 C 叫做证书颁发机构。
在真实情况下,数字证书会包含一些加密的基本信息。毕竟数字证书并没有统一的标准,这些加密信息会用来告诉 A 如何解密数字证书。当然这些信息不会被加密,不然 A 完全无法解密数字证书。因此现实情况下,C 会对数字证书包含的所有内容建立一个摘要(你可以把它当做简介),然后只对这个摘要用自己的私钥进行加密。这个过程叫做签名。当 A 收到证书后,会解密这段摘要,然后自己通过相同的算法独立算出证书的摘要——如果是一样的,那就没问题了。
SSL
那么现在开始连接。A 向 B 发出了一个请求。在建立连接后,B 会将数字证书发送给 A。A 会验证数字证书(甚至会询问 C 确保这张证书没有作废)。如果成功,A 会利用从证书中取得的 B 的公钥在加密环境下协商出一个一致的临时密钥,接下来双方会用这个密钥进行对称加密来互相交流。
这就完成了!现在 A 和 B 可以使用相同的密钥进行对称加密通信在这个基础上,A 和 B 可以使用标准的 HTTP 协议进行交流。同时由于没能截获密钥,可怜的 E 同学再次扑了个空。我们成功完成了一次加密的 HTTPS 通信。


如何给域名申请SSL 加密证书

部署 HTTPS 的第一步是挑选符合要求的证书签发机构和合适的证书种类。不同的签发机构之间,以及同一机构签发的不同种类的证书之间,所需的价格是不同的。

证书种类是什么?真实的情况的确比上文提到的情况要再复杂一点。总的来说,证书分为 DV、OV、EV 三类。DV 证书只能提供最基本的加密功能,价格最低;而 OV 和 EV 证书会在签发前验证申请者的身份,流程更繁琐,价格也更高,但是这类证书可以提供验证网站身份的功能(比如浏览器会对不同种类的证书提供视觉上的差异,见下图),而且在出现安全问题时(比如签发机构的私钥泄露,虽然几率很小,但是有可能)的赔付金额也更高。

对于签发机构,我推荐选择 Let’s Encrypt,这是由 Mozilla、思科、Akamai、IdenTrust 和 EFF 等组织发起的公共、免费的 SSL 项目。它所签发的 DV 证书完全免费,而且支持通配符和多域名。唯一的缺点是它只支持 3 个月的有效期,不过到期后可以免费续期。

什么是通配符?浏览器在验证证书时,会确保证书中指定的域名和当前访问的域名相符,而根域名(a.com)和子域名(b.a.com)会被当做不同的域名来处理,不同的子域名(b.a.com 和 c.a.com)也会被当做不同的域名。通配符证书(*.a.com)可以同时匹配不同的子域名,减少了所需签发证书的数量。但是,根域名和通配符子域名不会匹配,都需要签发证书。同时,Let’s Encrypt 支持的多域名可以在同一张证书中包含多个域名,大大减少了所需证书的数量。像图中这样,该域名下的所有二级域名都可以使用此证书。

CERTIFICATE INFORMATION

使用Let’s Encrypt签发SSL证书

要使用 Let’s Encrypt 签发,我们可以使用 acme.sh,这是一个基于 Let’s Encrypt 接口封装的开源命令行工具,支持多域名/通配符的申请,也支持自动续期。

使用acme.sh

安装 acme.sh: curl https://get.acme.sh | sh

创建 一个 bash 的 alias, 方便你的使用: alias acme.sh=~/.acme.sh/acme.sh

申请证书: acme.sh --issue --dns dns_he -d abc.com -d *.abc.com

申请证书例子中,使用了dns_he API部署,你可以在完整文档中使用你域名解析商的APIHow to use DNS API

稍等片刻,当证书签发下来,我们往往会得到两个文件,一个是你的私钥,一个是证书。

这时,我们就可以把证书放到服务器上了,然后配置服务器来开启 HTTPS。不同服务器的配置过程通常不同,我也不再赘述了。如果你使用 Nginx,可以使用如下配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server{
listen 80;
listen 443 ssl http2;
# 其他配置...
# 如果是 HTTP 就跳转到 HTTPS
if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}
# 证书和私钥路径
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# SSL 参数
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;
ssl_prefer_server_ciphers on;
ssl_session_timeout 1d;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_buffer_size 1400;
ssl_stapling on;
ssl_stapling_verify on;
# 其他配置...
}

当然,如果是面板之类的…大多有 SSL 的管理入口,依照提示部署证书即可。

最后,我们还需要对网页文件进行修改,尤其是页面上所有引用的资源必须同样使用 HTTPS,否则浏览器就不会显示安全小绿锁。