本节内容

发现PostgreSQL 如何实现 TLSCisco TLS 服务器身份发现Direct TLS 支持在 Aurora DSQL 中使用 direct TLS

Direct TLS 如何加速你的连接

几个月前,我的一位 Aurora DSQL 团队成员报告了一个有趣的发现。当使用公司 VPN 连接到他们的 DSQL 集群时,连接速度很快,正如预期的那样!但是,当_不使用 VPN_ 进行连接时,连接大约需要 3 秒。奇怪的是,这只发生在 AWS 办公室里。

发现

这个发现的触发点是 re:Invent 2024 上 Aurora DSQL 的公开预览。在公开发布之前,对 DSQL 的访问受到限制,要求开发人员必须使用公司 VPN。开发人员开始在 VPN 之外与 DSQL 交互,并意识到它比以前慢得多。 是什么解释了这一点?很明显,这是“网络”的问题,因为这是唯一的区别。这并不意味着办公室的 WiFi 很慢,否则连接总是会很慢,而不仅仅是 VPN 之外的连接。但是办公室 WiFi 中的_某些东西_增加了大量的开销。 事实证明,办公室有三个网络:

  1. 供 Amazon 员工使用的 WiFi 和有线网络
  2. 供访客使用的 WiFi 网络

我的一位团队成员进行了以下测试: 网络类型 | 慢 ---|--- 网络类型 | 慢 员工 WiFi | 是 员工有线 | 是 访客 WiFi | 否 所以…… _只有在公司网络上_才会发生一些特定的事情。 在进行一些服务器端调试后,团队注意到了一些奇怪的事情。对于每个打开到集群的连接,都会建立一个额外的连接。第二个连接甚至没有使用 Postgres!

PostgreSQL 如何实现 TLS

参考:来自 Postgres 16 文档的消息流 引用(稍作修改):

为了发起一个 SSL 加密的连接,前端 [Postgres 客户端] 最初发送一个 SSLRequest 消息,而不是 StartupMessage。 然后服务器用包含 SN 的单个字节进行响应,表示它是否愿意执行 SSL。如果前端对响应不满意,可能会在此处关闭连接。在 S 之后继续,与服务器执行 SSL 启动握手(此处未描述,属于 SSL 规范的一部分)。如果成功,则继续 […] 将其拟人化:

  1. 客户端 → 服务器:嘿,我想和你谈谈,但首先让我们设置 TLS
  2. 服务器 → 客户端:好的,请继续
  3. 客户端 ⇄ 服务器:TLS 握手
  4. 客户端 ⇄ 服务器:[加密流继续]

所以,我们在日志中看到的是,_第一个_连接是这样做的,但是_第二个_连接不是。第二个连接跳到了第 3 步并启动了 TLS 握手。第二个连接来自哪里,为什么它不遵循协议?

Cisco TLS 服务器身份发现

在与我们的公司网络团队沟通后,他们与我们分享了以下资源: https://www.ciscolive.com/c/dam/r/ciscolive/us/docs/2021/pdf/BRKSEC-2106.pdf 这是一份很棒的文档,如果您对细节感兴趣,我建议您通读一遍。否则,这里是摘要。 Cisco 防火墙具有基于所访问的 URL 或应用程序添加规则的功能。当您启动 TLS 连接时,客户端会向服务器发送一个“hello”消息,服务器会响应一些信息,包括其证书。防火墙使用服务器 TLS 证书中存在的信息来强制执行规则。 为了真正说明这一点:防火墙会看到您正在发送和接收的数据包。当客户端发送一个 hello 时,防火墙会说“这看起来像一个 TLS hello”,然后等待服务器的响应。它会检查证书,然后应用任何规则。 在 TLS 1.3 中,服务器的证书是加密的,这意味着防火墙无法再这样做。这就是这个幻灯片演示的内容。_TLS 服务器身份发现_是一种可以解决此问题的功能。防火墙将打开_第二个连接_并执行 TLS 1.2 握手以明文检索证书。如果规则允许连接,则防火墙允许连接继续。 但是,当然,这不是 Postgres 所期望的。Postgres 期望想要执行 TLS 的客户端首先询问服务器是否支持它。 事实证明,我们的防火墙未配置为阻止未知应用程序。发生的事情是防火墙_尝试_学习证书,然后在 3 秒后放弃,允许原始连接通过。谜团解开了!

