🔗 特性:SslBump Peek and Splice
- 目标:在得知源服务器名称后,特别是透明拦截 TLS/SSL 时,做出 bumping 决策。避免 bumping 非 TLS 流量。
- 状态:已完成。
- 版本: 3.5
- 开发者: AlexRousskov 和 Christos Tsantilas
🔗 动机
“Peek and Splice” 是一系列在 Squid-3.5 中引入的新的 SslBump 操作和相关特性。旧版本的 Squid 使用的 server-first 和 client-first 操作在许多情况下效果不佳。许多 SslBump 部署试图通过不 bumping 网站(除非本地策略强制要求)来最大限度地减少潜在损害。在新的操作可用之前,bumping 的决定是基于非常有限的信息做出的。
- 典型的 HTTP CONNECT 请求不包含太多细节,而
- 拦截的 TCP 连接除了 IP 地址和端口号外,不暴露任何信息。
Peek and Splice 使管理员能够在 TLS 握手过程的后期做出 bumping 决策,此时客户端 SNI 和服务器证书可用。或者,当明确我们根本不是在处理 TLS 连接时!
🔗 术语
在大多数情况下,本页面使用TLS 来表示TLS 或 SSL。
🔗 概述
Peek and Splice 功能会查看 TLS Client Hello 消息和 SNI 信息(如果存在),然后向服务器发送一个相同或相似(在可能范围内)的 Client Hello 消息,接着查看 TLS Server Hello 消息。
在这些步骤中的任何一个都可以做出最终决定是 splice、bump 还是终止连接(但 Squid 在第 N 步的操作会影响其在第 N+1 步进行 splice 或 bump 的能力!)。
请参阅下面的操作表,了解两个“查看”操作(即 peek 和 stare)以及各种最终操作(例如,“bump”、“splice”、“terminate”等)的定义。
🔗 处理步骤
Bumping Squid 会经历多个 TCP 和 TLS “握手”步骤。Peeking 步骤为 Squid 提供了更多关于客户端或服务器的信息,但通常会限制 Squid 未来可以执行的操作。下图显示了 TLS 客户端和 TLS 服务器之间简化的数据流和相关事件。请注意,当在客户端和服务器之间存在一个 bumping 代理时,流会被复制,第一个流在客户端和代理之间,第二个流在代理和服务器之间。

