〇、概述

作为概述,以下是本文要讲的内容。HTTPS 是什么? 每个人都可能从浏览器上认出 HTTPS,并对它有好感。然后再讲一遍基础知识,再详细讲一下协议版本,密码套件(Cipher Suites),本文的重点会落在如何配置 NGINX,让你的网站使用 HTTPS 服务。

除此之外,还有一个使用 HTTPS 作为代理的问题; 所以,如果你的 NGINX 在另一个应用程序的前面,你如何设置NGINX 作为 HTTPS 客户端。

在这里,我会介绍一些方法,用以检查你的 HTTPS 配置,以看到它是最安全的和最新的,以及一些额外主题,帮助你得到你需要的 A+ 级别的安全。

本文涉及以下内容:

  1. 什么是 HTTPS
  2. 协议版本
  3. 密码套件
  4. 证书

下一篇的内容将包括:

  1. 配置 NGINX
  2. 后端 HTTPS
  3. 检查配置
  4. 配置 HSTS
  5. OCSP Stapling

一、什么是 HTTPS

你可能猜到了,HTTPS 就是 HTTPS, S 代表安全(Security)。就网络而言,有两种协议,分别叫做 SSL 和 TLS。它们可以互换使用。但是,「安全协议」(a security protocol)是位于通信之上的安全层。如果你想一下OSI 七层网络模型,那么它位于第 7 层的下面即第 6 层,叫做表示层。

OSI 七层模型

在客户端和服务器之间,它向您提供的是数据的保密性。因此,所有从客户端发送到服务器的信息都是完全加密的,所以只有两个人知道如何读取信息,那就是客户端和服务器。它还提供了一种形式的身份验证,在这种身份验证中,客户机可以知道服务器到底是谁。这些都交织在握手(handshake)的概念中。

1.1 SSL 握手 (Diffie‑Hellman)

SSL 握手

  1. 客户端:客户端发送 hello、客户端随机(client random)和受支持的密码套件(cipher suites)给服务器;
  2. 第二步
    1. 2a:服务器发送服务器随机(server random)和公钥证书(public key certificate)(也会发送一个用于会话复用的session ID)给客户端。
    2. 2b:客户端随机、服务器随机和公钥证书的密钥签名。
  3. 服务器发送服务器 DH (Diffie‑Hellman) 参数和密钥签名(signature)给客户端。
  4. 客户端发送客户端 DH 参数给服务器。
  5. 客户端和服务器都从服务器 DH 参数和客户端 DH 参数中获得相同的 premaster secret。
  6. 客户端和服务器都从客户端随机、服务器随机和 premaster secret 中获得相同的会话密钥(session keys)。客户端可以从服务器请求内容,并且请求将被加密。(也发送了会话复用的会话票据(session ticket))

上图是 SSL/TLS 握手流程。这有点复杂; 有很多可移动的部分,但本质上,如果你退一步看,它是在客户端和发送加密信息的服务器之间额外的一到两次往返。在这种情况下,你有几个选项——有服务器随机,有客户端随机; 这些都是你不需要知道的深奥的东西。

您只需要知道服务器本身发送一个公钥,客户端和服务器建立一个共享 secret,它们可以使用这个 secret 来加密通信。因此,访问者和服务器之间的所有通信都使用对称密钥加密,这意味着双方都有相同的密钥。还有一个完整性密钥,在本例中是 HMAC,但我暂时先跳过这个图,转而讨论更重要的问题: 「为什么需要设置HTTPS?」

1.2 为什么需要设置 HTTPS

  • 用户隐私
  • SEO 加成
  • 放在「没有 HTTPS 能力的服务」的前面
  • 通用最佳实践

主要原因是用户隐私。在服务通信的情况下,这是信息的隐私 - 你有多信任你正在使用的传输信息的网络? 你相信这些网络不会向你的流量中注入信息,并且能够读取传输的信息吗? 另外 2015 年之后,如果你在你的网站上使用 https,它提供了一个搜索引擎优化的优势,谷歌排名(以及国内的百度)将会比那些不支持 HTTPS 的网站排名更高。

另一件你可以为 HTTPS 做的事情(这是 NGINX 的主要用例之一)是把它放在那些不支持 HTTPS 或不支持最现代、最新版本的 SSL 和 TLS 的服务前面。因此,你可以从 NGINX 得到的是所有加密算法的最好、最先进的实现,你不需要真的去思考 HTTPS 的复杂性,总的来说,这是一个很好的实践。

另外,如果有人去访问一个网站,他们喜欢看到那个快乐的小锁图标。在本例中是 nginx.com,它启用了 HTTPS 和 HSTS (我将在后面讨论这个特性)。你不能再使用普通的 HTTP 版本访问了; 浏览器知道总是使用 HTTPS。你在这里看到的另一件事是,有一个漂亮的 NGINX, Inc[US] 显示这是一个扩展验证证书 —— 本质上,这个证书表明NGINX 是哪家公司的。他们为此多付了一点钱,做了一些调查并在证书上展示出来。

