HTTPS 详解

Eagle looks to the sky by @peteevans, UK
某日闲得慌,想把家里内部多个网站升级至HTTPS,每个域名都做一个证书?那后期的维护绝对不是人干的。好在有万能的google,才发现多个域名也可以用一个证书来搞定。

一、HTTPS 简介

维基百科是这么解释HTTPS的:HTTPS 即 HTTP over SSL/TLS,是一种通过计算机网络进行安全通信的传输协议。HTTPS利用SSL/TLS来加密数据包,使用HTTP来通信。
HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。
这个协议由网景公司(Netscape)在1994年首次提出,随后扩展到互联网上。

HTTP与HTTPS的区别

SSL/TLS

如上图所示,HTTP不使用SSL/TLS来通信,所以它是不加密的通信。所有信息明文传播,带来了三大风险。

  • 窃听风险:第三方可以获知通信内容。
  • 篡改风险:第三方可以修改通信内容。
  • 冒充风险:第三方可以冒充他人身份参与通信。

SSL/TLS协议是为了解决这三大风险而设计的,希望达到:

  • 所有信息都是加密传播,第三方无法窃听。
  • 具有校验机制,一旦被篡改,通信双方会立刻发现。
  • 配备身份证书,防止身份被冒充。

SSL/TLS发展时间表

TLS(Transport Layer Security)是传输层安全协议,是 SSL3.0 的后续版本。TLS 版本相比于 SSL 变化最明显的是支持的加密算法不同。当前最新的协议版本为 TLS1.3。

HTTPS 工作流程

HTTPS 工作流程

检测数字证书的有效性

SSL/TLS自身不要求用户检查Web服务器的证书,但现在大部分浏览器都会对证书进行简单的完整性检查,并为用户提供进一步彻查的手段。
浏览器对服务器证书的有效性检测的基础算法是由网景公司发明的。

验证步骤如下所述:

  • 日期检测:首先,浏览器检查证书的起始日期和结束日期,以确保证书仍然有效。
    如果证书过期或还未被激活,则证书有效性验证失败,浏览器会对用户显示一条关于证书的错误信息。
  • 签名颁发者可信度检测:网络上大部分证书都是由一些权威证书颁发机构(CA) 签名发布的。因为这些权威CA通过非常清晰的流程来验证证书申请人的身份及商业行为的合法性并对服务器的合法性提供担保,所以浏览器会自带一个权威证书颁发机构的信任列表
    因为证书任何人都可以生成,所以如果浏览器收到了某未知(自签/恶意)颁发机构签发的证书,它就会为用户显示一条关于证书的警告信息。
  • 签名检测:一旦判定签名授权是可信的,浏览器就会使用该CA机构的公钥来对签名进行解密以获取证书的Hash值,然后与此证书的Hash值进行对比,以查看证书的完整性。
  • 网站身份检测:为防止服务器复制其他人的证书,或拦截其他人的流量,大部分浏览器都会试着 去验证证书中的域名与它们所对话的服务器的域名是否匹配。证书的域名存储在[Common Name(CN)]或[Subject Alt Name(SAN)]里。如果主机名与证书中的标识符不匹配,浏览器会提示用户证书不正确的差错报文并终止连接。

二、证书简介

证书分类

  1. CA证书(CA Certificate),也叫根证书或者中间级证书,用来对服务器/客户端证书进行签名,以表示服务器/客户端证书的合法性。
    如果是单向https认证,该证书是可选的
    如果服务器/客户端证书没有CA签名或者浏览器无法找到CA证书的公钥,那么浏览器默认这个证书是不安全的,会在地址显示一把灰色锁的图标。
  2. 服务器证书(Server Certificate),必选项,储存在服务器上,用来以非对称加密算法加密服务器与用户浏览器协商生成对称密钥的通信内容。使用证书私钥server.key、证书请求文件server.csr、CA证书的公私钥ca.key/ca.crt,生成服务器证书的公钥server.crt
  3. 客户端证书(Client Certificate),可选项,用来与服务器验证客户端的合法性。若有客户端证书则是双向https验证。

以上所有证书都可以自己生成。

证书列表

  • 双向认证,有三个私钥和三个证书。分别是 ca.key, ca.crt, server.key, server.crt, client.key, client.crt ,以及给浏览器的 client.pfx
  • 单向认证(有CA证书),证书和私钥是 ca.key, ca.crt, server.key, server.crt
  • 单向认证(无CA证书),证书和私钥就是 server.key, server.crt

为什么可以不使用CA证书?
根据SSL/TLS的握手步骤,只要有服务器证书的公(私)钥,浏览器就能与服务器进行正常通信以生成对称密钥 见图(HTTPS工作流程),只不过浏览器地址不显示小绿锁图标而已。

三、自制证书

如果想让客户端的浏览器地址栏显示出HTTPS特有的小绿锁图标,就必须满足以下2个条件:

  1. 服务器证书的公钥必须要有CA的签名。
  2. 浏览器(客户端)的证书受信列表里必须包含此CA,受信列表支持导入用户自己的CA证书。

