Skip to content
elephantoo

Networking commands

Lesson 27 of 31 18 min read

IP addresses and ports, ip, ping, ss, curl, dig, traceroute and a troubleshooting checklist.


Almost everything a server does involves the network: serving web pages, talking to a database, pulling packages, receiving SSH connections. When something "can't connect", you need to work out where the chain breaks. This lesson covers the core concepts (IP addresses, ports, DNS, routes) and the modern Linux tools to inspect and troubleshoot each layer: ip, ping, ss, dig, curl and traceroute.

The 60-second networking primer#

  • IP address: a machine's address on a network. IPv4 looks like 192.168.1.20, IPv6 like 2001:db8::20.
  • Private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) are used inside LANs and clouds and aren't reachable from the internet directly. 127.0.0.1 (localhost) is the machine itself.
  • CIDR notation: /24 means the first 24 bits are the network, so 192.168.1.0/24 covers 192.168.1.0–192.168.1.255.
  • Gateway / default route: where packets for other networks go (usually your router).
  • Port: a number (0–65535) identifying a service on a machine. 22 is SSH, 80 HTTP, 443 HTTPS, 3306 MySQL, 5432 PostgreSQL. Ports below 1024 need root to bind.
  • TCP is reliable and connection-based (web, SSH, databases); UDP is connectionless and fast (DNS, video, games).
  • DNS turns names (example.com) into IP addresses.

To connect to https://example.com, your machine needs to: resolve the name (DNS) → route packets to that IP (gateway) → reach port 443 (firewall) → find a service listening there.

Your addresses and interfaces: ip#

ip (package iproute2) replaces the old ifconfig and route commands:

Terminal
ip -br addr        # brief: one line per interface
Output
lo               UNKNOWN        127.0.0.1/8 ::1/128
enp0s3           UP             192.168.1.20/24 fe80::a00:27ff:fe4e:66a1/64
docker0          DOWN           172.17.0.1/16
  • lo is the loopback interface.
  • enp0s3, eth0 or ens5 is the wired/virtual NIC, and wlp2s0 is Wi-Fi. Modern names encode the hardware location.
  • docker0 is a bridge created by Docker.
Terminal
ip addr show enp0s3   # full details for one interface (MAC address, flags, MTU)
ip route              # the routing table
ip -br link           # interfaces and their state, without addresses
Output
default via 192.168.1.1 dev enp0s3 proto dhcp src 192.168.1.20 metric 100
192.168.1.0/24 dev enp0s3 proto kernel scope link src 192.168.1.20
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown

The default via 192.168.1.1 line is your gateway. ip route get 8.8.8.8 shows which route and source address a specific destination would use.

