为什么正确的基于 HAProxy SNI 的路由需要“tcp-request content accept”前端指令?

为什么正确的基于 HAProxy SNI 的路由需要“tcp-request content accept”前端指令?

mongodb+srv我最近尝试在 HAProxy 上为 mongodb协议连接设置基于 SNI 的路由。

我让它工作了,但直到我把

tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }

在我的前端配置中它开始正常工作

如果没有这些(或只需一个其中)我大约 70% 的请求都会偶尔出现连接重置的情况。请注意,有时连接确实能够建立。

根据http://cbonte.github.io/haproxy-dconv/2.0/configuration.html#4-tcp-request%20content

基于内容的规则按照其确切的声明顺序进行评估。如果没有匹配的规则或没有规则,则默认操作是接受内容。对于可以插入的规则数量没有具体限制。

所以它应该默认工作。

我可能遗漏了一些基本的 TCP 概念或一些特定的 Mongo 连接细节。但我注意到,几乎每个人在进行基于 SNI 的路由时都定义了相同的规则,因此这对大多数人来说一定很有意义。

工作 HAProxy 配置:

    frontend fe_mongo-nonprod
      bind :27017
      tcp-request inspect-delay 5s
      tcp-request content accept if { req_ssl_hello_type 1 }

      acl mongoAtlas-01 req_ssl_sni -i host1.mongodb.net
      acl mongoAtlas-02 req_ssl_sni -i host2.mongodb.net
      acl mongoAtlas-03 req_ssl_sni -i host3.mongodb.net
      use_backend be_mongo-nonprod if mongoAtlas-01 || mongoAtlas-02 || mongoAtlas-03

    backend be_mongo-nonprod
      mode tcp

      acl mongoAtlas-01 req_ssl_sni -i host1.mongodb.net
      acl mongoAtlas-02 req_ssl_sni -i host2.mongodb.net
      acl mongoAtlas-03 req_ssl_sni -i host3.mongodb.net

      use-server server-01 if mongoAtlas-01
      use-server server-02 if mongoAtlas-02
      use-server server-03 if mongoAtlas-03

      server server-01 host1.mongodb.net:27017
      server server-02 host2.mongodb.net:27017
      server server-03 host3.mongodb.net:27017

还值得一提的是,HAProxy 部署在 Kubernetes(GCP 中的 Google 管理集群)中,具有 istio-sidecar 并通过 Internal LoadBalancer k8s 服务公开。

如上所述,上述配置运行良好。我感兴趣的是为什么tcp-request content accept绝对需要,而此处的连接并非[总是]默认接受。

答案1

经过一番思考之后,我将尝试回答我自己的问题。

因此,HAProxy 文档也有以下内容提及: http://cbonte.github.io/haproxy-dconv/2.0/configuration.html

如果需要内容切换,建议先等待完整的客户端 hello(类型 1),如下例所示。

现在,由于 SNI 数据也包含在请求的 Client Hello 部分中(https://www.rfc-editor.org/rfc/rfc6066#page-6)我的假设如下:

如果 Client Hello 分布在多个 TCP 数据包中且没有tcp-request content accept is configured,则在收到第一个数据包时,HAProxy 会尝试对其进行路由,并且会发生以下两种情况之一:

  1. 如果配置了默认后端,则数据包将被转发到该后端。
  2. 如果没有配置默认后端(我的情况),则数据包将被丢弃并且连接将被重置。

还请注意,即使在第一种情况下,后端部分中 HAProxy 指向的服务器也可能需要 SNI。因此,转发没有 SNI 指示的不完整请求也会导致连接重置。

相关内容