Direct TLS 支持

这是同样的 Postgres 文档,这次是 version 17。有新内容!

第二种启动 SSL 加密的替代方法可用。服务器将识别立即开始 SSL 协商而没有任何先前的 SSLRequest 数据包的连接。一旦建立 SSL 连接,服务器将期望一个正常的启动请求数据包,并在加密通道上继续协商。 这段话的意思是,如果您在服务器和客户端上都使用 Postgres 17+,则可以跳过前面的第 1 步和第 2 步。您可以直接从 TLS 握手开始。 要在客户端中启用此功能,您需要三件事:

  1. Postgres 17+ 客户端
  2. sslmode=require,设置为连接参数,或通过 $PGSSLMODE
  3. sslnegotiation=direct,设置为连接参数

我们将此功能添加到 Aurora DSQL,问题就解决了。不再有 3 秒的停顿。通过使服务器支持 direct TLS,防火墙打开的第二个连接将成功。 Postgres 文档继续说:

在这种情况下,任何其他加密请求都将被拒绝。对于通用工具来说,不推荐使用此方法,因为它无法协商可用的最佳连接加密或处理未加密的连接。但是,它对于服务器和客户端一起控制的环境很有用。在这种情况下,它可以避免一次往返延迟,并允许使用依赖于标准 SSL 连接的网络工具。当以这种方式使用 SSL 连接时,客户端需要使用 RFC 7301 定义的 ALPN 扩展来防止协议混淆攻击。PostgreSQL 协议是“postgresql”,已在 IANA TLS ALPN 协议 ID 注册表中注册。 节省一次往返时间很酷!谁不喜欢更快的连接? Aurora DSQL,像大多数 AWS 服务一样,仅支持 TLS。如果您在不请求 TLS 的情况下连接到 DSQL,您将被拒绝: [复制]

psql "host=beabuc4gtix7m2hr6xh2huewkm.dsql.us-west-2.on.aws sslmode=disable"
FATAL: unable to accept connection, SSL is mandatory. AWS Authentication is required.

因此,我们强烈建议使用 direct TLS 功能。使用 direct TLS 没有缺点;如果您的客户端支持它,它会更好。我很高兴看到此功能如此迅速地添加到客户端和驱动程序的生态系统中。 感谢所有为此功能做出贡献的人。如果您想了解有关其开发的更多信息,请查看以下线程:

在 Aurora DSQL 中使用 direct TLS

这是一个使用 psql 和 direct TLS 连接到集群的完整示例: [复制]

export ENDPOINT=beabuc4gtix7m2hr6xh2huewkm.dsql.us-west-2.on.aws
export PGPASSWORD=$(aws dsql generate-db-connect-admin-auth-token --hostname $ENDPOINT)
psql "host=$ENDPOINT user=admin dbname=postgres sslmode=require sslnegotiation=direct"
psql (17.4 (Homebrew), server 16.9)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_128_GCM_SHA256, compression: off, ALPN: postgresql)

您也可以使用 pdsql (链接),如下所示: [复制]

pdsql "host=beabuc4gtix7m2hr6xh2huewkm.dsql.us-west-2.on.aws user=admin dbname=postgres"

除了自动化 token 生成之外,pdsql 还会自动添加 "sslmode=require sslnegotiation=direct"。如果您不想下载另一个工具,您可以构建一个执行类似操作的 bash 函数。 ^ 返回顶部 下一步操作 (0):已完成的操作 (0): 仪表盘 上下文 (0):