小绿锁

1、制作CA证书

1
2
3
4
5
6
7
8
9
10
11
echo 创建CA秘钥
openssl genrsa -out ca.key 2048
echo 生成CA公钥并自签名
openssl req -sha256 -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/C=CN/ST=Hebei/L=BaoDing/O=my Organization/OU=my Unit/E=my@gmail.com/CN=myCA"
# /C=国家
# /ST=省
# /L=市
# /O=组织
# /OU=单位
# /E=邮箱
# /CN=Common Name=证书名字

2、制作服务器证书

这里以我们的blog域名shixuen.com为例

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
echo 创建Server秘钥
openssl genrsa -out shixuen.com.key 2048

echo 创建Server请求文件,CN为默认域名
openssl req -new -sha256 -key shixuen.com.key -out shixuen.com.csr -subj "/C=CN/ST=Hebei/L=BaoDing/O=my Organization/OU=my Unit/E=my@gmail.com/CN=shixuen.com"

#echo 生成单域名的服务器证书公钥并使用CA签名
#openssl x509 -req -in shixuen.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3560 -out shixuen.com.crt
echo 生成多域名的服务器证书并使用CA签名
cat > /tmp/shixuen.com.ini <<EOF
[ ext ]
subjectAltName = @dns
[ dns ]
# 域名支持通配符 *
# 支持IP地址
DNS.1 = shixuen.com
DNS.2 = *.shixuen.com
DNS.3 = haven200.ga
DNS.4 = *.haven200.ga
DNS.5 = localhost
DNS.6 = 127.0.0.1
EOF
openssl x509 -req -in shixuen.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3560 -out shixuen.com.crt -extfile /tmp/shixuen.com.ini -extensions ext

echo 将服务器证书导出为pfx格式,请输入密码
openssl pkcs12 -export -out shixuen.com.pfx -inkey shixuen.com.key -in shixuen.com.crt

echo 完成

单域名证书不包含[Subject Alt Name]属性,此证书只匹配[CN]属性的域名。
多域名证书包含[Subject Alt Name]属性,此时证书可以匹配[CN]或[SAN]属性的域名。

3、制作客户端证书(可选)

Web网站上很少使用双向认证,一般只使用单向认证。
OpenVPN使用的双向认证,所以它最后生成的证书有

  • ca.key, ca.crt
  • server.key, server.crt
  • client.key, client.crt

四、自制证书的使用方法

服务器证书

这里以 Web 服务器 Caddy 为例

  1. 将生成的server.crtserver.key上传至服务器/var/www/.cert/下。
  2. 修改 Caddy 的配置文件,启用自制证书。
    1
    2
    3
    4
    5
    6
    7
    8
    http://www.shixuen.com {
    redir https://{host}{uri}
    }
    https://www.shixuen.com {
    root /var/www/
    gzip
    tls /var/www/.cert/shixuen.com.crt /var/www/.cert/shixuen.com.key
    }

此时,我们使用浏览器浏览网站https://www.shixuen.com会弹出一个证书不被信任的错误页面,我们点击页面下方的允许例外后就可以浏览我们的网站了。

此时浏览器地址栏显示出 HTTPS 所特有的小锁图标,但小锁图标为灰色,表示证书存在问题。
灰锁

根据 HTTPS 工作流程 得知,这是因为浏览器对服务器证书的验证中第二项签名颁发者可信度没有通过。

那么如何使浏览器的地址栏显示出绿色的小锁图标呢?
这就需要在浏览器或客户端系统上安装我们刚刚生成的 CA 证书。

CA 证书的使用

浏览器

我们可以将根证书(ca.crt)导入至浏览器的根证书可信列表中。
这里以 Firefox 浏览器为例:

  1. 在地址栏输入about:preferences打开首选项
    首选项
  2. 点击页面左侧的隐私与安全菜单
    隐私与安全
  3. 将右侧页面下拉至底,在证书选项里点击查看证书,弹出证书管理器页面
    证书选项
  4. 点击证书颁发机构,然后再点击导入,将我们自己的 CA 证书(ca.crt)导入至浏览器中
    证书页面
  5. 清除浏览器缓存

此时再去重新打开我们的网站https://www.shixuen.com,地址栏直接显示 HTTPS 的标志性图标小绿锁。
小绿锁

Linux

当然,我们也可以直接将 CA 证书导入至系统中,这样我们使用任意浏览器浏览网站时,都不会再弹出证书错误的页面了。

Linux 系统的根证书存储在/usr/share/ca-certificates/mozilla/

1
2
3
4
5
:~$ sudo cp ca.crt /usr/share/ca-certificates/mozilla/haven200_ca.crt
:~$ sudo cat >> /etc/ca-certificates.conf <<EOF
mozilla/haven200_ca.crt
eof
:~$ sudo update-ca-certificates

Windows 导入

Windows 就不再细说了,直接双击ca.crt,点击导入吧,全图形界面。


References:
segmentfault.com
WikiPedia-HTTPS