Skip to content

Linux Networking Reference

Linux Networking Reference

The commands that actually diagnose network problems: ip, ss, nmap, tcpdump, curl, dig, and iptables — with real-world one-liners for debugging in production.

ip — modern replacement for ifconfig and route
# Interface management (ip link)
ip link show                          # list all interfaces
ip link show eth0                     # specific interface
ip link set eth0 up                   # bring interface up
ip link set eth0 down
ip link set eth0 mtu 9000             # jumbo frames

# IP address management (ip addr / ip address)
ip addr show                          # all IPs on all interfaces
ip addr show eth0                     # specific interface
ip addr add 192.168.1.10/24 dev eth0  # add IP
ip addr del 192.168.1.10/24 dev eth0  # remove IP
ip addr flush dev eth0                # remove all IPs from interface

# Routing table (ip route)
ip route show                         # full routing table
ip route get 8.8.8.8                  # which route would be used? (debug!)
ip route add default via 192.168.1.1  # add default gateway
ip route add 10.0.0.0/8 via 10.1.1.1 dev eth1  # static route
ip route del 10.0.0.0/8              # remove route
ip route flush cache                  # flush route cache

# Neighbour table (ARP)
ip neigh show                         # ARP cache
ip neigh add 192.168.1.1 lladdr aa:bb:cc:dd:ee:ff dev eth0   # static ARP
ip neigh flush dev eth0              # flush ARP for interface

# Namespaces (for container debugging)
ip netns list
ip netns exec myns ip addr show      # run command in namespace
nsenter -t  -n ip addr show     # enter pod/container network namespace
ss — socket statistics (modern netstat)
# Basic usage
ss -tlnp    # TCP (-t), listening (-l), numeric (-n), with process (-p)
ss -ulnp    # UDP listening
ss -tlnp    # the one you run every time something won't start

# Flags
# -t  TCP sockets
# -u  UDP sockets
# -l  listening sockets only
# -a  all sockets (listening + established)
# -n  numeric ports (no DNS lookup — faster)
# -p  show process name and PID
# -e  extended info (timer, UID)
# -s  summary statistics
# -4  IPv4 only
# -6  IPv6 only

# Useful combinations
ss -tlnp                          # what's listening on TCP?
ss -s                             # summary: TCP states, UDP, RAW
ss state established              # only established connections
ss -tn state established          # established TCP, numeric
ss -tn dst 10.0.1.5               # connections TO specific host
ss -tn src :443                   # connections FROM port 443
ss -tn '( dport = :80 or dport = :443 )'  # filter by dest port

# Show socket for specific process
ss -tlnp | grep nginx
ss -tlnp | grep ':8080'
ss -tlnp | grep "pid=1234"

# Watch connections in real time
watch -n1 'ss -tn state established | wc -l'

# Count connections per state
ss -s

# Compare to netstat
# netstat -tlnp    →  ss -tlnp
# netstat -an      →  ss -an
# netstat -rn      →  ip route show
tcpdump — capture and inspect traffic
# Basic capture
tcpdump -i eth0                       # capture on interface
tcpdump -i any                        # all interfaces
tcpdump -i eth0 -n                    # no DNS resolution (faster)
tcpdump -i eth0 -v                    # verbose (TTL, TOS, length)
tcpdump -i eth0 -vv                   # very verbose
tcpdump -i eth0 -nn                   # no DNS + no port name resolution

# Filters (BPF — Berkeley Packet Filter syntax)
tcpdump host 192.168.1.10            # traffic to/from host
tcpdump src host 192.168.1.10        # only FROM host
tcpdump dst host 192.168.1.10        # only TO host
tcpdump port 443                      # by port
tcpdump tcp port 8080                 # TCP only on port
tcpdump not port 22                   # exclude SSH noise
tcpdump host 10.0.1.5 and port 5432  # combine with and/or/not
tcpdump 'tcp[tcpflags] & tcp-syn != 0'  # only SYN packets (new connections)

# Save to file (for Wireshark analysis)
tcpdump -i eth0 -w /tmp/capture.pcap
tcpdump -i eth0 -w /tmp/capture.pcap -C 100  # rotate at 100MB
tcpdump -r /tmp/capture.pcap          # read from file

