Debug DNS resolution and network connectivity. Use when troubleshooting DNS failures, testing port connectivity, diagnosing firewall rules, inspecting HTTP requests with curl verbose mode, configuring /etc/hosts, or debugging proxy and certificate issues.
---
name: dns-networking
description: Debug DNS resolution and network connectivity. Use when troubleshooting DNS failures, testing port connectivity, diagnosing firewall rules, inspecting HTTP requests with curl verbose mode, configuring /etc/hosts, or debugging proxy and certificate issues.
metadata: {"clawdbot":{"emoji":"🌐","requires":{"anyBins":["dig","nslookup","curl","ping","nc"]},"os":["linux","darwin","win32"]}}
---
# DNS & Networking
Debug DNS resolution, network connectivity, and HTTP issues. Covers dig/nslookup, port testing, firewall rules, curl diagnostics, /etc/hosts, proxy configuration, and certificate troubleshooting.
## When to Use
- DNS name not resolving or resolving to wrong IP
- Connection refused / connection timed out errors
- Diagnosing firewall or security group rules
- HTTP requests failing for unclear reasons
- Proxy configuration issues
- SSL/TLS certificate errors
- Testing connectivity between services
## DNS Debugging
### Query DNS records
```bash
# A record (IP address)
dig example.com
dig +short example.com
# Specific record types
dig example.com MX # Mail servers
dig example.com CNAME # Aliases
dig example.com TXT # Text records (SPF, DKIM, etc.)
dig example.com NS # Name servers
dig example.com AAAA # IPv6 address
dig example.com SOA # Start of Authority
# Query a specific DNS server
dig @8.8.8.8 example.com
dig @1.1.1.1 example.com
# Trace the full resolution path
dig +trace example.com
# Reverse lookup (IP → hostname)
dig -x 93.184.216.34
# nslookup (simpler, works everywhere)
nslookup example.com
nslookup example.com 8.8.8.8 # Query specific server
nslookup -type=MX example.com
# host (simplest)
host example.com
host -t MX example.com
```
### Check DNS propagation
```bash
# Query multiple public DNS servers
for dns in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
echo -n "$dns: "
dig +short @"$dns" example.com
done
# Check TTL (time to live)
dig example.com | grep -E '^\S+\s+\d+\s+IN\s+A'
# The number is TTL in seconds
```
### Local DNS issues
```bash
# Check /etc/resolv.conf (which DNS server the system uses)
cat /etc/resolv.conf
# Check /etc/hosts (local overrides)
cat /etc/hosts
# Flush DNS cache
# macOS:
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
# Linux (systemd-resolved):
sudo systemd-resolve --flush-caches
# Windows:
ipconfig /flushdns
# Check if systemd-resolved is running (Linux)
resolvectl status
```
### /etc/hosts patterns
```bash
# /etc/hosts — local DNS overrides (no TTL, instant)
# Point a domain to localhost (for development)
127.0.0.1 myapp.local
127.0.0.1 api.myapp.local
# Block a domain
0.0.0.0 ads.example.com
# Test a migration (point domain to new server before DNS change)
203.0.113.50 example.com
203.0.113.50 www.example.com
# Multiple names for one IP
192.168.1.100 db.local redis.local cache.local
```
## Port and Connectivity Testing
### Test if a port is open
```bash
# nc (netcat) — most reliable
nc -zv example.com 443
nc -zv -w 5 example.com 80 # 5 second timeout
# Test multiple ports
for port in 22 80 443 5432 6379; do
nc -zv -w 2 example.com $port 2>&1
done
# /dev/tcp (bash built-in, no extra tools needed)
timeout 3 bash -c 'echo > /dev/tcp/example.com/443' && echo "Open" || echo "Closed"
# curl (also tests HTTP)
curl -sI -o /dev/null -w "%{http_code}" https://example.com
# Test from inside a Docker container
docker exec my-container nc -zv db 5432
```
### Network path diagnostics
```bash
# traceroute (show network hops)
traceroute example.com
# mtr (continuous traceroute with stats — best for finding packet loss)
mtr example.com
mtr -r -c 20 example.com # Report mode, 20 packets
# ping
ping -c 5 example.com
# Show local network interfaces
ip addr show # Linux
ifconfig # macOS / older Linux
# Show routing table
ip route show # Linux
netstat -rn # macOS
route -n # Linux (older)
```
### Check listening ports
```bash
# What's listening on which port (Linux)
ss -tlnp
ss -tlnp | grep :8080
# macOS
lsof -i -P -n | grep LISTEN
lsof -i :8080
# Older Linux
netstat -tlnp
netstat -tlnp | grep :8080
# Which process is using a port
lsof -i :3000
fuser 3000/tcp # Linux
```
## curl Diagnostics
### Verbose request inspection
```bash
# Full verbose output (headers, TLS handshake, timing)
curl -v https://api.example.com/endpoint
# Show timing breakdown
curl -o /dev/null -s -w "
DNS: %{time_namelookup}s
Connect: %{time_connect}s
TLS: %{time_appconnect}s
TTFB: %{time_starttransfer}s
Total: %{time_total}s
Status: %{http_code}
Size: %{size_download} bytes
" https://api.example.com/endpoint
# Show response headers only
curl -sI https://api.example.com/endpoint
# Follow redirects and show each hop
curl -sIL https://example.com
# Resolve a domain to a specific IP (bypass DNS)
curl --resolve example.com:443:203.0.113.50 https://example.com
# Use a specific network interface
curl --interface eth1 https://example.com
```
### Debug common HTTP issues
```bash
# Test with different HTTP versions
curl --http1.1 https://example.com
curl --http2 https://example.com
# Test with specific TLS version
curl --tlsv1.2 https://example.com
curl --tlsv1.3 https://example.com
# Ignore certificate errors (debugging only)
curl -k https://self-signed.example.com
# Send request with custom Host header (virtual hosts)
curl -H "Host: example.com" https://203.0.113.50/
# Test CORS preflight
curl -X OPTIONS -H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: POST" \
-v https://api.example.com/endpoint
```
## Firewall Basics
### iptables (Linux)
```bash
# List all rules
sudo iptables -L -n -v
# Allow incoming on port 80
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# Allow incoming from specific IP
sudo iptables -A INPUT -s 203.0.113.0/24 -p tcp --dport 22 -j ACCEPT
# Block incoming on a port
sudo iptables -A INPUT -p tcp --dport 3306 -j DROP
# Save rules (persist across reboot)
sudo iptables-save > /etc/iptables/rules.v4
```
### ufw (simpler, Ubuntu/Debian)
```bash
# Enable
sudo ufw enable
# Allow/deny
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.0/24 to any port 22
sudo ufw deny 3306
# Check status
sudo ufw status verbose
# Reset all rules
sudo ufw reset
```
### macOS firewall
```bash
# Check status
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
# Enable
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on
# Allow an application
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/local/bin/myapp
```
## Proxy Configuration
### Environment variables
```bash
# Set proxy for most CLI tools
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
export NO_PROXY=localhost,127.0.0.1,.internal.example.com
# For curl specifically
export http_proxy=http://proxy.example.com:8080 # lowercase also works
# With authentication
export HTTPS_PROXY=http://user:password@proxy.example.com:8080
```
### Test through proxy
```bash
# curl with explicit proxy
curl -x http://proxy.example.com:8080 https://httpbin.org/ip
# SOCKS proxy
curl --socks5 localhost:1080 https://httpbin.org/ip
# Verify your external IP through proxy
curl -x http://proxy:8080 https://httpbin.org/ip
curl https://httpbin.org/ip # Compare with direct
# Test proxy connectivity
curl -v -x http://proxy:8080 https://example.com 2>&1 | grep -i "proxy\|connect"
```
### Common proxy issues
```bash
# Node.js fetch/undici does NOT respect HTTP_PROXY
# Use undici ProxyAgent or node-fetch with http-proxy-agent
# Git through proxy
git config --global http.proxy http://proxy:8080
git config --global https.proxy http://proxy:8080
# Remove:
git config --global --unset http.proxy
# npm through proxy
npm config set proxy http://proxy:8080
npm config set https-proxy http://proxy:8080
# pip through proxy
pip install --proxy http://proxy:8080 package-name
```
## Certificate Troubleshooting
```bash
# Check certificate from a server
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates
# Check expiry
echo | openssl s_client -connect example.com:443 2>/dev/null | \
openssl x509 -noout -enddate
# Download certificate chain
openssl s_client -showcerts -connect example.com:443 < /dev/null 2>/dev/null | \
awk '/BEGIN CERT/,/END CERT/' > chain.pem
# Verify a certificate against CA bundle
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt server.pem
# Check certificate for a specific hostname (SNI)
openssl s_client -connect cdn.example.com:443 -servername cdn.example.com
# Common error: "certificate has expired"
# Check the date on the server:
date
# If the system clock is wrong, certs will appear invalid
```
## Quick Diagnostics Script
```bash
#!/bin/bash
# net-check.sh — Quick network diagnostics
TARGET="${1:?Usage: net-check.sh <hostname> [port]}"
PORT="${2:-443}"
echo "=== Network Check: $TARGET:$PORT ==="
echo -n "DNS resolution: "
IP=$(dig +short "$TARGET" | head -1)
[[ -n "$IP" ]] && echo "$IP" || echo "FAILED"
echo -n "Ping: "
ping -c 1 -W 3 "$TARGET" > /dev/null 2>&1 && echo "OK" || echo "FAILED (may be blocked)"
echo -n "Port $PORT: "
nc -zv -w 5 "$TARGET" "$PORT" 2>&1 | grep -q "succeeded\|open" && echo "OPEN" || echo "CLOSED/FILTERED"
if [[ "$PORT" == "443" || "$PORT" == "8443" ]]; then
echo -n "TLS: "
echo | openssl s_client -connect "$TARGET:$PORT" -servername "$TARGET" 2>/dev/null | \
grep -q "Verify return code: 0" && echo "VALID" || echo "INVALID/ERROR"
echo -n "Certificate expiry: "
echo | openssl s_client -connect "$TARGET:$PORT" 2>/dev/null | \
openssl x509 -noout -enddate 2>/dev/null | sed 's/notAfter=//'
fi
echo "=== Done ==="
```
## Tips
- `dig +short` is the fastest way to check DNS from the command line. Use `@8.8.8.8` to bypass local caching.
- `nc -zv` is the simplest port connectivity test. If nc isn't available, use bash's `/dev/tcp`.
- curl's `-w` format string with timing variables is the fastest way to diagnose slow HTTP requests: DNS, connect, TLS, and TTFB are all visible.
- DNS changes propagate based on TTL. Check the current TTL with `dig` before expecting a DNS change to take effect.
- `/etc/hosts` changes take effect immediately (no TTL, no propagation delay). Use it to test domain migrations before changing DNS.
- When debugging "connection refused": first verify the port is open with `nc`, then check the service is actually listening with `ss -tlnp` or `lsof -i`.
- `mtr` is better than `traceroute` for diagnosing packet loss — it runs continuously and shows per-hop loss percentages.
- Node.js, Python `requests`, and many libraries do NOT automatically use `HTTP_PROXY` environment variables. Check each tool's proxy documentation.
don't have the plugin yet? install it then click "run inline in claude" again.
debug DNS resolution, network connectivity, and HTTP issues when DNS names won't resolve, ports are unreachable, firewall rules are unclear, HTTP requests fail silently, or certificates are invalid. covers dig, nslookup, port testing with netcat, curl diagnostics, /etc/hosts configuration, proxy setup, and TLS troubleshooting. use this when you need to isolate whether a problem is DNS, network routing, firewall rules, or the application itself.
required binaries (at least one from each group):
dig, nslookup, or hostnc (netcat) or bash's /dev/tcp (built-in)curlping, ip/ifconfig, ss/netstat/lsof, traceroute/mtropensslsystem access:
/etc/resolv.conf, /etc/hostsss -tlnpenvironment (optional but recommended):
HTTP_PROXY, HTTPS_PROXY, NO_PROXY env vars if behind corporate proxyCURL_CA_BUNDLE if using custom CA certificate bundleexternal connections:
/etc/resolv.conf)edge cases to know:
systemd-resolve --flush-caches on Linux, dscacheutil -flushcache on macOS).HTTP_PROXY env vars. each needs explicit config.date on target and client match.dig or curl requests to the same target may hit rate limits. add delays between attempts.-w or -timeout flags.input: hostname (e.g., example.com)
do one of:
dig +short example.com (fastest, shows A record only)dig example.com (shows full record with TTL)nslookup example.com (simpler syntax, more portable)host example.com (minimal output)output: IPv4 address (or blank if resolution fails)
note: if blank, DNS is broken. check step 2 before continuing.
input: access to /etc/resolv.conf and system DNS tools
run:
cat /etc/resolv.conf
resolvectl status # Linux only; shows systemd-resolved status
output: list of nameservers (usually 1.1.1.1, 8.8.8.8, or ISP DNS)
decision: if no nameservers listed or all listed servers are unreachable, DNS is misconfigured. try dig @8.8.8.8 example.com to test with public DNS.
input: hostname, list of DNS servers to query
run:
dig @8.8.8.8 example.com
dig @1.1.1.1 example.com
dig @9.9.9.9 example.com
or loop:
for dns in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
echo -n "$dns: "
dig +short @"$dns" example.com
done
output: IP address from each resolver (may differ if propagation is incomplete)
decision: if results differ between resolvers, DNS is still propagating. check TTL and wait.
input: hostname
run:
dig example.com | grep -E '^\S+\s+\d+\s+IN\s+A'
output: line like example.com. 300 IN A 93.184.216.34 (300 = TTL in seconds)
note: if TTL is low (< 300 seconds), changes propagate faster. if TTL is high (3600+), old DNS data will cache longer.
input: access to /etc/hosts
run:
cat /etc/hosts | grep -E "example\.com|api\.example\.com"
output: lines like 127.0.0.1 example.com (if override exists) or blank (if none)
decision: if /etc/hosts entry exists, it overrides DNS globally on that system. edit /etc/hosts to test migrations locally before changing DNS.
input: hostname, port number
do one of:
nc -zv -w 5 example.com 443 (netcat, most reliable, 5 second timeout)timeout 3 bash -c 'echo > /dev/tcp/example.com/443' && echo "Open" || echo "Closed" (bash built-in, no extra tools)curl -sI -o /dev/null -w "%{http_code}\n" https://example.com (HTTP only, also tests cert)output: "succeeded" (netcat) or "Open" (bash) or HTTP status code (curl)
note: if port is closed, check firewall rules next (step 9).
input: hostname, list of ports to test
run:
for port in 22 80 443 5432 6379; do
nc -zv -w 2 example.com $port 2>&1
done
output: "succeeded" or "failed" for each port
decision: if some ports open and others closed, firewall is likely filtering. check step 9.
input: hostname
do one of:
traceroute example.com (shows each hop, slow)mtr -r -c 20 example.com (continuous, shows packet loss percentage per hop, better)output: list of hops with IP, latency, and packet loss %
note: if one hop shows high loss, network is congested or routing is suboptimal at that point.
input: port number, system access (may need sudo)
on Linux (netstat or ss):
ss -tlnp | grep :8080 # Check if port is listening
ss -tlnp # Show all listening ports
netstat -tlnp | grep :8080 # Older Linux
on macOS:
lsof -i :8080 # Show process listening on port 8080
lsof -i -P -n | grep LISTEN # Show all listening
output: process name and PID listening on that port (or blank if nothing listening)
decision: if port is not in the output, the service isn't listening. start the service. if port is listening but curl/nc can't connect, firewall is blocking.
input: system access (usually requires sudo)
on Linux (iptables):
sudo iptables -L -n -v
on Linux (ufw, simpler):
sudo ufw status verbose
on macOS:
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
output: list of allowed/denied rules
decision: if no ACCEPT rule for your port and source IP, add one or disable firewall for testing.
input: port, protocol, optional source IP, system (Linux or macOS)
on Linux (ufw, simplest):
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.0/24 to any port 22
on Linux (iptables, lower level):
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables-save > /etc/iptables/rules.v4
output: rule added (ufw prints confirmation, iptables is silent)
note: iptables changes don't persist by default. save with iptables-save to survive reboot.
input: URL, optional custom headers or proxy
run full verbose output:
curl -v https://api.example.com/endpoint
run timing breakdown:
curl -o /dev/null -s -w "
DNS: %{time_namelookup}s
Connect: %{time_connect}s
TLS: %{time_appconnect}s
TTFB: %{time_starttransfer}s
Total: %{time_total}s
Status: %{http_code}
Size: %{size_download} bytes
" https://api.example.com/endpoint
output: curl verbose log or timing breakdown
decision: if TLS time is high, cert verification is slow. if TTFB is high, backend is slow. if DNS is high, resolver is slow.
input: URL, desired HTTP version (1.1, 2, 3) or TLS version (1.2, 1.3)
run:
curl --http2 https://example.com
curl --tlsv1.3 https://example.com
output: HTTP status and response
decision: if request fails with one version but works with another, server may not support the protocol version your client is using.
input: proxy URL (http://proxy:8080 or socks5://localhost:1080), target URL
run:
curl -x http://proxy.example.com:8080 https://httpbin.org/ip
curl --socks5 localhost:1080 https://httpbin.org/ip
output: HTTP response or proxy error
decision: if proxy test fails but direct test works, proxy is misconfigured or not running. if both fail, check firewall rules.
input: proxy URL, optional auth credentials
run:
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
export NO_PROXY=localhost,127.0.0.1,.internal.example.com
with auth:
export HTTPS_PROXY=http://user:password@proxy.example.com:8080
output: env vars set (verify with echo $HTTP_PROXY)
note: curl and most standard tools read these vars. node.js fetch, git, npm, pip do not. configure each tool separately.
input: hostname, port (usually 443)
run:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | \
openssl x509 -noout -subject -issuer -dates
output: subject (CN), issuer, notBefore, notAfter
decision: if notAfter is in the past, cert has expired. if issuer is self-signed and not in your CA bundle, cert verification will fail.
input: hostname, port
run:
echo | openssl s_client -connect example.com:443 2>/dev/null | \
openssl x509 -noout -enddate
output: line like notAfter=Dec 25 10:30:00 2025 GMT
decision: if date is within 30 days, renew certificate soon. if date is in past, cert is expired and will be rejected.
input: hostname, port
run:
openssl s_client -showcerts -connect example.com:443 < /dev/null 2>/dev/null | \
awk '/BEGIN CERT/,/END CERT/' > chain.pem
output: file chain.pem containing full cert chain (intermediate + root)
note: use this chain for verification or debugging certificate path issues.
input: server certificate file (server.pem), CA bundle (usually /etc/ssl/certs/ca-certificates.crt)
run:
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt server.pem
output: server.pem: OK or error message (e.g., "self signed certificate")
decision: if fails, cert is not trusted by system CA bundle. either add cert to bundle or ignore verification (insecure, for testing only).
input: hostname, port
run:
openssl s_client -connect example.com:443 -servername example.com
output: full TLS handshake output
note: -servername is required for SNI (Server Name Indication). without it, some servers (multi-tenant, CDN) will return wrong certificate.
input: hostname, optional port (defaults to 443)
run the quick diagnostics script:
#!/bin/bash
TARGET="${1:?Usage: net-check.sh <hostname> [port]}"
PORT="${2:-443}"
echo "=== Network Check: $TARGET:$PORT ==="
echo -n "DNS resolution: "
IP=$(dig +short "$TARGET" | head -1)
[[ -n "$IP" ]] && echo "$IP" || echo "FAILED"
echo -n "Ping: "
ping -c 1 -W 3 "$TARGET" > /dev/null 2>&1 && echo "OK" || echo "FAILED (may be blocked)"
echo -n "Port $PORT: "
nc -zv -w 5 "$TARGET" "$PORT" 2>&1 | grep -q "succeeded\|open" && echo "OPEN" || echo "CLOSED/FILTERED"
if [[ "$PORT" == "443" || "$PORT" == "8443" ]]; then
echo -n "TLS: "
echo | openssl s_client -connect "$TARGET:$PORT" -servername "$TARGET" 2>/dev/null | \
grep -q "Verify return code: 0" && echo "VALID" || echo "INVALID/ERROR"
echo -n "Certificate expiry: "
echo | openssl s_client -connect "$TARGET:$PORT" 2>/dev/null | \
openssl x509 -noout -enddate 2>/dev/null | sed 's/notAfter=//'
fi
echo "=== Done ==="
output: single report showing DNS, ping, port, TLS, and cert expiry
execution: ./net-check.sh example.com 443
if DNS resolves locally but fails via public DNS:
/etc/hosts or systemd-resolved.systemd-resolve --flush-caches (Linux) or dscacheutil -flushcache (macOS).dig to see how long cached data will persist./etc/hosts to override DNS locally instead of waiting for propagation.if DNS doesn't resolve at all:
/etc/resolv.conf to verify nameservers are configured.dig @8.8.8.8 example.com.nameserver 8.8.8.8 in /etc/resolv.conf or use systemd-resolved config.if port is unreachable (connection refused or timeout):
nc -zv -w 5 example.com 443.ufw status or iptables -L.if curl hangs indefinitely:
curl --max-time 10 https://example.com.ss -tlnp | grep :443.**