https 绿锁

1.3 HTTPS 带来的缺点有哪些?

  • 操作运维的复杂性
  • 额外的延迟(首次连接多了 2 次往返)
  • CPU 消耗

但 HTTPS 不是十全十美; 也有一些缺点。具体来说,有一点操作运维上的复杂性。你必须管理证书,你必须确保它们持续更新。您需要有受信任的管理员来保存私钥资料。

当你通过 HTTPS 连接到一个网站时,第一次可能会慢一些; 如果您的物理距离不一定很近,那么除了 TCP 握手之外,还有 SSL 握手,正如我提到的,它至少增加了两次往返。因此,延迟会受到轻微的影响,但这可以通过 SSL 的一些更高级的特性(如 SPDY 和 HTTP/2 )来缓解,本文不会详细介绍这些特性。

最终 HTTPS 可以和 HTTP 一样快,但有时不是。你的服务器上也有加密的成本; 这是一个很长时间不使用 HTTPS 的原因,但它越来越不适用。最新一代英特尔服务器可以非常快速地完成 HTTPS 所需的加密,而且几乎没有成本。所以,在现代硬件中,加密传输中的数据基本上是免费的。

1.4 你需要为 HTTPS 做哪些事情?

  • 支持的一系列 SSL/TLS 协议
  • 倾向使用的一系列的密码套件
  • 由受信任的证书机构(CA)签名的私钥和证书

如果你想为你的服务或网站设置 HTTPS,你需要做一些选择并获得一些东西。第一个「决定」是您想要支持的协议,第二个「决定」是您想要支持的密码(后面将详细说明这意味着什么),还有「您需要获得」证书和相应的私钥。这是一个重要的部分,由客户信任的第三方证书颁发机构「颁发」。我稍后会讲到,但首先让我们谈谈协议版本(protocol versions)。

二、协议版本(Protocol Versions)

回顾一下前文,HTTPS 是 HTTP 加上 S,S一直在变化; 它是随着时间而进化的。最初,SSL v1.0 是 Netscape(网景) 发明的协议。有一个著名的轶事是,马克·安德森(Marc Andreessen)在麻省理工学院做演讲时观众席上有人用铅笔描述了如何破解密码算法。

所以,SSL TLS 加密协议其实并没有很长的历史,1995 年 网景 发布了 SSL v2.0,这也是 web 加密的开始。这使得电子商务领域,人们可以在线提交密码和信用卡,并且至少是相当安全的。

2.1 HTTPS 历史背景

接下来请参见加密协议历史概要 - HTTPS 基础原理和配置 - 1 - 东风微鸣技术博客 (ewhisper.cn)

😂被破解历史概要 - HTTPS 基础原理和配置 - 1 - 东风微鸣技术博客 (ewhisper.cn)

2.2 客户端兼容性

请参见:客户端兼容性 - HTTPS 基础原理和配置 - 1 - 东风微鸣技术博客 (ewhisper.cn)

2.3 配置选项及得分

请参见:配置建议 - HTTPS 基础原理和配置 - 1 - 东风微鸣技术博客 (ewhisper.cn)

三、密码套件(Cipher Suites)

现在让我们进入密码套件。什么是密码套件? SSL、TLS 和 HTTPS 使用各种加密算法来建立连接,这实际上是一个字母池。它们是什么意思?

密码套件就是描述使用的加密类型的复杂字符串,它是由 openssl 定义的(可以通过 openssl ciphers 查看你的密码套件)。

示例如下:

TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:RSA-PSK-AES256-GCM-SHA384:DHE-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:AES256-GCM-SHA384:PSK-AES256-GCM-SHA384:PSK-CHACHA20-POLY1305:RSA-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-GCM-SHA256:AES128-GCM-SHA256:PSK-AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:ECDHE-PSK-AES256-CBC-SHA384:ECDHE-PSK-AES256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:RSA-PSK-AES256-CBC-SHA384:DHE-PSK-AES256-CBC-SHA384:RSA-PSK-AES256-CBC-SHA:DHE-PSK-AES256-CBC-SHA:AES256-SHA:PSK-AES256-CBC-SHA384:PSK-AES256-CBC-SHA:ECDHE-PSK-AES128-CBC-SHA256:ECDHE-PSK-AES128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:RSA-PSK-AES128-CBC-SHA256:DHE-PSK-AES128-CBC-SHA256:RSA-PSK-AES128-CBC-SHA:DHE-PSK-AES128-CBC-SHA:AES128-SHA:PSK-AES128-CBC-SHA256:PSK-AES128-CBC-SHA

3.1 密码套件拆解

密码套件拆解

从本质上讲,第一个术语是密钥交换,即双方用来交换密钥的算法。在上图这种情况下,它是基于 Diffie-Hellman算法。

第二个术语是您的证书中的密钥类型。因为每个证书都有一个特定类型的公钥。这里是RSA。