# Capture HTTP requests (GET/POST visible in clear)
tcpdump -i eth0 -A -s0 port 80 | grep -E 'GET|POST|Host:'

# Count packets per host (quick traffic analysis)
tcpdump -i eth0 -nn -c 1000 | awk '{print $3}' | \
  cut -d. -f1-4 | sort | uniq -c | sort -rn | head -10

# Debug container networking
# 1. Find the veth pair: ip link show | grep veth
# 2. Capture on veth: tcpdump -i veth1234abcd
# Or enter namespace: nsenter -t  -n tcpdump -i eth0
nmap — port scanning and network discovery
# Host discovery
nmap -sn 192.168.1.0/24             # ping sweep (no port scan)
nmap -sn 192.168.1.0/24 --open      # only show responding hosts

# Port scanning
nmap 192.168.1.10                    # scan 1000 common ports
nmap -p 80,443,8080,8443 10.0.1.5   # specific ports
nmap -p 1-65535 10.0.1.5            # all ports (slow)
nmap -p- 10.0.1.5                   # all ports (same as above, shorter)
nmap -F 10.0.1.5                    # fast — top 100 ports

# Scan types
nmap -sT 10.0.1.5   # TCP connect scan (full handshake, no root needed)
nmap -sS 10.0.1.5   # SYN scan (stealth, root required, faster)
nmap -sU 10.0.1.5   # UDP scan (slow — UDP has no handshake)

# Service and version detection
nmap -sV 10.0.1.5   # detect service versions
nmap -sV --version-intensity 5 10.0.1.5   # more aggressive version detection
nmap -O 10.0.1.5    # OS detection (root required)
nmap -A 10.0.1.5    # -sV + -O + script scan + traceroute (aggressive, noisy)

# Timing templates
nmap -T0 10.0.1.5   # paranoid (IDS evasion)
nmap -T3 10.0.1.5   # normal (default)
nmap -T4 10.0.1.5   # aggressive (fast networks)
nmap -T5 10.0.1.5   # insane (may miss things)

# Output formats
nmap -oN scan.txt   # normal text
nmap -oX scan.xml   # XML (for tools)
nmap -oG scan.gnmap # grepable
nmap -oA scan       # all three formats with base name

# Quick internal network audit
nmap -sn 10.0.0.0/24 -oG - | grep "Up" | awk '{print $2}' | \
  xargs nmap -sV -p 22,80,443,3306,5432,6379,8080,9200 --open

Don’t scan networks you don’t own. Even internal scanning can trigger IDS alerts or cause problems on sensitive production systems.

dig — DNS diagnostics
# Basic queries
dig example.com                   # A record (default)
dig example.com A                 # explicit A record
dig example.com AAAA              # IPv6
dig example.com MX                # mail exchangers
dig example.com NS                # nameservers
dig example.com TXT               # TXT records (SPF, DKIM, etc.)
dig example.com CNAME             # canonical name
dig example.com SOA               # start of authority

# Use specific DNS server
dig @8.8.8.8 example.com          # query Google DNS
dig @1.1.1.1 example.com          # query Cloudflare
dig @10.96.0.10 my-service.prod.svc.cluster.local  # K8s CoreDNS

# Reverse lookup (PTR)
dig -x 93.184.216.34              # IP → hostname
dig PTR 34.216.184.93.in-addr.arpa.

# Short output (just the answer)
dig example.com +short
dig example.com A +short          # just the IP(s)

# Full trace — see entire delegation chain
dig example.com +trace

# Check DNSSEC
dig example.com +dnssec

# Disable recursion (query authoritative only)
dig example.com +norec

# Useful diagnostics
dig example.com +noall +answer    # clean answer section only
dig example.com +stats            # include query time and server

# Common debug scenarios
# Mail not delivering?
dig example.com MX +short

# CDN not propagating?
dig @8.8.8.8 example.com A +short   # vs
dig @1.1.1.1 example.com A +short

