Se restablecen las conexiones durante el handshake de TLS para clientes que no son de la SNI

Síntoma

Es posible que tu aplicación cliente experimente errores de restablecimiento o rechazo de conexión, u otros similares, durante el handshake de TLS al llamar al endpoint de Apigee.

Mensajes de error

  • Es posible que los clientes de Postman o Node.js vean mensajes de error ECONRESET.

  • Curl puede mostrar el mensaje Connection reset by peer al hacer llamadas HTTPS directamente a la dirección IP de entrada de Apigee. Por ejemplo:

    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 
  • Es posible que otros clientes muestren errores diferentes. Sin embargo, el patrón sería el mismo: el cliente no puede establecer una conexión completa durante el handshake TLS.

Posibles motivos

La pasarela de entrada de Apigee Hybrid tiene habilitado de forma predeterminada el indicador del nombre del servidor (SNI). Este problema puede producirse si tu cliente no tiene habilitada la SNI y no hay ninguna ruta de Apigee comodín configurada para habilitar clientes que no sean de la SNI. Como resultado, no se envía ningún certificado de servidor TLS predeterminado al cliente y se produce un restablecimiento de TCP de entrada de Apigee.

Diagnóstico

  1. Determina si tu cliente tiene habilitado SNI. Si ya sabes que no está habilitado para SNI, ve al paso 4 para validar la configuración de Apigee Hybrid.

    Revisa los registros de acceso de Apigee Ingress para detectar solicitudes de clientes sin el nombre del servidor SNI y comprueba si los hosts virtuales no están configurados con un certificado predeterminado para clientes que no son de SNI.

    • Obtén una lista de tus pods apigee-ingressgateway con el siguiente comando:
      kubectl -n apigee get pods -l app=apigee-ingressgateway

      Ejemplo de salida

      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
      
    • Obtén los registros de un pod apigee-ingressgateway.
      kubectl -n apigee logs APIGEE_INGRESSGATEWAY_POD
      Donde APIGEE_INGRESSGATEWAY_POD es un pod apigee-ingressgateway que aparece en el resultado del comando anterior.
    • Un registro de acceso puede tener el siguiente aspecto:
      {
        "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
      }
      
    • Analizando el registro anterior, puedes deducir lo siguiente:
      1. "sni_host": null: El cliente no tiene habilitado el SNI porque no hay ningún nombre de host de SNI. Por ejemplo, api-test.mydomain.com está asociado a esta solicitud.
      2. "status_details": "filter_chain_not_found" : los certificados de servidor se seleccionan en función de un filter chain que se basa en el sni_host. Si no existe ningún sni_host y no se ha configurado ningún valor predeterminado, no se podrá encontrar el filter chain. Esto significa que no se devuelve ningún certificado de servidor, como se muestra en la solicitud de cliente de ejemplo.
      3. "status": 0: No hay ningún código de estado porque la conexión se ha restablecido.
  2. En lugar de revisar los registros, una forma más precisa de comprobar si un cliente tiene habilitado SNI sería capturar paquetes delante de Apigee Ingress o en Apigee Ingress. Esto ayudará a determinar si el cliente está enviando el encabezado SNI para el handshake TLS.
    1. Para ejecutar Apigee Ingress en Google Kubernetes Engine, necesitarías SSH en el nodo que ejecuta la pasarela de entrada e instalar toolbox y tcpdump.
      tcpdump -n -i any -s 0 'host IP_Address' -w FILE_NAME

      Donde FILE_NAME es el nombre del archivo, incluida la ruta, en el que quieres guardar la salida de la captura de paquetes.

    2. Analiza la captura de paquetes con Wireshark o una herramienta similar.
    3. A continuación, se muestra un análisis de ejemplo de una captura de paquetes realizada en Apigee Ingress con Wireshark. .
      • En el resultado de la captura de paquetes, el mensaje 83 indica que el cliente (origen) ha enviado un mensaje "Client Hello" a Apigee Ingress (destino). client-hello.png
      • Si seleccionas el mensaje Client Hello y examinas Handshake Protocol: Client Hello, verás que falta Extension: server_name. client-hello-extension.png
      • Por ejemplo, un cliente con SNI habilitado mostrará Extension: server_name en el resultado, como se muestra en el siguiente ejemplo. client-hello-extension-sni.png
      • Esto confirma que el cliente no ha enviado el server_name a Apigee Ingress.
      • Como no se incluye ningún server_name de SNI en el mensaje Client Hello, no se devuelve ningún certificado de servidor y Apigee Ingress cierra la conexión con un paquete RST.
  3. Comprueba si los clientes que no usan SNI son compatibles probando un endpoint de Apigee con una herramienta como OpenSSL para enviar solicitudes con o sin el encabezado SNI.
    1. Comprueba si los clientes que no son de la SNI están habilitados.
      openssl s_client -connect api-test.mydomain.com:443 -noservername

      Ejemplo de salida

      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 respuesta anterior muestra que no hay ningún certificado de peer disponible, lo que significa que los clientes de SNI no están habilitados en la ruta de Apigee, ya que hemos pasado la opción -noservername en el comando. Si se devuelve un certificado de peer al usar la marca -noservername, esto indicaría que se ha configurado una ruta comodín.
  4. Revisa la configuración de la ruta de Apigee para ver si hay una ruta comodín configurada y habilitada en el host virtual.
    1. Obtén una lista de las rutas de Apigee definidas con el siguiente comando:
      kubectl -n apigee get apigeeroutes 

      Ejemplo de salida

      NAME                                  STATE     AGE
      myorg-hyb-dev-grp-000-33620d0         running   2d1h
      non-sni                               running   17s
      
    2. Comprueba cada ruta de Apigee para ver si hay nombres de host que incluyan un comodín.

      Por cada ruta de Apigee, ejecuta el comando proporcionado para obtener una matriz JSON de sus nombres de host definidos. Las rutas comodín se indican con un asterisco (*) en la salida.

      kubectl -n apigee get apigeeroute APIGEE_ROUTE_NAME

      Ejemplo de ruta myorg-hyb-dev-grp-000-33620d0:

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

      Ejemplo de salida

      ["api-test.mydomain.com"]

      Ejemplo de ruta non-sni:

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

      Ejemplo de salida

      ["*"]

      La ruta non-sniapigeeroute es una ruta comodín porque contiene (*) como nombre de host.

    3. Si se configura una ruta comodín, se habilitan los clientes que no son de la SNI.
    4. En la ruta comodín, asegúrate de que la marca enableNonSniClient esté definida como true. El siguiente comando se ejecuta en la ruta comodín con el cliente non-sni.
      kubectl -n apigee get apigeeroute non-sni -o jsonpath='{.spec.enableNonSniClient}'

      Ejemplo de salida

      true
    5. Si la ruta comodín existe y los clientes que no son de la SNI están habilitados, revisa la configuración del host virtual en el archivo overrides.yaml para asegurarte de que la ruta comodín aparece en 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. El additionalGateways se mostrará en la ruta de Apigee definida por la configuración de su host virtual. Usa el siguiente comando para confirmar que el additionalGateway configurado aparece en la configuración de la ruta de Apigee.
        kubectl -n apigee get apigeeroute APIGEE_ROUTE_NAME -o jsonpath='{.spec.additionalGateways}

      Por ejemplo, la ruta myorg-hyb-dev-grp-000-33620d0 debería mostrar la ruta non-sni como additionalGateway.

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

      Ejemplo de salida

      ["non-sni"]

    Resolución

    Si los pasos de diagnóstico indican que tu cliente no tiene habilitado el SNI y los clientes que no tienen habilitado el SNI no están habilitados o configurados correctamente en tu instalación de Apigee Hybrid, sigue la documentación para habilitar clientes que no tienen habilitado el SNI para permitir el tráfico de clientes que no tienen habilitado el SNI.

    Debe recoger información de diagnóstico

    Si el problema persiste incluso después de seguir las instrucciones anteriores, recoge la siguiente información de diagnóstico y ponte en contacto con el equipo de Asistencia de Google Cloud:
    • Overrides.yaml
    • Resultado de los siguientes comandos
      • kubectl -n apigee get apigeeroutes
      • En cada una de las rutas indicadas, ejecuta el siguiente comando: kubectl -n apigee describe apigeeroute
    • Grupos de entornos que presentan el problema