Linux Network Troubleshooting from the Command Line

Network problems are frustrating because the symptom is often vague: “the server cannot connect.”

A better approach is to move through the network one layer at a time.

First check the local interface, then routing, then DNS, then the remote service.

Check the interfaces

Start with ip.

ip addr

Look for an interface that is UP and has the expected address.

A shorter view is often easier to scan.

ip -br addr

Do not assume the interface is called eth0. Modern systems may use names such as ens18, enp1s0, or something provider-specific.

Check the route

The routing table tells Linux where packets should go.

ip route

There is usually a default route similar to:

default via 192.0.2.1 dev eth0

Ask Linux which route it would choose for a specific destination.

ip route get 1.1.1.1

This is extremely useful on hosts with multiple interfaces or policy routing.

Test the local gateway

If the gateway is reachable, the local network stack is probably working.

ping -c 4 192.0.2.1

A failed ping does not automatically prove the network is broken because some networks block ICMP.

Treat ping as evidence, not as the final verdict.

Test an IP without DNS

Try a public IP directly.

ping -c 4 1.1.1.1

If IP connectivity works but a hostname does not, DNS becomes a strong suspect.

If both fail, continue with routes, firewall rules, interface state, and the provider network.

Check DNS

Use dig when available.

dig example.com

For a specific resolver:

dig @1.1.1.1 example.com

This separates “my configured resolver is broken” from “the domain has no useful answer.”

You can also inspect the resolver configuration.

resolvectl status

On systems using another resolver stack, /etc/resolv.conf may still provide useful clues.

Test the actual application

Ping tells you very little about HTTP.

Use curl for an HTTP or HTTPS service.

curl -I https://example.com

For timing information:

curl -o /dev/null -s -w 'connect=%{time_connect} total=%{time_total}
' https://example.com

Now you can distinguish a quick connection from a slow application response.

Check listening sockets

If your service should listen on port 8080, verify that something actually does.

ss -lntp

Filter it when needed.

ss -lntp | grep ':8080'

A service listening on 127.0.0.1:8080 is reachable locally but not directly through the server's external address.

Understand bind addresses

This difference matters:

127.0.0.1:8080

versus:

0.0.0.0:8080

The first accepts connections only through the local loopback interface. The second can accept connections arriving through the host's interfaces, subject to firewall rules.

Do not expose a service externally unless it is intended to be reachable.

Check the firewall

The firewall tooling depends on the distribution and setup.

On a system using UFW:

sudo ufw status verbose

On systems using nftables directly:

sudo nft list ruleset

Do not assume that an empty UFW output means no firewall exists. Another firewall manager may be active.

Trace the path when necessary

traceroute can help show where traffic stops.

traceroute example.com

Some systems use tracepath instead.

tracepath example.com

Intermediate hops may intentionally hide themselves, so a * does not automatically mean the path is broken.

Check connection failures with logs

If a systemd service cannot reach another service, inspect its journal.

journalctl -u myapp -b

Look for DNS errors, connection refusals, timeouts, TLS errors, and authentication failures.

These messages often tell you which layer is actually failing.

A useful decision tree

If the interface is down, fix the interface first.

If the interface is fine but there is no route, fix routing.

If an IP works but a hostname fails, investigate DNS.

If DNS works but TCP connection fails, check the destination, firewall, port, and listener.

If TCP connects but HTTP fails, inspect TLS, application logs, and the HTTP response.

This method is slower than guessing for the first five minutes, but much faster over the whole incident.