๐ŸŒ

Network Debugging

๐Ÿ‘จโ€๐Ÿณ Chefโฑ๏ธ 45 minutes

๐Ÿ“‹ Suggested prerequisites

  • โ€ขBasic terminal
  • โ€ขHTTP knowledge

What you'll learn

To diagnose network problems like a professional. When your API returns 502, when CORS blocks you, or when "it works on my machine but not in production", you'll know exactly where to look.

By the end you'll have a mental and practical toolkit to solve the most common network problems.


Your toolkit

curl: The Swiss army knife

# Basic GET
curl https://api.example.com/health

# See response headers
curl -I https://api.example.com/health

# See full exchange (request + response)
curl -v https://api.example.com/health

# POST with JSON
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"name":"test"}' \
  https://api.example.com/users

# With authentication
curl -H "Authorization: Bearer TOKEN" https://api.example.com/me

# Measure times
curl -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
  -o /dev/null -s https://api.example.com

ping: Check connectivity

# Basic
ping google.com

# Only 4 packets
ping -c 4 google.com

# If fails: network or DNS problem
# If works: server responds to ICMP

nslookup / dig: DNS

# Resolve domain
nslookup api.example.com

# More detail with dig
dig api.example.com

# See specific records
dig api.example.com A      # IPv4
dig api.example.com AAAA   # IPv6
dig api.example.com CNAME  # Alias
dig api.example.com MX     # Mail servers

netstat / ss: Active connections

# See listening ports (Linux)
ss -tlnp

# See listening ports (Mac)
netstat -an | grep LISTEN

# See established connections
ss -tn
netstat -an | grep ESTABLISHED

Scenario 1: "My API returns 502"

Step 1: Verify the server responds

# First, verify DNS
nslookup api.example.com
# If fails: DNS problem

# Then, verify connectivity
ping api.example.com
# If fails: server down or firewall

# Finally, verify HTTP
curl -I https://api.example.com/health

Step 2: If using reverse proxy (Nginx)

# See Nginx logs
sudo tail -f /var/log/nginx/error.log

# Common errors:
# "upstream timed out" - backend too slow
# "connection refused" - backend not running
# "no live upstreams" - all backends down

Step 3: Verify the backend

# See if process is running
ps aux | grep node  # or python, java, etc.

# See if listening on correct port
ss -tlnp | grep 3000

# See backend logs
docker logs my-app --tail 100

# Or if systemd
journalctl -u my-app -f

Most common cause

502 Bad Gateway almost always means:
1. Backend is not running
2. Backend listens on different port
3. Backend takes longer than Nginx timeout

Scenario 2: "CORS blocks me"

Understanding CORS

Your frontend:   https://app.example.com
Your API:        https://api.example.com

Browser: "Hey API, my origin is app.example.com"
API:     "I don't know you, blocked"
Browser: "CORS error!"

Step 1: Check the exact error

Open DevTools > Console

Common errors:
- "No 'Access-Control-Allow-Origin' header" โ†’ Missing header
- "not in the Access-Control-Allow-Origin list" โ†’ Origin not allowed
- "Method PUT is not allowed" โ†’ Method not allowed

Step 2: Verify headers with curl

# Simulate preflight OPTIONS
curl -X OPTIONS \
  -H "Origin: https://app.example.com" \
  -H "Access-Control-Request-Method: POST" \
  -I https://api.example.com/endpoint

# Look for these headers in response:
# Access-Control-Allow-Origin: https://app.example.com
# Access-Control-Allow-Methods: GET, POST, PUT, DELETE
# Access-Control-Allow-Headers: Content-Type, Authorization

Step 3: Configure the server

// Express.js
const cors = require('cors');

app.use(cors({
  origin: 'https://app.example.com', // Or array of origins
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true // If using cookies
}));

Scenario 3: "SSL certificate fails"

Step 1: Verify the certificate

# See certificate details
echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null | openssl x509 -text -noout

# See only dates
echo | openssl s_client -connect api.example.com:443 2>/dev/null | openssl x509 -dates -noout

# Expected output:
# notBefore=Jan  1 00:00:00 2024 GMT
# notAfter=Apr  1 00:00:00 2024 GMT

Common errors

ErrorCauseSolution
certificate has expiredExpired certRenew with certbot
unable to verifyIncomplete chainInclude intermediate cert
hostname mismatchDomain doesn't matchCheck CN/SAN of cert
self-signedSelf-signed certUse Let's Encrypt

Renew with Certbot

# See certificate status
sudo certbot certificates

# Renew manually
sudo certbot renew

# Renew specific domain
sudo certbot certonly -d api.example.com

Scenario 4: "Responses are very slow"

Step 1: Measure where latency is

curl -w "\n\
DNS:        %{time_namelookup}s\n\
Connect:    %{time_connect}s\n\
TLS:        %{time_appconnect}s\n\
TTFB:       %{time_starttransfer}s\n\
Total:      %{time_total}s\n" \
  -o /dev/null -s https://api.example.com/slow-endpoint

# Example output:
# DNS:        0.023s      <- DNS resolution
# Connect:    0.045s      <- TCP connection
# TLS:        0.120s      <- TLS handshake
# TTFB:       2.500s      <- Time to first byte (PROBLEM!)
# Total:      2.550s

Interpretation

If DNS is high:     DNS resolver problem
If Connect is high: Network latency or server far away
If TLS is high:     Certificate/crypto problem
If TTFB is high:    Server takes long to process
If Total >> TTFB:   Response too large

Step 2: Diagnose the backend

# See slow queries in PostgreSQL
SELECT query, calls, mean_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;

# See active processes
SELECT pid, query, state, wait_event_type
FROM pg_stat_activity
WHERE state = 'active';

Cheat Sheet

Essential commands

CommandUse
curl -I URLSee response headers
curl -v URLSee full exchange
ping HOSTVerify connectivity
nslookup DOMAINResolve DNS
dig DOMAINDetailed DNS
ss -tlnpListening ports (Linux)
netstat -anConnections (Mac/Linux)
traceroute HOSTPacket route

Status codes

CodeMeaningWhere to look
400Bad RequestMalformed request
401UnauthorizedToken/API key
403ForbiddenPermissions
404Not FoundCorrect URL?
429Rate LimitedToo many requests
500Internal ErrorBackend logs
502Bad GatewayBackend + proxy logs
503UnavailableServer overloaded
504Gateway TimeoutProxy timeout

Next step

Practice these commands with your own services. When something fails, you'll have the tools to diagnose it.