Skip to content
EgyKode
Guided labnetworking

HTTP & TLS Troubleshooting

Take a failing HTTPS request apart layer by layer: DNS, TCP, TLS, HTTP — and know which one broke.

Time
50 min
Level
Intermediate
Objectives
4 objectives
Cost
Free

Before you start

You will need

  • curl
  • openssl
  • dig
  • nc

You will be able to

  • Inspect a certificate chain and its expiry from the command line
  • Separate a TLS failure from an HTTP failure
  • Read `curl -v` output as a sequence of layers

CostFree

— uses public endpoints and a local container.

Success criteria

0 of 4

The scenario#

"The site is down." It returns a certificate error in one browser, works in another, and curl fails with something different again.

Each of those is a different layer, and the fix depends entirely on which one.

The four layers, in order#

text
DNS  ->  TCP  ->  TLS  ->  HTTP
dig      nc       openssl   curl

curl -v walks all four in one command, and its output is readable as exactly that sequence:

Terminal
curl -v https://egykode.com/ 2>&1 | head -20
text
* Host egykode.com:443 was resolved.          <- DNS worked
* Connected to egykode.com (52.84.143.46)      <- TCP worked
* TLS handshake, Certificate (11):             <- TLS in progress
* SSL certificate verify ok.                   <- TLS worked
> GET / HTTP/2                                 <- HTTP begins

Whichever line is missing is the layer that failed.

1. DNS#

Terminal
dig +short egykode.com
dig egykode.com | grep -A2 "ANSWER SECTION"

A wrong-but-cached answer is the common case; the TTL in the answer tells you whether you are looking at cache or configuration.

2. TCP, without TLS in the way#

Terminal
nc -vz egykode.com 443

This proves reachability on its own. If nc connects and curl still fails, the network is fine and the problem is TLS or above — which removes firewalls and security groups from the investigation entirely.

3. TLS#

Terminal
echo | openssl s_client -connect egykode.com:443 -servername egykode.com 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates
 
# Just the expiry, for a monitoring check
echo | openssl s_client -connect egykode.com:443 2>/dev/null \
  | openssl x509 -noout -enddate
 
# The full chain the server actually sends
echo | openssl s_client -connect egykode.com:443 -showcerts 2>/dev/null | grep -c "BEGIN CERTIFICATE"

-servername sets SNI. Without it a server hosting several sites returns its default certificate, and you diagnose the wrong one.

The three failures you will meet:

MessageMeansFix
certificate has expiredThe dates have passedRenewal automation stopped
unable to get local issuer certificateChain incompleteServer sends the leaf but not the intermediate
certificate is not valid for <host>Right cert, wrong nameMissing SAN entry

The second is the subtle one: it works in browsers, which cache intermediates from previous sites, and fails in curl and in your application. "It works in Chrome" is not evidence the chain is complete.

4. HTTP#

Terminal
curl -sI https://egykode.com/ | head -5
curl -s -o /dev/null -w 'code=%{http_code} tls=%{time_appconnect} total=%{time_total}\n' https://egykode.com/

time_appconnect is when TLS finished. If it is close to time_total, the handshake is your latency, not the application.

5. Practise on deliberately broken endpoints#

Terminal
curl -v https://expired.badssl.com/        2>&1 | grep -i "certificate"
curl -v https://wrong.host.badssl.com/     2>&1 | grep -i "certificate"
curl -v https://untrusted-root.badssl.com/ 2>&1 | grep -i "issuer"
curl -v https://self-signed.badssl.com/    2>&1 | grep -i "self.signed"

Read each error and name the layer before moving on. -k skips verification and is useful to confirm the diagnosis — if -k works, the transport is fine and the fault is purely certificate validation.

When it goes wrong#

Works in the browser, fails in curl

Almost always an incomplete chain. The browser cached the intermediate from another site; curl did not.

SSL_ERROR_SYSCALL with no detail

The connection dropped during the handshake — often a middlebox, or the server rejecting the TLS version. Try --tlsv1.2.

Certificate looks correct but the name is wrong

You omitted -servername, so the server returned its default certificate.

nc connects but curl times out

The port is open and nothing is speaking HTTPS on it — check you are not hitting a plain HTTP port with https://.

The concept behind it

Ready to try it without help?Do the challenge

Phase complete · 02 The application, in containers

You can now: The application runs locally in production-shaped containers, behind a reverse proxy, over TLS.

Next phase

Lab 13 of 58 on the project path

03 · AWS by handAWS IAM & Least PrivilegeWrite a policy that grants exactly one action, prove what it blocks, and swap a long-lived key for a role.50 minBeginner

Previous: Reverse Proxy & Load Balancing with Nginx