# Kubernetes DNS not resolving?
kubectl exec -it my-pod -- dig my-service.production.svc.cluster.local
iptables / nftables — firewall rules
# iptables — list rules
iptables -L                        # list all chains (filter table)
iptables -L -n                     # numeric (no DNS lookup)
iptables -L -n -v                  # with packet/byte counters
iptables -L -n -v --line-numbers   # with line numbers (for delete)
iptables -t nat -L -n -v           # NAT table (PREROUTING, POSTROUTING)
iptables -t mangle -L -n           # mangle table

# Common operations
# Block incoming from IP
iptables -I INPUT 1 -s 1.2.3.4 -j DROP

# Allow specific port
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Allow established connections (essential — don't miss this)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Block outgoing to IP
iptables -A OUTPUT -d 1.2.3.4 -j DROP

# Delete rule by line number
iptables -D INPUT 3

# Flush all rules (careful — locks you out if SSH is blocked)
iptables -F              # flush rules
iptables -X              # delete user-defined chains

# Save/restore rules
iptables-save > /etc/iptables/rules.v4
iptables-restore < /etc/iptables/rules.v4

# nftables (modern replacement — used in RHEL 8+, Debian 10+)
nft list ruleset              # show all rules
nft list table inet filter
nft add rule inet filter input tcp dport 443 accept

# UFW (user-friendly frontend — Ubuntu)
ufw status verbose
ufw allow 443/tcp
ufw deny from 1.2.3.4
ufw delete allow 80/tcp
ufw enable / disable
curl — HTTP debugging one-liners
# Verbose HTTP request (shows headers, TLS details)
curl -v https://example.com
curl -vvv https://example.com   # even more verbose (TLS handshake details)

# Show only headers
curl -I https://example.com     # HEAD request
curl -sD - -o /dev/null https://example.com   # GET but only print headers

# Timing breakdown
curl -o /dev/null -s -w "%{time_namelookup}s DNS\n%{time_connect}s connect\n%{time_starttransfer}s TTFB\n%{time_total}s total\n" https://example.com

# Test specific IP / bypass DNS
curl --resolve example.com:443:93.184.216.34 https://example.com

# Check TLS certificate
curl -vI https://example.com 2>&1 | grep -E 'subject|issuer|expire|SSL|TLS'

# Follow redirects and show final URL
curl -L -s -o /dev/null -w "%{url_effective}\n" https://example.com

# POST JSON
curl -s -X POST https://api.example.com/endpoint \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"key": "value"}' | jq .

# Download with progress
curl -O --progress-bar https://example.com/file.tar.gz

# Connect via proxy
curl -x http://proxy:3128 https://example.com

# Test from inside a K8s pod
kubectl exec -it my-pod -- curl -v http://other-service.production.svc.cluster.local/health
Diagnosing connectivity problems — step by step
# Step 1: Can we resolve DNS?
dig example.com +short
# No result: DNS problem — check /etc/resolv.conf, firewall port 53

# Step 2: Can we reach the host?
ping -c4 example.com      # ICMP (may be blocked by firewalls)
traceroute example.com    # path tracing
tracepath example.com     # no root needed, MTU discovery

# Step 3: Can we connect to the port?
nc -zv example.com 443    # TCP port check
curl -m 5 -so /dev/null -w "%{http_code}" http://example.com  # HTTP check

# Step 4: What route would we take?
ip route get 93.184.216.34  # which interface and gateway

# Step 5: Is the local port actually listening?
ss -tlnp | grep :8080

# Step 6: Is a firewall blocking it?
iptables -L -n | grep DROP
# Check cloud security groups / NACLs if on AWS/GCP/Azure

# Step 7: Capture the actual traffic
tcpdump -i eth0 host example.com -nn

# Container/K8s: which namespace is the pod in?
ip link show | grep veth   # find veth pair
cat /proc//net/dev    # network interfaces in container namespace

# Common failures and their causes
# ECONNREFUSED   — nothing listening on that port
# ETIMEDOUT      — firewall dropping packets (no RST)
# ECONNRESET     — connection actively rejected mid-stream
# EHOSTUNREACH   — no route to host (routing table issue)
# Name resolution failed — DNS not working

🔍 Free tool: HTTP Security Headers Analyzer — after configuring your Linux network stack, check that your web services return the right HTTP security headers.

Founded

2023 in London, UK

Contact

hello@releaserun.com