Changes made with ip (such as sudo ip addr add 10.0.0.5/24 dev eth0) are temporary and vanish at reboot. Permanent configuration lives in Netplan YAML on Ubuntu (/etc/netplan/*.yaml, applied with sudo netplan apply), or in NetworkManager on desktops and Fedora/RHEL (nmcli, nmtui).

Your public IP (as the internet sees it, after NAT) is different: curl -s https://ifconfig.me.

Is it reachable? ping#

Terminal
ping -c 3 example.com
Output
PING example.com (93.184.215.14) 56(84) bytes of data.
64 bytes from 93.184.215.14: icmp_seq=1 ttl=55 time=11.9 ms
64 bytes from 93.184.215.14: icmp_seq=2 ttl=55 time=11.6 ms
64 bytes from 93.184.215.14: icmp_seq=3 ttl=55 time=11.5 ms

--- example.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 11.587/11.714/11.913/0.142 ms

-c 3 stops after 3 packets (without it, ping runs until Ctrl+C). Look at the packet loss and the time (latency). Many cloud servers and firewalls block ICMP, so a failed ping doesn't always mean the host is down. Test the actual port instead (see below).

Where does it break? traceroute and mtr#

Terminal
traceroute example.com      # sudo apt install traceroute
tracepath example.com       # often preinstalled (iputils-tracepath), no root needed
mtr -rw -c 10 example.com   # ping + traceroute combined, with per-hop loss (package mtr-tiny)

Each line is a hop (router) on the way. * * * means that hop doesn't answer probes, which is common and only a concern if every hop after it is also silent.

DNS: names to addresses#

Terminal
dig +short example.com
dig example.com A
Output
93.184.215.14
;; ANSWER SECTION:
example.com.		300	IN	A	93.184.215.14

;; Query time: 12 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)

(dig prints more sections; the important parts are shown.) dig comes from dnsutils on Debian/Ubuntu and bind-utils on Fedora. Useful queries:

Terminal
dig example.com MX +short          # mail servers
dig example.com TXT +short         # SPF, verification records
dig @1.1.1.1 example.com +short    # ask a specific DNS server (bypass your resolver)
dig -x 8.8.8.8 +short              # reverse lookup: IP -> name
getent hosts example.com           # resolve the way applications do (includes /etc/hosts)
resolvectl status                  # which DNS servers systemd-resolved is using
  • /etc/hosts holds static name → IP mappings, checked before DNS. It's handy for testing (203.0.113.10 staging.example.com).
  • On Ubuntu, /etc/resolv.conf points to 127.0.0.53, the local systemd-resolved stub, which forwards to the real DNS servers. resolvectl status shows those servers.
  • If dig @1.1.1.1 name works but dig name doesn't, your configured resolver is the problem.

Which ports are open? ss#

ss (socket statistics) replaces the old netstat:

Terminal
sudo ss -tlnp
Output
State   Recv-Q  Send-Q   Local Address:Port    Peer Address:Port  Process
LISTEN  0       4096         127.0.0.1:3306         0.0.0.0:*      users:(("mysqld",pid=812,fd=23))
LISTEN  0       511            0.0.0.0:80           0.0.0.0:*      users:(("nginx",pid=901,fd=6))
LISTEN  0       4096     127.0.0.53%lo:53           0.0.0.0:*      users:(("systemd-resolve",pid=530,fd=14))
LISTEN  0       128            0.0.0.0:22           0.0.0.0:*      users:(("sshd",pid=744,fd=3))
LISTEN  0       511               [::]:80              [::]:*      users:(("nginx",pid=901,fd=7))

Flags: -t TCP, -u UDP, -l listening only, -n numeric (no name lookups), -p show the process. The local address matters a lot:

  • 0.0.0.0:80 or [::]:80: listening on all interfaces, so it's reachable from other machines (if the firewall allows).
  • 127.0.0.1:3306: localhost only. MySQL here can't be reached remotely, which is a safe default.

Other handy forms: ss -tn (established TCP connections), ss -s (summary counts), ss -tnp state established '( dport = :443 )'. sudo lsof -i :8080 also answers "who is using port 8080?".

Talking HTTP: curl#

curl is the Swiss-army knife for testing web services and APIs:

Terminal
curl https://example.com                     # print the body
curl -I https://example.com                  # headers only (HEAD request)
curl -sS -o /dev/null -w "%{http_code} %{time_total}s\n" https://example.com
curl -L http://example.com                   # follow redirects
curl -v https://api.example.com/health       # verbose: DNS, TLS handshake, request and response headers
curl -X POST -H "Content-Type: application/json" \
     -d '{"name":"ada"}' https://httpbin.org/post
curl -fsSL https://example.com/install.sh -o install.sh   # download (read before running!)
curl --resolve example.com:443:203.0.113.10 https://example.com   # test a specific server IP
Output
200 0.035s

(That's the output of the -w line: the status code and total time.) -f makes curl exit non-zero on HTTP errors (4xx/5xx), which is essential in scripts. -s is silent and -S still shows errors. wget is the simpler download-only alternative: wget https://example.com/file.tar.gz.

Testing a TCP port#

Is something listening, and does the firewall let you through?

Terminal
nc -zv db.internal 5432          # netcat: "succeeded" / "refused" / timeout
timeout 3 bash -c '</dev/tcp/db.internal/5432' && echo open || echo closed   # pure bash, no tools needed
curl -v telnet://db.internal:5432   # curl can test raw TCP too

How to read the result:

ResultUsually means
connected / succeedednetwork, firewall and service are all fine; look at the application layer
Connection refusedhost reachable, but nothing listening on that port/interface (check ss -tlnp on the server)
timeout (hangs)packets dropped: a firewall or security group, a wrong IP, or the host is down
No route to hostrouting problem, or a firewall rejecting with ICMP
Could not resolve hostDNS problem

A troubleshooting checklist#

When "the app can't reach the server", work up the layers:

  1. Local interface: ip -br addr. Do I have an IP? Is the link up?
  2. Gateway: ip route and ping -c 2 <gateway>.
  3. Internet / remote network: ping -c 2 1.1.1.1 (an IP, so DNS isn't involved yet).
  4. DNS: dig +short name / getent hosts name. Does it resolve, and to the right IP?
  5. Port reachability: nc -zv host port. Refused or timeout?
  6. On the server: sudo ss -tlnp. Is the service listening, on the right interface (0.0.0.0 vs 127.0.0.1)?
  7. Firewalls: sudo ufw status / sudo firewall-cmd --list-all on the server, plus cloud security groups.
  8. Application: curl -v, then the service logs (journalctl -u service).

Working this list in order turns "the network is broken" into a precise diagnosis.

Downloading and copying files over the network#

curl -O URL and wget URL fetch files over HTTP(S). To copy between your own machines, use SSH-based tools, scp and rsync, which are covered in the next lesson.

Common mistakes#

  • Assuming a failed ping means the host is down. ICMP is often blocked; test the real port.
  • A service bound to 127.0.0.1 and then wondering why other machines can't connect. Check ss -tlnp.
  • Forgetting the cloud firewall (AWS security groups, GCP firewall rules) in addition to the host firewall.
  • Editing /etc/resolv.conf by hand on Ubuntu. It's managed by systemd-resolved/Netplan, and your changes get overwritten.
  • Temporary ip addr add changes that disappear at reboot. Use Netplan or NetworkManager for permanent config.
  • Piping curl | bash from unknown sources. Download the script, read it, then run it.

What's next#

The most important network service for an admin is SSH. Next you'll log in to remote machines securely with keys, configure ~/.ssh/config, create tunnels, and copy files with scp and rsync.

Check your understanding

Quick quiz

0/3 answered
  1. 1.Which command shows which processes are listening on TCP ports?

  2. 2.curl http://10.0.0.5:8080 works, but curl http://api.internal:8080 fails with 'Could not resolve host'. Where is the problem?

  3. 3.What does 'Connection refused' (as opposed to a timeout) usually tell you?

Finished reading?

Mark this lesson complete to track your progress.