Skip to content
Latchkey

"Connection timed out" (firewall blocks egress) in CI

The client sent SYN packets to open a connection and never heard back. Unlike a refused connection, a timeout means the packets were dropped in transit, which is the classic signature of a firewall or security group blocking egress.

What this error means

A request hangs for the full timeout, then fails with "Connection timed out" (curl exit 28) or "Operation timed out". DNS resolves fine; the failure is at connect, not lookup.

Terminal
curl: (28) Failed to connect to api.example.com port 443 after 130000 ms:
Connection timed out

Common causes

A firewall or security group drops the egress

The runner network only permits outbound to an allowlist. Packets to a non-allowed host or port are dropped, so the handshake never completes.

The destination host or port is not listening

A wrong port or a host that is down accepts no connection, but a dropping firewall in front produces a timeout rather than a refusal.

How to fix it

Confirm the block and allowlist the destination

  1. Test the exact host and port with a short connect timeout to isolate reachability.
  2. If it times out, add the destination host/port to the egress allowlist or security group.
  3. Re-run once the rule is in place.
Terminal
curl -sS --connect-timeout 5 https://api.example.com/ -o /dev/null -w '%{http_code}\n'

Route through the sanctioned proxy

If direct egress is blocked by policy, set the proxy the network expects so traffic leaves through the approved path.

.github/workflows/ci.yml
env:
  HTTPS_PROXY: http://proxy.corp.example:8080
  HTTP_PROXY: http://proxy.corp.example:8080

How to prevent it

  • Keep an explicit egress allowlist and add new destinations before CI needs them.
  • Set a short --connect-timeout so blocked hosts fail fast instead of hanging.
  • Document which endpoints jobs must reach so firewall rules stay in sync.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →