Warum ist die Frontend-Anweisung „TCP-Request-Inhalt akzeptieren“ für ein ordnungsgemäßes HAProxy SNI-basiertes Routing erforderlich?

Warum ist die Frontend-Anweisung „TCP-Request-Inhalt akzeptieren“ für ein ordnungsgemäßes HAProxy SNI-basiertes Routing erforderlich?

mongodb+srvIch habe kürzlich versucht, SNI-basiertes Routing auf HAProxy für eine MongoDB -Protokollverbindung einzurichten .

Ich habe es zum Laufen gebracht, aber erst als ich

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

in meiner Frontend-Konfiguration, dass es richtig funktionierte

Ohne diese (odermit nur einemdavon) Bei etwa 70 % meiner Anfragen kam es immer wieder zu sporadischen Verbindungsabbrüchen. Beachten Sie, dass die Verbindung manchmal tatsächlich hergestellt werden konnte.

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

Inhaltsbasierte Regeln werden in der genauen Reihenfolge ihrer Deklaration ausgewertet. Wenn keine Regel übereinstimmt oder keine Regel vorhanden ist, besteht die Standardaktion darin, den Inhalt zu akzeptieren. Es gibt keine bestimmte Begrenzung für die Anzahl der Regeln, die eingefügt werden können.

Es sollte also standardmäßig funktionieren.

Entweder übersehe ich ein grundlegendes TCP-Konzept oder ein bestimmtes Mongo-Verbindungsdetail. Aber mir ist aufgefallen, dass fast jeder die gleiche Regel definiert hat, wenn er sich für SNI-basiertes Routing entscheidet, also muss es für die meisten Leute Sinn ergeben.

Funktionierende HAProxy-Konfiguration:

    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

Erwähnenswert ist auch, dass HAProxy in Kubernetes (von Google verwalteter Cluster in GCP) bereitgestellt wird, über einen Istio-Sidecar verfügt und über den Internal LoadBalancer k8s-Dienst verfügbar gemacht wird.

Wie gesagt funktioniert die obige Konfiguration einwandfrei. Mich interessiert, warum dies tcp-request content acceptunbedingt erforderlich ist und die Verbindung hier nicht [immer] standardmäßig akzeptiert wird.

Antwort1

Ich werde versuchen, meine eigene Frage zu beantworten, nachdem ich darüber nachgedacht habe.

Daher enthalten die HAProxy-Dokumente auch Folgendes: http://cbonte.github.io/haproxy-dconv/2.0/configuration.html

Wenn ein Inhaltswechsel erforderlich ist, wird empfohlen, zunächst auf ein vollständiges Client-Hello (Typ 1) zu warten, wie im folgenden Beispiel.

Da die SNI-Daten nun auch im Abschnitt „Client Hello“ der Anfrage enthalten sind (https://www.rfc-editor.org/rfc/rfc6066#page-6) meine Vermutung ist folgende:

Falls Client Hello über mehrere TCP-Pakete verteilt ist und kein tcp-request content accept is configured, versucht HAProxy beim Empfang des ersten Pakets, es weiterzuleiten, und es passiert eines der folgenden zwei Dinge:

  1. Wenn das Standard-Backend konfiguriert ist, wird das Paket an dieses Backend weitergeleitet.
  2. Wenn kein Standard-Backend konfiguriert ist (mein Fall), wird das Paket gelöscht und die Verbindung zurückgesetzt.

Beachten Sie auch, dass selbst im ersten beschriebenen Fall der Server, auf den HAProxy im Backend-Abschnitt verweist, möglicherweise ebenfalls SNI erfordert. Das Weiterleiten einer unvollständigen Anfrage ohne SNI-Angabe führt daher ebenfalls zur Zurücksetzung der Verbindung.

verwandte Informationen