Network Troubleshooting Commands
When something on a server “doesn’t work”, the cause is almost always one of three things: a name can’t be looked up (DNS), the two machines can’t reach each other (connectivity), or the program you want to talk to isn’t listening (the service). On-call engineers earn their keep by figuring out which of these it is, fast. This page walks through the core Linux command-line tools — ping, traceroute/mtr, dig/nslookup, ss/netstat, and ip — and gives you a repeatable flow to follow under pressure. Everything here runs on a fresh Ubuntu 22.04 or 24.04 LTS server.
Install the tools first
Ubuntu ships with ping, ip, and ss out of the box. The DNS and tracing tools usually need to be installed.
sudo apt update
sudo apt install -y dnsutils traceroute mtr-tiny net-tools
A quick note on these package names. dnsutils gives you dig and nslookup. traceroute gives you the command of the same name. mtr-tiny gives you mtr (My Traceroute), a live combination of ping and traceroute. net-tools gives you the old netstat and ifconfig commands — they are deprecated (replaced by ss and ip) but you still meet them on older systems, so it helps to recognise them.
The troubleshooting flow
Before reaching for any tool, decide what you’re testing. This order takes you from “the network as a whole” down to “this one service”.
| Question | Tool | What a failure tells you |
|---|---|---|
| Can I resolve the name to an IP? | dig, nslookup | DNS problem |
| Can I reach the host at all? | ping, mtr | Connectivity / routing problem |
| Where does the path break? | traceroute, mtr | A specific hop or firewall |
| Is the service listening? | ss | The app is down or bound wrong |
| Is my own network config sane? | ip | Bad interface / IP / route |
Work top to bottom and stop at the first failure — that’s your culprit.
Step 1: Is it DNS? (dig and nslookup)
DNS (Domain Name System) is the phone book of the internet: it turns a name like example.com into an IP address. If DNS is broken, nothing else will work, so check it first.
dig (Domain Information Groper) is the precise tool. Use the +short flag for a clean answer.
dig +short example.com
Output:
93.184.216.34
If you get an IP back, DNS is fine. If you get nothing, ask the full version which shows the status:
dig example.com
Output:
; <<>> DiG 9.18.30 <<>> example.com
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4821
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 3600 IN A 93.184.216.34
;; Query time: 12 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
status: NOERROR with an ANSWER SECTION means success. status: NXDOMAIN means the name does not exist. No SERVER line or a timeout means your resolver itself is unreachable — check /etc/resolv.conf and the systemd-resolved service. nslookup example.com does the same job in a friendlier format if you prefer it.
When to use which: use
digfor scripting and for the exact record type (e.g.dig MX example.comfor mail). Usenslookuponly for a quick interactive check. Never trust the browser’s “site not found” page to tell you it’s DNS — confirm it withdig.
Step 2: Can I reach the host? (ping)
ping sends a small ICMP (Internet Control Message Protocol) “are you there?” packet and times the reply. It tests raw reachability, not whether your app works.
ping -c 4 example.com
Output:
PING example.com (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34: icmp_seq=1 ttl=56 time=14.2 ms
64 bytes from 93.184.216.34: icmp_seq=2 ttl=56 time=13.8 ms
64 bytes from 93.184.216.34: icmp_seq=3 ttl=56 time=14.0 ms
64 bytes from 93.184.216.34: icmp_seq=4 ttl=56 time=13.9 ms
--- example.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 13.8/14.0/14.2/0.15 ms
0% packet loss means the host is up and reachable. 100% packet loss means it’s down, blocked, or unreachable. The -c 4 flag sends exactly 4 packets and stops (otherwise ping runs forever; press Ctrl+C to quit).
Gotcha: many production hosts and cloud firewalls (including AWS security groups) silently drop ICMP. A failed ping does NOT always mean the host is down — it may just not answer pings. Confirm the actual service with
ssor a port check before declaring an outage.
Step 3: Where does the path break? (traceroute and mtr)
If ping fails or is slow, traceroute shows every router (hop) between you and the target, so you can see exactly where packets get stuck.
traceroute example.com
Output:
traceroute to example.com (93.184.216.34), 30 hops max, 60 byte packets
1 _gateway (10.0.0.1) 0.512 ms 0.498 ms 0.530 ms
2 100.64.0.1 (100.64.0.1) 8.221 ms 8.110 ms 8.305 ms
3 72.14.215.85 13.402 ms 13.388 ms 13.511 ms
4 93.184.216.34 14.022 ms 13.998 ms 14.110 ms
Lines showing * * * mean that hop didn’t reply — a few of these in the middle are normal, but * * * all the way to the end points to where the path is broken or filtered.
mtr combines ping and traceroute into one live, updating screen. It’s the better tool for catching intermittent loss because it keeps sending packets.
mtr --report --report-cycles 10 example.com
Output:
Start: 2026-06-15T09:14:22+0000
HOST: web-01 Loss% Snt Last Avg Best Wrst
1.|-- _gateway 0.0% 10 0.5 0.5 0.4 0.7
2.|-- 100.64.0.1 0.0% 10 8.2 8.3 8.1 8.9
3.|-- 72.14.215.85 0.0% 10 13.4 13.5 13.2 14.0
4.|-- example.com 0.0% 10 14.0 14.1 13.8 14.4
A hop with high Loss% that continues to the destination is your problem hop.
Step 4: Is the service listening? (ss)
You’ve confirmed DNS resolves and the host is reachable, but the app still won’t connect. Now check whether the program is actually listening on its port. ss (Socket Statistics) is the modern replacement for netstat.
sudo ss -tlnp
The flags mean: -t TCP, -l listening sockets only, -n numeric (don’t resolve names, faster), -p show the process.
Output:
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=812,fd=6))
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=812,fd=7))
LISTEN 0 128 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=640,fd=5))
Read the Local Address:Port column carefully. 0.0.0.0:80 means the service listens on all interfaces — reachable from outside. 127.0.0.1:5432 means it only listens on localhost — a remote client will be refused. A very common bug is an app bound to 127.0.0.1 when it should be on 0.0.0.0. If your port isn’t in the list at all, the service isn’t running — check it with sudo systemctl status nginx.
The old equivalent is sudo netstat -tlnp, which prints almost identical output.
ss command | Shows |
|---|---|
ss -tlnp | TCP listening sockets + process |
ss -ulnp | UDP listening sockets + process |
ss -tnp state established | Live established TCP connections |
ss -s | Summary counts of all sockets |
Step 5: Is my own config sane? (ip)
If even local things look wrong, check your own machine’s network setup with ip, the modern replacement for ifconfig.
ip addr show
Output:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.15/24 brd 10.0.0.255 scope global eth0
state UP and an inet line with an IP mean the interface is configured. To check the routing table — which decides where packets go — use:
ip route show
Output:
default via 10.0.0.1 dev eth0 proto dhcp
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.15
The default via 10.0.0.1 line is your default gateway (the router that sends traffic to the wider internet). No default route means you can reach your local subnet but nothing beyond it.
Best Practices
- Always go in order: DNS, then reachability, then the service. Stop at the first failure instead of guessing.
- Use
dig +shortin scripts and the fulldigoutput when you need thestatus:line to interpret a failure. - Don’t conclude “host down” from a failed
pingalone — ICMP is often blocked. Verify the real port withssorcurl. - Prefer the modern tools (
ss,ip) over the deprecated ones (netstat,ifconfig); learn to read both since old servers still use them. - Run
ss -tlnpandip addron the server itself before blaming the network — most “network” outages are a stopped service or a wrong bind address. - Save your
mtr --reportoutput to a file when escalating to a network team; intermittent loss is hard to argue without evidence.