Réinitialisation de la connexion lors du handshake TLS pour les clients sans SNI

Problème constaté

Votre application cliente peut rencontrer des erreurs de réinitialisation ou de refus de connexion, ou des erreurs similaires lors du handshake TLS lorsque vous appelez le point de terminaison Apigee.

Messages d'erreur

  • Les clients Postman ou Node.js peuvent voir des messages d'erreur ECONRESET.

  • Curl peut afficher le message Connection reset by peer (Connexion réinitialisée par le pair) lors d'appels HTTPS directement à l'adresse IP d'entrée Apigee. Exemple :

    curl https://1.2.3.4/basepath -H "Host: your.apigee.domain" -kv
    * Connected to 1.2.3.4 (1.2.3.4) port 443
    * (304) (OUT), TLS handshake, Client hello (1):
    * Recv failure: Connection reset by peer
    * Closing connection 
  • D'autres clients peuvent afficher des erreurs différentes. Toutefois, le schéma serait le même : le client n'est pas en mesure d'établir une connexion complète lors du handshake TLS.

Causes possibles

La passerelle d'entrée d'Apigee hybrid est activée par défaut avec l'indication du nom du serveur (SNI). Ce problème peut se produire si votre client n'est pas compatible avec SNI et qu'aucune route Apigee générique n'est configurée pour activer les clients non SNI. Cela entraîne l'absence d'envoi de certificat de serveur TLS par défaut au client et une réinitialisation TCP de l'entrée Apigee.