第三部分是你的传输密码,用来加密所有数据的加密算法。这里面有很多不同的部分,但 AES-GCM 是最安全的密码; 这实际上是英特尔处理器几乎零成本完成的事情。所以这是一个相当便宜和可靠的密码使用。

最后一点是完整性。正如我提到的,消息有一个缓存,以确保它们没有被篡改,但如果它是加密的,并具有完整性,你可以从那里校验。

3.2 服务器密码套件

  • 客户端按优先顺序列出受支持的密码套件
  • 服务器接受:客户端列表和服务器支持的密码列表的交集
  • 服务器会选择剩下中的更喜欢的那些

现在,并不是所有的浏览器和服务器都支持相同的密码列表。这被称为协议灵活性,实质上服务器所做的是: 客户端说,“嘿,这就是我所支持的全部”。服务器说:“好吧,我知道其中的五个。我会挑我最喜欢的”。

3.3 密码套件商定(Cipher Suite Negotiation)

因此,如上图所示,如果客户端说,「左边的这些是我依次支持的」,而服务器端只支持两个,然后它就会选择自己喜欢的。

3.4 推荐的密码套件

这并不是一个争论的大问题,但你有很多选择。CloudFlare 使用这个密码套件列表,你可以在 GitHub 的这里找到它。有一个 NGINX 配置格式,这些是 CloudFlare 推荐的。这些是 CloudFlare 上的所有网站最终都会使用的。

ssl_protocols               TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ecdh_curve              X25519:P-256:P-384:P-521;
ssl_ciphers                 '[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]:ECDHE+AES128:RSA+AES128:ECDHE+AES256:RSA+AES256:ECDHE+3DES:RSA+3DES';
ssl_prefer_server_ciphers   on;

有一种很酷的新密码叫 ChaCha 20。在主线 NGINX 它还不支持,其他的都可以用。Mozilla 在这方面也有自己的建议,你可以去访问他们的服务器端 TLS 站点,他们会为你生成 NGINX 或任何你可能使用的网络服务器的 SSL 配置。这就是密码套件。生成的示例如下:

# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

四、证书

现在我们有了协议集和密码集; 接下来是证书。这是 HTTPS 最重要的部分。这是在客户面前标识您作为一个站点的标志。但是,证书里有什么呢?

4.1 证书里有什么?

  • 组织名(Organization name)
  • 公钥(Public Key)
  • 颁发者名称(Issuer name)
  • 权限
    • 有效期
    • 域名(Hostnames)
  • 颁发者数字签名(Digital signature by issuer)

其中包括你的名字(你是谁)、你的站点适用于哪些域名、证书何时有效、公钥(客户可以使用公钥验证你用它签名的任何东西),然后是数字签名。数字签名是来自公共证书颁发机构的戳记,表明它是一个真实的证书: 这个人实际上拥有这个 DNS 名称,并且在这些点上是有效的。

4.2 什么是授信证书?

那么,是什么使证书可信呢? 这是目前互联网上所有证书颁发机构(ca)的分类,大多数证书都是由这些机构签署的。这里有一些常见的名字。赛门铁克已经购买了几个这样的证书颁发机构,包括 GeoTrust、Verisign 等。

这些都是受信任的大公司,最重要的是,它们的证书受到浏览器的信任。因此,如果赛门铁克通过某人从他们那里购买证书的过程表示该证书良好,那么浏览器将显示绿锁。

4.3 我如何获得一个证书?

您可以通过创建私钥或一对密钥来获得证书,然后将您的公钥发送给证书颁发机构,通过验证签章将其转换为证书。这通常会花费一些钱(有免费的方法),但本质上私钥你必须保持私有,唯一应该得到它的实体是你的管理员和你的web服务器本身

4.4 我如何创建一个 CSR(证书签名申请)和私钥?

有几种方法可以创建这些密钥对。CSR 本质上是将公钥打包到证书颁发机构以创建证书的方法。有OpenSSL, CFSSL等多种方式。

使用 OpenSSL:

openssl genrsa -out key.pem 2048
openssl req -new -sha256 -key key.pem -out key.csr

4.5 如何获得一个免费证书?

如果你想要一个免费的,目前最知名的网站是 Let's Encrypt - 免费的SSL/TLS证书 (letsencrypt.org)。他们会给你一个免费网站的证书。随着时间的推移,获得证书的成本似乎会更低。还有免费证书颁发机构的建议。所以现在,你可以付费使用 Comodo 或 DigiCert 等网站,也可以选择免费路线。

4.6 证书链(Certificate Chain)

证书不会直接由证书颁发机构签署; 这是一种建立起来的信任链。如果你有一个证书,它通常是由一个中间证书颁发机构签署的,而这个中间证书颁发机构是由真正的证书颁发机构签署的。

在这种情况下,并不是所有的浏览器都必须知道链中的下一个证书是什么,并且浏览器实际上只与顶部绑定(真正的脱机根证书)。因此,当你获得一个证书时,你还需要拥有整个信任链。

通常CA会给你这个证书链链,在 CA 没有给你的证书链情况下你可以通过一些工具去创建。