為什麼正確的基於 HAProxy SNI 的路由需要「tcp-request content Accept」前端指令?

為什麼正確的基於 HAProxy SNI 的路由需要「tcp-request content Accept」前端指令?

我最近嘗試在 HAProxy 上設定基於 SNI 的路由以進行 mongodbmongodb+srv協定連接。

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

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,並透過內部 LoadBalancer k8s 服務公開。

如上所述,上述配置運作良好。我感興趣的是為什麼這tcp-request content accept是絕對必需的,並且默認情況下不[總是]接受連接。

答案1

經過一番思考後,我將嘗試回答自己的問題。

因此,HAProxy 文件也提到了以下內容: http://cbonte.github.io/haproxy-dconv/2.0/configuration.html

如果需要內容切換,建議先等待完整的用戶端問候(類型 1),如下例所示。

現在,由於 SNI 資料也包含在請求的 Client Hello 部分中(https://www.rfc-editor.org/rfc/rfc6066#page-6)我的假設如下:

如果 Client Hello 分佈在多個 TCP 封包中且 no tcp-request content accept is configured,則在收到第一個封包後,HAProxy 會嘗試路由它,並且會發生以下兩種情況之一:

  1. 如果配置了預設後端,則封包將轉送到該後端。
  2. 如果沒有配置預設後端(我的情況),資料包將被丟棄並重置連接。

另請注意,即使在描述的第一種情況下,後端部分中指向的伺服器 HAProxy 也可能需要 SNI。因此轉送不帶 SNI 指示的不完整請求也會導致連線重設。

相關內容