Diagnostic

  1. Déterminez si votre client est compatible avec l'extension SNI. Si vous savez déjà que SNI n'est pas activé, passez à l'étape 4 pour valider la configuration d'Apigee Hybrid.

    Examinez les journaux d'accès Apigee Ingress pour détecter les requêtes client sans nom de serveur SNI, et vérifiez si les hôtes virtuels ne sont pas configurés avec un certificat par défaut pour les clients non SNI.

    • Obtenez la liste de vos pods apigee-ingressgateway à l'aide de la commande suivante :
      kubectl -n apigee get pods -l app=apigee-ingressgateway

      Exemple de sortie

      NAME                                                              READY   STATUS    RESTARTS   AGE
      apigee-ingressgateway-ext-ingress-myorg-hyb-8f2c412-dvrcp         2/2     Running   0          46h
      apigee-ingressgateway-ext-ingress-myorg-hyb-8f2c412-wg26k         2/2     Running   0          46h
      
    • Obtenez les journaux d'un pod apigee-ingressgateway.
      kubectl -n apigee logs APIGEE_INGRESSGATEWAY_POD
      APIGEE_INGRESSGATEWAY_POD est un pod apigee-ingressgateway listé dans la résultat de la commande précédente.
    • Voici un exemple de journal d'accès :
      {
        "request_time": 1,
        "tls_protocol": null,
        "upstream_service_time": null,
        "request_method": null,
        "request_protocol": null,
        "upstream_response_time": null,
        "bytes_sent": 0,
        "start_time": "2025-05-19T04:46:20.117Z",
        "bytes_received": 0,
        "host": null,
        "upstream_cluster": null,
        "upstream_address": null,
        "remote_address": "10.138.0.28:19432",
        "request_path": null,
        "request_id": null,
        "user_agent": null,
        "status_details": "filter_chain_not_found",
        "request": "- - -",
        "status": 0,
        "x_forwarded_for": null,
        "apigee_dynamic_data": null,
        "upstream_response_flags": "NR",
        "sni_host": null
      }
      
    • En analysant le journal précédent, vous pouvez déduire les éléments suivants :
      1. "sni_host": null : le client n'est pas compatible avec SNI, car il n'y a pas de nom d'hôte SNI. Par exemple, api-test.mydomain.com est associé à cette requête.
      2. "status_details": "filter_chain_not_found"  : les certificats de serveur sont sélectionnés en fonction d'un filter chain basé sur le sni_host. Si aucun sni_host n'existe et qu'aucune valeur par défaut n'est configurée, le filter chain est introuvable. Cela signifie qu'aucun certificat de serveur n'est renvoyé, comme le montre l'exemple de requête client.
      3. "status": 0 : aucun code d'état n'est disponible, car la connexion a été réinitialisée.
  2. Au lieu d'examiner les journaux, une méthode plus précise pour vérifier si un client est compatible avec SNI consiste à capturer des paquets devant Apigee Ingress ou sur Apigee Ingress lui-même. Cela vous aidera à déterminer si le client envoie l'en-tête SNI pour le handshake TLS.
    1. Pour exécuter Apigee Ingress sur Google Kubernetes Engine, vous devez vous connecter en SSH au nœud exécutant la passerelle Ingress, puis installer toolbox et tcpdump.
      tcpdump -n -i any -s 0 'host IP_Address' -w FILE_NAME

      FILE_NAME correspond au nom du fichier, y compris le chemin d'accès, dans lequel vous souhaitez enregistrer la sortie de la capture de paquets.

    2. Analysez la capture de paquets à l'aide de Wireshark ou d'un outil similaire.
    3. Voici un exemple d'analyse d'une capture de paquets à l'aide de Wireshark sur Apigee Ingress. .
      • Dans le résultat de la capture de paquets, le message 83 indique que le client (source) a envoyé un message "Client Hello" à Apigee Ingress (destination). client-hello.png
      • Lorsque vous sélectionnez le message Client Hello et examinez le protocole Handshake : Client Hello, vous constatez que l'extension : server_name est manquante. client-hello-extension.png
      • Par exemple, un client compatible avec SNI affichera Extension: server_name dans le résultat, comme illustré dans l'exemple suivant. client-hello-extension-sni.png
      • Cela confirme que le client n'a pas envoyé server_name à Apigee Ingress.
      • Étant donné qu'aucun server_name SNI n'est inclus dans le message Client Hello, aucun certificat de serveur n'est renvoyé et Apigee Ingress ferme la connexion avec un paquet RST.
  3. Vérifiez si les clients non SNI sont compatibles en testant un point de terminaison Apigee avec un outil tel qu'OpenSSL pour envoyer des requêtes avec ou sans l'en-tête SNI.al.
    1. Vérifiez si les clients non SNI sont activés.
      openssl s_client -connect api-test.mydomain.com:443 -noservername

      Exemple de résultat

      Connecting to 1.2.3.4
      CONNECTED(00000005)
      write:errno=54
      ---
      no peer certificate available
      ---
      No client certificate CA names sent
      ---
      SSL handshake has read 0 bytes and written 299 bytes
      Verification: OK
      ---
      New, (NONE), Cipher is (NONE)
      This TLS version forbids renegotiation.
      Compression: NONE
      Expansion: NONE
      No ALPN negotiated
      Early data was not sent
      Verify return code: 0 (ok)
      ---
      
      
    2. La réponse ci-dessus indique no peer certificate available (aucun certificat homologue disponible), ce qui signifie que les clients SNI ne sont pas activés dans la route Apigee, car nous avons transmis l'option -noservername dans la commande. Si un certificat homologue a été renvoyé lors de l'utilisation de l'indicateur -noservername, cela indique qu'une route générique est configurée.
  4. Examinez la configuration actuelle des routes Apigee pour voir si une route générique est configurée et activée sur l'hôte virtuel.
    1. Obtenez la liste des routes Apigee définies à l'aide de la commande suivante :
      kubectl -n apigee get apigeeroutes 

      Exemple de sortie

      NAME                                  STATE     AGE
      myorg-hyb-dev-grp-000-33620d0         running   2d1h
      non-sni                               running   17s
      
    2. Vérifiez chaque route Apigee pour les noms d'hôte qui incluent un caractère générique.

      Pour chaque route Apigee, exécutez la commande fournie pour récupérer un tableau JSON de ses noms d'hôte définis. Une route générique est indiquée par un astérisque (*) dans le résultat.

      kubectl -n apigee get apigeeroute APIGEE_ROUTE_NAME

      Exemple pour la route myorg-hyb-dev-grp-000-33620d0 :

      kubectl -n apigee get apigeeroute myorg-hyb-dev-grp-000-33620d0 -o jsonpath='{.spec.hostnames}'

      Exemple de sortie

      ["api-test.mydomain.com"]

      Exemple pour la route non-sni :

      kubectl -n apigee get apigeeroute non-sni -o jsonpath='{.spec.hostnames}'

      Exemple de sortie

      ["*"]

      L'apigeeroute non-sni est une route générique, car elle contient (*) comme nom d'hôte.

    3. Si une route générique est configurée, les clients non SNI sont activés.
    4. Pour la route générique, assurez-vous que l'indicateur enableNonSniClient est défini sur "true". La commande suivante s'exécute sur la route générique avec le client non-sni.
      kubectl -n apigee get apigeeroute non-sni -o jsonpath='{.spec.enableNonSniClient}'

      Exemple de sortie

      true
    5. Si la route générique existe et que les clients non SNI sont activés, examinez la configuration de l'hôte virtuel dans le fichier overrides.yaml pour vous assurer que la route générique est listée dans additionalGateways.
      virtualhosts:
      - name: dev-grp
        selector:
          app: apigee-ingressgateway
          ingress_name: ext-ingress
        sslCertPath: ./certs/keystore_dev-grp.pem
        sslKeyPath: ./certs/keystore_dev-grp.key
        additionalGateways: ["non-sni"]
        
    6. Le additionalGateways s'affiche dans la route Apigee définie par la configuration de votre hôte virtuel. Utilisez la commande suivante pour vérifier que votre additionalGateway configuré s'affiche dans la configuration de route Apigee.
        kubectl -n apigee get apigeeroute APIGEE_ROUTE_NAME -o jsonpath='{.spec.additionalGateways}

      Par exemple, la route myorg-hyb-dev-grp-000-33620d0 doit afficher la route non-sni en tant que additionalGateway.

        kubectl -n apigee get apigeeroute myorg-hyb-dev-grp-000-33620d0 -o jsonpath='{.spec.additionalGateways}'

      Exemple de sortie

      ["non-sni"]

    Solution

    Si les étapes de diagnostic indiquent que votre client est un client non SNI et que les clients non SNI ne sont pas activés ni correctement configurés dans votre installation Apigee Hybrid, suivez la documentation Activer les clients non SNI pour autoriser le trafic provenant de clients non SNI.

    Vous devez collecter des informations de diagnostic

    Si le problème persiste, même après avoir suivi les instructions ci-dessus, rassemblez les informations de diagnostic suivantes, puis contactez Google Cloud Customer Care :
    • Overrides.yaml
    • Résultat des commandes suivantes
      • kubectl -n apigee get apigeeroutes
      • Pour chacun des itinéraires indiqués, exécutez la commande suivante : kubectl -n apigee describe apigeeroute
    • Groupe(s) d'environnements présentant le problème