Compute Engine SSL Socket Handshake Timeout on avangartclinic com

Hello Google Cloud Community,

We are running a web application deployed on Google Cloud Compute Engine behind an HTTPS Load Balancer, but we are encountering socket connection handshake timeout issues.

Technical Issue: When external browser clients attempt to establish secure socket sessions with our primary web domain (Avangart Clinic), the load balancer drops the connection during the TLS preflight handshake with a CORS Origin Header Missing error.

Environment Details:

  • Portal Domain: avangartclinic.com

  • Infrastructure: Google Cloud Compute Engine / External HTTP(S) Load Balancer

  • Protocol: HTTPS / TLS 1.3

  • Browsers Tested: Google Chrome Mobile, Safari iOS, Microsoft Edge

Steps Taken:

  1. Verified that the primary SSL certificate on avangartclinic.com is fully valid and cross-chain verified via SSL Labs.

  2. Added cross-origin headers (COOP/COEP) in our backend Nginx server block.

  3. Verified that direct internal IP calls complete without delay, but external requests through the HTTPS load balancer timeout during TLS negotiation.

Are there specific HTTP header backend policies or SSL negotiation settings required in Google Cloud Load Balancing for custom HTTPS web domains?

Any developer advice or configuration guidance would be greatly appreciated.

Thanks!

There are no special SSL negotiation or backend header settings required in Google Cloud Load Balancing for custom HTTPS domains - TLS 1.3 and WebSockets work out of the box.

That being said, the symptoms described mix a few different protocol layers. There isn’t a “TLS preflight handshake” - the TLS 1.3 handshake (ClientHello / ServerHello) completes before any HTTP request or Origin header is sent over the wire, so the load balancer will never drop a TLS handshake due to a missing Origin header. Similarly, Cross-Origin-Opener-Policy (COOP) and Cross-Origin-Embedder-Policy (COEP) control browser cross-origin document isolation rather than CORS (Access-Control-Allow-*).

Depending on whether the connection is actually timing out during the handshake or failing at the HTTP/WebSocket layer after TLS completes, I’d recommend checking the following:

  1. Verify firewall rules and backend service protocol (if connections time out through the load balancer but work via internal IP):

    • Make sure a VPC ingress firewall rule allows traffic from the Google Cloud load balancer and health check ranges (35.191.0.0/16 and 130.211.0.0/22, plus the regional REGIONAL_MANAGED_PROXY subnet range if you’re using a Regional External Application Load Balancer) to your Compute Engine instances on the backend port.
    • Check the protocol configured on the backend service (HTTP, HTTPS, or HTTP2). If the backend service protocol is set to HTTPS while Nginx on the VM is listening for plaintext HTTP on that port, the load balancer’s backend TLS handshake to the VM will fail. Either set the backend service protocol to HTTP or configure TLS on the Nginx listener.
    • Check Cloud Logging (resource.type="http_load_balancer") and inspect jsonPayload.statusDetails (for example, failed_to_connect_to_backend or backend_timeout) to confirm whether the request is reaching the load balancer proxy and failing on the backend connection.
  2. Check backend service timeout and Nginx upgrade headers (if “secure socket sessions” refers to WebSockets over wss://):

    • Browsers don’t send OPTIONS preflight requests for WebSockets, but they do send an Origin header on the initial HTTP GET upgrade request. Make sure no custom request header policies on the backend service strip the Origin header, and verify that your Nginx server block forwards the required upgrade headers to your upstream application:

      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Host $host;
      proxy_set_header Origin $http_origin;
      
    • The backend service timeout (timeoutSec) defaults to 30 seconds and applies to the full lifetime of a WebSocket connection. Increase it if long-lived WebSocket sessions are being closed prematurely:

      gcloud compute backend-services update <BACKEND_SERVICE_NAME> \
          --global \
          --timeout=3600s
      
  3. Configure a CORS policy for standard HTTP preflight (OPTIONS) requests:

    • If browser fetch or XHR requests are failing CORS preflight checks, configure a native CORS policy on the backend service (or return Access-Control-Allow-* headers from Nginx) instead of COOP/COEP:

      gcloud compute backend-services update <BACKEND_SERVICE_NAME> \
          --global \
          --cors-policy-allow-origins="https://<ALLOWED_ORIGIN>" \
          --cors-policy-allow-methods="GET,POST,PUT,DELETE,OPTIONS" \
          --cors-policy-allow-headers="Authorization,Content-Type,Origin,Accept" \
          --cors-policy-allow-credentials \
          --cors-policy-max-age=3600