Linux Networking Commands Every Engineer Should Know
Your app can't connect to the database. Latency is spiking. DNS resolution is failing. A microservice can't reach its dependency. Networking issues are behind the majority of production incidents, and if you can't debug them from the command line, you're flying blind. Let's fix that.
ip — The Modern Network Swiss Knife
The ip command replaced the old ifconfig. If you're still using ifconfig, it's time to switch.
# Show all network interfaces and their IP addresses
ip addr show
# or the short form
ip a
# Show only IPv4 addresses
ip -4 addr show
# Show a specific interface
ip addr show eth0
# Show routing table — where does traffic go?
ip route show
# 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.5
# 172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
# Which route will traffic to a specific IP take?
ip route get 8.8.8.8
# 8.8.8.8 via 10.0.0.1 dev eth0 src 10.0.0.5
# Show link state (up/down)
ip link show
# Show ARP/neighbor table
ip neigh show
For temporary network changes (testing only — won't survive a reboot):
# Add an IP address to an interface
sudo ip addr add 10.0.0.100/24 dev eth0
# Bring an interface up/down
sudo ip link set eth0 up
sudo ip link set eth0 down
# Add a static route
sudo ip route add 192.168.1.0/24 via 10.0.0.1 dev eth0
# Delete a route
sudo ip route del 192.168.1.0/24
ss — Socket Statistics (Replaces netstat)
ss is faster than netstat and gives you more detail. Use it to see what's listening and what's connected.
# Show all listening TCP ports
ss -tlnp
# 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=1234))
# LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=567))
# LISTEN 0 128 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=890))
# Flags explained:
# -t = TCP, -u = UDP, -l = listening, -n = numeric (no DNS), -p = show process
# Show all established connections
ss -tnp
# Show connections to a specific port
ss -tnp | grep :443
# Count connections by state
ss -s
# TCP: 245 (estab 180, closed 15, orphaned 0, timewait 50)
# Find which process is using port 8080
ss -tlnp | grep :8080
# Show connections to a specific remote IP
ss -tnp dst 10.0.1.50
The old netstat still works but is deprecated:
# Equivalent netstat commands (if ss isn't available)
netstat -tlnp # Listening TCP ports
netstat -anp # All connections
curl — Test HTTP Endpoints
curl is your best friend for debugging API and web connectivity.
# Simple GET request
curl https://api.example.com/health
# Show response headers
curl -I https://api.example.com/health
# Show everything — request headers, response headers, body
curl -v https://api.example.com/health
# POST with JSON data
curl -X POST https://api.example.com/data \
-H "Content-Type: application/json" \
-d '{"key": "value"}'
# Follow redirects
curl -L http://example.com
# Set a timeout (critical for debugging hangs)
curl --connect-timeout 5 --max-time 10 https://api.example.com/health
# Test with specific DNS resolution (bypass DNS)
curl --resolve api.example.com:443:10.0.1.50 https://api.example.com/health
# Download a file
curl -O https://releases.hashicorp.com/terraform/1.7.0/terraform_1.7.0_linux_amd64.zip
# Show only HTTP status code
curl -o /dev/null -s -w "%{http_code}\n" https://api.example.com/health
# 200
# Measure response time breakdown
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nTotal: %{time_total}s\n" https://api.example.com/health
# DNS: 0.012s
# Connect: 0.045s
# TLS: 0.120s
# Total: 0.250s
That last command is incredibly useful for debugging latency. It tells you exactly where time is being spent — DNS, TCP connect, TLS handshake, or server processing.
DNS Troubleshooting — dig and nslookup
When things break, DNS is guilty until proven innocent.
# Basic DNS lookup
dig api.example.com
# ;; ANSWER SECTION:
# api.example.com. 300 IN A 10.0.1.50
# Short answer only
dig +short api.example.com
# 10.0.1.50
# Query a specific DNS server
dig @8.8.8.8 api.example.com
# Look up different record types
dig api.example.com A # IPv4 address
dig api.example.com AAAA # IPv6 address
dig api.example.com CNAME # Canonical name
dig api.example.com MX # Mail servers
dig api.example.com TXT # TXT records (SPF, DKIM, etc.)
dig api.example.com NS # Nameservers
# Trace the full DNS resolution path
dig +trace api.example.com
# Reverse DNS lookup
dig -x 10.0.1.50
# nslookup — simpler alternative
nslookup api.example.com
nslookup api.example.com 8.8.8.8 # Query specific DNS server
DNS Configuration Files
# What DNS server does this machine use?
cat /etc/resolv.conf
# nameserver 10.0.0.2
# nameserver 8.8.8.8
# search example.com
# Local hostname overrides
cat /etc/hosts
# 127.0.0.1 localhost
# 10.0.1.50 api.example.com # Manual override
# 10.0.1.51 db.example.com
# On systemd systems, check resolved
resolvectl status
Adding entries to /etc/hosts is a quick way to test DNS changes before they propagate, or to redirect traffic during maintenance.
ping and traceroute — Connectivity Testing
# Basic ping — test if a host is reachable
ping -c 4 10.0.1.50
# PING 10.0.1.50: 64 bytes, time=0.5ms, 0% packet loss
# Ping with specific packet size (test MTU issues)
ping -c 4 -s 1472 10.0.1.50
# Trace the network path to a host
traceroute api.example.com
# 1 gateway (10.0.0.1) 0.5 ms
# 2 isp-router (203.0.113.1) 5.2 ms
# 3 * * * # Firewall blocking ICMP
# 4 target (10.0.1.50) 12.1 ms
# Use TCP instead of ICMP (works when ICMP is blocked)
sudo traceroute -T -p 443 api.example.com
# mtr — combines ping and traceroute in real-time
mtr api.example.com
# Shows continuous stats for each hop: loss%, sent, last, avg, best, worst
Network Configuration Files
Understanding where network settings live is crucial for persistent configuration changes.
# Check if NetworkManager is managing your interfaces
systemctl status NetworkManager
nmcli device status
nmcli connection show
# Show active connection details
nmcli connection show "Wired connection 1"
# Set a static IP with NetworkManager
sudo nmcli connection modify "Wired connection 1" \
ipv4.method manual \
ipv4.addresses 10.0.0.100/24 \
ipv4.gateway 10.0.0.1 \
ipv4.dns "8.8.8.8,8.8.4.4"
sudo nmcli connection up "Wired connection 1"
# On Ubuntu with netplan
cat /etc/netplan/01-netcfg.yaml
sudo netplan apply
Real-World Scenario: App Can't Connect to Database
Here's the exact debugging workflow when your app reports "Connection refused" or "Connection timed out" to a database:
# Step 1: Can we resolve the hostname?
dig +short db.example.com
# 10.0.1.51 — good, DNS works
# Step 2: Can we reach the host at all?
ping -c 3 10.0.1.51
# If this fails — network/routing issue
# Step 3: Is the port open and listening?
ss -tlnp | grep :5432 # Check on DB server
nc -zv 10.0.1.51 5432 # Check from app server
# Connection to 10.0.1.51 5432 port [tcp/postgresql] succeeded!
# Step 4: If connection times out — check firewall
sudo iptables -L -n | grep 5432
sudo firewall-cmd --list-all # On RHEL/CentOS
# Step 5: Is the service bound to the right interface?
# On the DB server:
ss -tlnp | grep :5432
# LISTEN 127.0.0.1:5432 — PROBLEM! Only listening on localhost
# Should be 0.0.0.0:5432 or 10.0.1.51:5432
# Step 6: Check if the app can actually authenticate
curl -v telnet://10.0.1.51:5432
# Step 7: Check the route from app to database
traceroute -T -p 5432 10.0.1.51
Common culprits:
- DNS not resolving — check
/etc/resolv.confand/etc/hosts - Port not open — service isn't running or firewall is blocking
- Service listening on 127.0.0.1 — needs to bind to
0.0.0.0or the correct interface - Security group/firewall — cloud provider or
iptablesrules blocking traffic - Wrong subnet/route — app and database on different networks without routing
Quick Reference Table
| Task | Command |
|---|---|
| Show IP addresses | ip a |
| Show routing table | ip route |
| Show listening ports | ss -tlnp |
| Test HTTP endpoint | curl -v URL |
| DNS lookup | dig +short hostname |
| Test port connectivity | nc -zv host port |
| Trace network path | traceroute host |
| Show DNS config | cat /etc/resolv.conf |
| Network interface status | nmcli device status |
Next up: Automate Anything with Linux Cron Jobs — stop doing repetitive tasks manually. Automate everything.
