Por que a instrução de front-end "aceitação de conteúdo de solicitação tcp" é necessária para o roteamento adequado baseado em HAProxy SNI?

Por que a instrução de front-end "aceitação de conteúdo de solicitação tcp" é necessária para o roteamento adequado baseado em HAProxy SNI?

Recentemente, tentei configurar o roteamento baseado em SNI no HAProxy para mongodb+srvconexão do protocolo mongodb.

Eu fiz funcionar, mas não foi até colocar

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

na minha configuração de frontend que começou a funcionar corretamente

Sem estes (oucom apenas umdestes) continuei recebendo redefinições de conexão esporádicas em cerca de 70% das minhas solicitações. Observe que em algum momento a conexão conseguiu ser estabelecida.

De acordo comhttp://cbonte.github.io/haproxy-dconv/2.0/configuration.html#4-tcp-request%20content

As regras baseadas em conteúdo são avaliadas na ordem exata de declaração. Se nenhuma regra corresponder ou se não houver nenhuma regra, a ação padrão será aceitar o conteúdo. Não há limite específico para o número de regras que podem ser inseridas.

Portanto, deveria estar funcionando por padrão.

Ou estou faltando algum conceito fundamental de TCP ou algum detalhe específico da conexão do Mongo. Mas percebi que quase todo mundo tem a mesma regra definida quando optam pelo roteamento baseado em SNI, então deve fazer sentido para a maioria das pessoas.

Configuração funcional do 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

Vale ressaltar também que o HAProxy é implantado no Kubernetes (cluster gerenciado pelo Google no GCP), possui um istio-sidecar e é exposto via serviço Internal LoadBalancer k8s.

Como afirmado, a configuração acima funciona perfeitamente bem. O que me interessa é por que tcp-request content accepté absolutamente necessário e a conexão nem sempre é aceita por padrão aqui.

Responder1

Tentarei responder à minha própria pergunta depois de pensar um pouco.

Portanto, os documentos do HAProxy também têm a seguinte menção: http://cbonte.github.io/haproxy-dconv/2.0/configuration.html

Se for necessária a troca de conteúdo, é recomendado primeiro aguardar uma saudação completa do cliente (tipo 1), como no exemplo abaixo.

Agora, como os dados SNI também estão contidos na seção Client Hello da solicitação (https://www.rfc-editor.org/rfc/rfc6066#page-6) minha suposição é a seguinte:

No caso de o Client Hello estar espalhado por vários pacotes TCP e no tcp-request content accept is configured, ao receber o primeiro pacote o HAProxy tenta roteá-lo e uma de duas coisas acontece:

  1. Se o back-end padrão estiver configurado, o pacote será encaminhado para esse back-end.
  2. Se nenhum back-end padrão estiver configurado (meu caso), o pacote será descartado e a conexão será redefinida.

Observe também que mesmo no primeiro caso descrito, o servidor HAProxy aponta na seção de back-end também pode exigir SNI. Portanto, encaminhar uma solicitação incompleta sem a indicação do SNI também resultará na redefinição da conexão.

informação relacionada