News
🌐 Networking Tutorials Debug Network Connections with ss, netstat, and curl

Debug Network Connections with ss, netstat, and curl

Diagnose connection failures, see what is listening, trace where a request breaks down, and find the tool for each layer of the problem.

Network problems have a layered structure. A request that does not get through could be failing at DNS, at the TCP connection, at TLS, or at the application layer. Each layer has its own tools. Knowing which tool to reach for first cuts debugging time significantly.


Is the service listening?

Before anything else — confirm the service is actually running and accepting connections.

ss -tulnp | grep :8080

If nothing appears, the service is not listening. Check whether it started:

sudo systemctl status myservice
sudo journalctl -u myservice -n 50

If ss shows the service listening on 127.0.0.1:8080 but you are trying to connect from a different machine, that is the problem — it is only listening on loopback. Either configure the service to bind to 0.0.0.0 (all interfaces) or to the specific interface address, and ensure the firewall allows the port.


Can you reach the port at all?

Test basic TCP connectivity:

nc -zv 192.168.1.10 8080

-z tests the connection without sending data. -v makes it verbose.

Connection to 192.168.1.10 8080 port [tcp/*] succeeded!

If the connection is refused (Connection refused), the service is not listening or the port is blocked. If it hangs with no output, a firewall is dropping the packets silently.

Check from the server's own loopback to isolate firewall issues:

nc -zv 127.0.0.1 8080     # from the server itself

If this succeeds but a remote connection does not, the firewall is blocking external access. Check ufw status or firewall-cmd --list-all.


Is DNS resolving correctly?

dig example.com A

Check the ANSWER SECTION. If it is empty, the domain has no A record or DNS resolution is failing.

Compare against a public resolver to rule out local cache issues:

dig @8.8.8.8 example.com A

If the public resolver gives a different answer than your local one, your local cache has a stale record. Wait for the TTL to expire, or flush the local cache:

sudo systemd-resolve --flush-caches    # systemd-resolved
sudo resolvectl flush-caches           # same, newer interface

Trace a full HTTP request with curl

curl is the most versatile debugging tool for HTTP connections:

curl -v https://example.com

The verbose output shows:

  • DNS resolution (Trying 203.0.113.10...)
  • TCP connection (Connected to example.com)
  • TLS handshake (SSL connection using TLS1.3)
  • Request headers sent
  • Response headers received
  • Response body

Work top to bottom — if DNS fails, you see it immediately. If TLS fails, you see the certificate error. If the server returns a 4xx or 5xx, you see the status code.

Test with specific headers:

curl -v -H "Authorization: Bearer token123" https://api.example.com/v1/users

Test a specific IP without changing DNS:

curl --resolve example.com:443:203.0.113.10 https://example.com

Useful for testing a new server before DNS propagation, or for verifying which backend is responding behind a load balancer.

Follow redirects and show timing:

curl -L -w "\n\nDNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://example.com

The -w flag appends timing data after the response. time_starttransfer is time to first byte — the single most useful number for diagnosing slow responses.


Active connections to a service

See who is currently connected to a port:

ss -tnp | grep :443

The output shows established connections with source and destination IPs, which lets you confirm that traffic is actually arriving and from where.


Packet-level debugging

When application-layer tools are not enough, tcpdump captures the actual packets:

sudo tcpdump -i any port 8080 -n

-i any captures on all interfaces. -n suppresses hostname resolution. The output shows every packet to or from port 8080, with source, destination, and TCP flags. Useful for confirming whether packets are arriving at the server at all, and whether the server is sending any response.

To capture to a file and analyse in Wireshark:

sudo tcpdump -i eth0 port 8080 -w /tmp/capture.pcap

The debugging path

When a connection is not working, work down this checklist:

  1. Is the service running? (systemctl status)
  2. Is it listening on the expected port and interface? (ss -tulnp)
  3. Can you connect locally? (nc -zv 127.0.0.1 PORT)
  4. Does the firewall allow the port? (ufw status)
  5. Does DNS resolve correctly? (dig)
  6. Can you connect from the client machine? (nc -zv HOST PORT)
  7. Does an HTTP request succeed? (curl -v)

Most problems become obvious by step 4 or 5.