步骤 1
- 从客户端获取 TCP 级别信息。
- 在转发代理环境中,还需要解析 CONNECT 请求。
- 在拦截环境中,使用 TCP 级别信息创建一个假的 CONNECT 请求。
- 使用上述 CONNECT 请求通过调用序列。
- 评估所有 ssl_bump 规则,并执行第一个匹配的操作(splice, bump, peek, stare, 或 terminate)。
步骤 1 是唯一总是执行的步骤。
CONNECT 请求会被记录在 access.log 中。
请注意,对于拦截的 HTTPS 流量,此时没有可用的“域名”。日志条目将只包含目标 IP 地址和端口。在转发代理环境中,某些真实的 CONNECT 请求也是如此。
步骤 2
- 从客户端获取 TLS Client Hello 信息,包括 SNI(如果可用)。调整步骤 1 中的 CONNECT 请求以反映 SNI。
- 使用上述调整后的 CONNECT 请求通过调用序列。
- 再次评估所有 ssl_bump 规则,并执行第一个匹配的操作(splice, bump, peek, stare, 或 terminate)。
- 在此步骤进行 Peeking 通常会导致在步骤 3 中无法进行 bumping。
- 在此步骤进行 Staring 通常会导致在步骤 3 中无法进行 splicing。
步骤 2 仅在上一 步匹配了 peek 或 stare 规则时执行。
如果此步骤是最终步骤(即没有步骤 3),则调整后的 CONNECT 请求会在此步骤中记录在 access.log 中。但是,在 splicing 时,调整后的 CONNECT 请求会附加到生成的隧道中,直到隧道关闭才会记录。
步骤 3
- 从服务器获取 TLS Server Hello 信息,包括服务器证书。
- 验证 TLS 服务器证书。
- 再次评估所有 ssl_bump 规则,并为连接执行第一个匹配的操作(splice, bump, 或 terminate)。
步骤 3 仅在上一步匹配了 peek 或 stare 规则时执行。
上一 步的调整后的 CONNECT 请求总是在此步骤(如果 Squid 到达此步骤)的 access.log 中记录。但是,在 splicing 时,调整后的 CONNECT 请求会附加到生成的隧道中,直到隧道关闭才会记录。
在大多数情况下,步骤 3 中唯一有意义的选择是终止连接。Splicing 或 bumping 的决定通常由上一步的 peeking 或 staring 决定。
Squid 配置必须在希望通过延迟最终操作来获取更多信息的需求与执行特定最终操作(有时无法进一步延迟)的要求之间取得平衡。
🔗 操作
代理处理 TLS 连接时有几种可能的操作。请参阅 squid.conf 中的 ssl_bump 指令,了解您的 Squid 版本支持的操作列表。有些操作只能在特定的处理步骤中执行(见上文)。在给定的处理步骤中,Squid(3.5.8 及更高版本)会忽略带有不可能操作的 ssl_bump 行。这有助于我们保持配置的合理性。处理步骤将在下面进一步讨论。
| 操作 | 适用的处理步骤 | 描述 |
|---|---|---|
| peek | step1, step2 | 当在步骤 1 中匹配 peek 规则时,Squid 会继续到步骤 2,在那里它会解析 TLS Client Hello 并提取 SNI(如果存在)。当在步骤 2 中匹配 peek 规则时,Squid 会继续到步骤 3,在那里它会解析 TLS Server Hello 并提取服务器证书,同时保留 splicing 客户端和服务器连接的可能性;查看服务器证书通常会排除未来的 bumping(参见限制)。 |
| splice | step1, step2, and sometimes step3 | 成为一个 TCP 隧道而不解码连接。客户端和服务器之间的数据交换就像没有代理一样。 |
| stare | step1, step2 | 当在步骤 1 中匹配 stare 规则时,Squid 会继续到步骤 2,在那里它会解析 TLS Client Hello 并提取 SNI(如果存在)。当在步骤 2 中匹配 stare 规则时,Squid 会继续到步骤 3,在那里它会解析 TLS Server Hello 并提取服务器证书,同时保留 bumping 客户端和服务器连接的可能性;查看服务器证书通常会排除未来的 splicing(参见限制)。 |
| bump | step1, step2, and sometimes step3 | 与服务器建立 TLS 连接(使用客户端 SNI,如果存在),并与客户端建立 TLS 连接(使用模拟的服务器证书)。然而,如果 bump 规则在步骤 1 中匹配,这并非实际发生的情况。请参见 bug 4327 |
| terminate | step1, step2, step3 | 关闭客户端和服务器连接。 |
splice、bump 和 terminate 操作是最终操作:它们阻止对 ssl_bump 规则的进一步处理。peek 和 stare 操作允许 Squid 继续到下一个 SslBump 步骤。
🔗 另请参阅
如果 Squid-4 或更高版本无法解析预期的 TLS Client Hello 消息,Squid 会查阅 on_unsupported_protocol 指令。
🔗 配置示例
重要提示
如果您在 HTTP 连接被 bumped 之前使用 dstdomain ACL,请注意它将尝试匹配(假的或真实的)CONNECT 请求 URI。根据您的监听端口配置、浏览器行为、当前 SslBump 步骤以及其他因素,该 URI 可能只是一个 IP 地址,并且该 IP 地址的反向查找可能不是加密请求中的源服务器域名。ssl::server_name acl 类型可以使用(假的或真实的)CONNECT 请求 URI、TLS 客户端 SNI 和服务器证书主题信息。它还有用于控制使用哪些信息位的选项。但是,它不执行 DNS 查询。请阅读您 Squid 版本的 acl 文档并谨慎选择。
可以使用 at_step 类型 acl 来仅在特定步骤选择一个操作。
一些常见策略的教程可用
- 显式
-
# 以下示例的常见 acl: acl serverIsBank ssl::server_name .bank1.example.com acl serverIsBank ssl::server_name .bank2.example.net # 为所有用户使用的所有银行扩展 serverIsBank
acl monitoredSites ssl::server_name .foo.example.com acl monitoredSites ssl::server_name .bar.example.org
🔗 基本 splicing 和 bumping
仅观察 TCP/TLS 元数据。不查看 HTTP 信息。不修改任何内容。可用于日志记录,因为 SNI 和服务器证书会被 peek,并可以被记录。
根据其他设置,Squid 可能会终止无法验证客户端 SNI(主机头伪造检测)或服务器证书的连接。
ssl_bump peek all
ssl_bump splice all
仅 bumping 一组网站。
对于没有 SNI 的、访问 monitoredSites 的请求通常不起作用——它们不会被 bumped。
ssl_bump bump monitoredSites
ssl_bump peek all
ssl_bump splice all
Bump 除银行外的所有网站
对于访问非银行网站的请求通常不起作用——它们不会被 bumped。
根据其他设置,Squid 可能会终止访问银行的连接,如果 Squid 无法验证客户端 SNI(主机头伪造检测)或服务器证书。
ssl_bump splice serverIsBank
ssl_bump peek all
ssl_bump bump all
🔗 Peek SNI 并 Bump
SNI 通过在步骤 #2 中解析 TLS Client Hello 来获取(由 ssl_bump peek step1 指示)。解析 TLS Client Hello 并不会排除未来的 bumping。如果您想获取 SNI 并进行 bumping,那么请在步骤 #1 进行 peek,并在下一步(即步骤 #2)进行 bump。
acl step1 at_step SslBump1
ssl_bump peek step1
ssl_bump bump monitoredSites !serverIsBank
ssl_bump splice all
请注意,仅根据步骤 #1 和 #2 的信息做出决定,您将无法了解 TLS 服务器的视角。您所有的决定都将基于 TLS 客户端告诉您的信息。这通常不是问题,因为在大多数情况下,如果客户端欺骗(例如,向“non-bank.example.com”服务器发送“bank.example.com”SNI),TLS 服务器将拒绝与 Squid 建立 [在步骤 #2 中 bumped 或 spliced 的] 连接。但是,并非所有服务器都会这样做,并且很容易设置一个恶意的转发 TLS 服务器而不拒绝。此外,如果客户端根本没有提供 SNI 信息(例如,您正在处理 Windows XP 上的 IE),那么您的 ACL 在这两个早期步骤中可能没有足够的信息,尤其是在拦截连接时。
如果您还在步骤 #2 进行 peek,您将知道服务器证书,但在大多数情况下将无法再 bump 该连接(参见下面的限制)。
🔗 Peek SNI 并 Splice
上述配置通过在步骤 1 中匹配 peek 规则来获取 SNI(通过解析 TLS Client Hello),然后要么 splice 银行连接,要么 stare TLS Server Hello(由于匹配步骤 2 中的 stare 规则),并 bump 非银行连接(由于默认的 bump-after-stare 规则)。
ssl_bump peek step1
ssl_bump splice serverIsBank
ssl_bump stare all
在上述配置中,splice 的决定(如果发生)在步骤 #2 中做出(并且仅在该步骤中)。Bump 的决定(如果发生)在步骤 #3 中做出(并且仅在该步骤中),使用由步骤 2 中匹配的 stare 规则驱动的默认规则。这种延迟的 bumping 决定允许 Squid 在 bumping 时模仿服务器证书的属性。这种延迟 bumping 的代价(cons)是必须仅基于客户端提供的信息来做出 splicing 的决定。
此配置已在 Squid 用户邮件列表中进行了深入讨论。
🔗 Stare 时模仿 TLS Client Hello 属性
本节介绍 ssl_bump stare 操作生成的 TLS Client Hello 消息字段。本节中的信息不完整且有些过时。
| TLS Client Hello 字段 | 已转发? | 评论 |
|---|---|---|
| TLS/SSL 版本 | 是 | 仅 SSL v3 和 TLS 版本。 |
| 密码列表 | 是 | |
| SNI 扩展 | 是 | SNI 代表服务器名称指示。它是正在连接的源服务器的主机名,不是 URL 域名。 |
| 随机字节 | 是 | |
| 压缩 | 部分 | 模拟了压缩请求标志。如果客户端请求压缩,则模拟消息中的压缩算法由 Squid OpenSSL 设置(而不是从客户端消息中复制)。这可能是可以的,因为唯一广泛使用的算法是 deflate。有可能 OpenSSL 不支持其他压缩算法。 |
| 其他 TLS 扩展 | 有时 | 为了使 TLS 连接 splicing 在未来能够正常工作,我们可能需要模仿至少一些这些。 |
| 其他 | 有时 | 可能还有其他字段。我们可能需要模仿其中一些。但是,盲目转发所有内容可能不是个好主意,因为它很可能导致 bumping 期间的 TLS 协商失败。 |
请注意,为了在将来的步骤中实现 splicing,Client Hello 消息必须“按原样”发送,没有任何修改。另一方面,“按原样”发送 Client Hello 消息在大多数实际用例中会阻止 Squid 最终 bumping 连接。因此,模仿 Client Hello(如 staring 所做)还是“按原样”发送(如 peeking 所做)的决定,对于 Squid 在发送 Hello 消息后 splice 或 bump 连接的能力至关重要。
🔗 限制
🔗 查看服务器通常会排除 Bumping
要查看服务器证书,Squid 必须完整地转发 Client Hello。如果该 Client Hello 或服务器响应包含 Squid 不支持或不理解的任何 TLS 扩展(许多都有!),那么 Squid 无法可靠地 bump 连接,因为该 bumped 通信的另外两方可能会开始使用这些扩展,导致 Squid 的 OpenSSL 出现不可预测的混乱。可能的解决方案或变通方法(所有这些在不同方面都有缺陷)
- 如果 bumping 在您的环境中比 splicing 更重要/更有价值,您应该选择“stare”而不是“peek”。当然,Staring 通常会排除未来的 splicing。选择您的牺牲。
- 我们可以添加一个 ACL 来告诉您这些扩展和其他复杂性是否存在于 Client Hello 中。这是可行的,但如果该 ACL 通常评估为“是”,我们是否真的想进行所有这些额外的开发,然后使 Squid 配置复杂化?
- 我们可以教会 Squid 理解更多 TLS 扩展。这可能需要大量底层工作(因为我们需要做 OpenSSL 无法为我们做的事情)。这种方法最终可能会涵盖许多流行案例,但永远无法涵盖所有情况,当然也需要持续的添加。
- Squid 可以忽略客户端和/或服务器扩展并尝试继续 bumping。确切的结果无法预测,但通常会导致整个事务失败,可能会出现用户可见的浏览器警告。
- 我们可以教会 Squid 放弃当前的服务器连接,然后 bumping 一个新打开的连接。这是我们不希望做的,因为它很可能导致 Squid 因为白白打开和关闭连接而导致更糟糕的运营问题。
🔗 TLS 会话恢复
在 TLS 会话恢复期间,没有服务器证书供 Squid 检查。初始实现不尝试通过缓存会话信息来查找隐含的服务器证书,但即使有这样的缓存(以会话 ticket 为索引),也不能保证在 Squid 缓存中找到证书。此外,会话缓存本身可能需要 bumping 来了解会话 ticket(TLS NewSessionTicket 消息出现在初始握手之后!)。管理员必须决定是否要 splice 缺少服务器证书的会话,因为关于服务器的信息很少或没有。
更多限制待定。
🔗 日志记录
🔗 %ssl::bump_mode logformat 代码
Squid 记录一个单一的 access.log 记录来反映 CONNECT 请求处理。如果您在 logformat 定义中添加 %ssl::bump_mode,则该记录中的值将取决于 Squid 版本。
- Squid v3.5 记录第一个 ssl_bump 决定(通常是 step1 操作);
- Squid v4+ 记录最终的 ssl_bump 决定(通常是最后一个使用的 ssl_bump 操作)。
如果隧道被 bumped,那么每个 bumped 的 HTTP 请求也会被记录,当然。这些记录中的 %ssl::bump_mode 值是最终的 SslBump 决定。自然,该值将是“bump”或已弃用的 bumping 操作之一(即“server-first”或“client-first”)。这些 bumped 请求的日志记录行为对于所有现代 Squid 版本都相同。
下面是两个特定于版本的表,其中记录了 CONNECT 和 bumped 请求的预期 %ssl::bump_mode 值。
Squid v3.5 记录
| ssl_bump 配置 | 记录值 | |||
|---|---|---|---|---|
| step1 | step2 | step3 | CONNECT | bumped requests |
| splice | - | - | splice | - |
| bump | - | - | bump | bump |
| peek | splice | - | peek | - |
| peek | bump | - | peek | bump |
| peek | peek | splice | peek | - |
| peek | stare | bump | peek | bump |
| stare | peek | splice | stare | - |
| stare | stare | bump | stare | bump |
| server-first | - | - | server-first | server-first |
| client-first | - | - | client-first | client-first |
Squid v4+ 记录
| ssl_bump 配置 | 记录值 | |||
|---|---|---|---|---|
| step1 | step2 | step3 | CONNECT | bumped requests |
| splice | - | - | splice | - |
| bump | - | - | bump | bump |
| peek | splice | - | splice | - |
| peek | bump | - | bump | bump |
| peek | peek | splice | splice | - |
| peek | stare | bump | bump | bump |
| stare | peek | splice | splice | - |
| stare | stare | bump | bump | bump |
| server-first | - | - | server-first | server-first |
| client-first | - | - | client-first | client-first |
两个表之间的区别在于 CONNECT 列:具有多个 SslBump 步骤的行有所不同。
类别:功能
导航:站点搜索,站点页面,类别,🔼 向上