Linux Networking Reference

IPs, interfaces, routes, DNS, ports, and the tools you actually use to diagnose network problems.

ip command — interfaces and addresses

# List all interfaces and their IP addresses
ip addr show
ip a            # short form

# Show one interface
ip addr show eth0

# Bring an interface up/down
ip link set eth0 up
ip link set eth0 down

# Add an IP address to an interface (temporary — not persistent)
ip addr add 10.0.0.5/24 dev eth0

# Remove an IP address
ip addr del 10.0.0.5/24 dev eth0

ip replaces the older ifconfig. Use ipifconfig is not installed by default on modern systems.

Routes

# Show routing table
ip route show
ip r            # short form

# Show the route a packet to a specific destination would take
ip route get 8.8.8.8

# Add a static route (temporary)
ip route add 192.168.50.0/24 via 10.0.0.1

# Add a default gateway (temporary)
ip route add default via 10.0.0.1

# Delete a route
ip route del 192.168.50.0/24 via 10.0.0.1

Temporary routes added with ip route add are lost on reboot. To make them persistent, use nmcli or edit the network config files.

DNS tools

# Query DNS (shows full response with TTL, record type)
dig example.com
dig example.com A        # A records only
dig example.com MX       # MX records
dig example.com @8.8.8.8 # use a specific resolver

# Reverse lookup (IP to hostname)
dig -x 8.8.8.8

# Quick hostname resolution (no extra detail)
host example.com
host 8.8.8.8

# nslookup (interactive or one-shot)
nslookup example.com
nslookup example.com 8.8.8.8

# Which DNS servers am I using?
cat /etc/resolv.conf
resolvectl status         # on systems using systemd-resolved

Reading dig output:

;; ANSWER SECTION:
example.com.     3600  IN  A   93.184.216.34
#               ^TTL       ^type ^value

Open ports and sockets

# Show all listening ports and the processes using them
ss -tlnp          # TCP, listening, numeric, with process

# All listening (TCP + UDP)
ss -ulnp          # UDP
ss -tlnp          # TCP

# All established connections
ss -tnp

# Show connections to a specific port
ss -tnp '( dport = :443 or sport = :443 )'

# Old way (still works, may not be installed)
netstat -tlnp

Reading ss -tlnp output:

State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
LISTEN  0       128     0.0.0.0:22          0.0.0.0:*          users:(("sshd",pid=1234))
LISTEN  0       511     0.0.0.0:80          0.0.0.0:*          users:(("nginx",pid=5678))

Testing connectivity

# Basic reachability (ICMP)
ping -c 4 8.8.8.8

# Test TCP connectivity to a specific port
nc -zv 10.0.0.5 22     # -z = scan, -v = verbose
nc -zv 10.0.0.5 443

# Test HTTP(S) with curl (shows response headers)
curl -v http://example.com
curl -vk https://example.com    # -k = ignore TLS errors

# Trace the path packets take
traceroute 8.8.8.8
mtr 8.8.8.8              # interactive traceroute with live updates
# Test multiple ports quickly
for port in 22 25 80 443; do
  nc -zv -w2 target-host $port 2>&1
done

Network config files (RHEL/nmcli)

On RHEL 8/9, NetworkManager manages interfaces. Config files are in /etc/NetworkManager/system-connections/ in keyfile format (or the older /etc/sysconfig/network-scripts/ifcfg-* on RHEL 7/early 8).

# /etc/NetworkManager/system-connections/eth0.nmconnection

[connection]
id=eth0
type=ethernet
interface-name=eth0

[ipv4]
method=manual
addresses=10.0.0.5/24
gateway=10.0.0.1
dns=10.0.0.10;10.0.0.11

[ipv6]
method=disabled

Do not edit these files directly unless you are comfortable with the format. Use nmcli to make changes — it updates the files and activates the changes cleanly.

nmcli quick reference

# Show connection status
nmcli connection show

# Show device status
nmcli device status

# Set a static IP on an interface
nmcli con mod eth0 ipv4.method manual ipv4.addresses "10.0.0.5/24" ipv4.gateway "10.0.0.1"

# Set DNS servers
nmcli con mod eth0 ipv4.dns "10.0.0.10 10.0.0.11"

# Apply the change
nmcli con up eth0

# Set DHCP
nmcli con mod eth0 ipv4.method auto
nmcli con up eth0

# Add a DNS search domain
nmcli con mod eth0 ipv4.dns-search "example.com internal.example.com"

Packet capture with tcpdump

# Capture all traffic on eth0
tcpdump -i eth0

# Capture to a file (open with Wireshark)
tcpdump -i eth0 -w /tmp/capture.pcap

# Filter by host
tcpdump -i eth0 host 10.0.0.5

# Filter by port
tcpdump -i eth0 port 25

# Filter by protocol and port
tcpdump -i eth0 tcp port 443

# Watch DNS queries
tcpdump -i eth0 port 53

# Watch SMTP traffic to a specific host
tcpdump -i eth0 host mail.example.com and port 25

# Show packet contents in ASCII
tcpdump -i eth0 port 25 -A | head -50

tcpdump is the first tool to reach for when you need to see what is actually on the wire. Useful for confirming whether traffic is reaching a host, and for diagnosing TLS handshake failures, routing issues, or unexpected connections.

When tcpdump isn't enough:
  • Need to read a protocol (HTTP, TLS, DNS, SMB, Kerberos) rather than just see packets → capture with tcpdump -w file.pcap and open in Wireshark. Use display filters like tls.handshake, http.request, tcp.analysis.retransmission.
  • Need to confirm which ports are open on a host from the network, or find services a box is exposing → use NMAP: nmap -sV host or nmap -p- host. Stay inside scope.

Interface-level counters — ethtool & ip -s link

Before blaming the network, check whether the interface itself is healthy. Errors, drops, or a link stuck at the wrong speed show up here first, not in tcpdump.

# Per-interface packet and error counters
ip -s link show eth0
# Look at: RX/TX errors, dropped, overrun, carrier

# Link, speed, duplex, auto-neg
ethtool eth0
# Confirms Link detected: yes / Speed: 10000Mb/s / Duplex: Full

# Driver and firmware
ethtool -i eth0

# Detailed statistics from the driver (useful for NICs with offload)
ethtool -S eth0 | grep -iE 'err|drop|discard'

# Ring buffer sizes (increase if you see rx_dropped under load)
ethtool -g eth0

# Offload features (TSO, GSO, GRO, checksum). Disable per-feature for debugging
ethtool -k eth0

Non-zero dropped or overrun in ip -s link usually means the host can't keep up with the NIC (CPU, ring buffer, or driver). Link flapping or wrong speed in ethtool usually means a cable, SFP, or switch-port problem — not the host.

Network namespaces (containers)

If you are working with containers, the application's network stack lives in a separate namespace. The host ip commands show host-level networking only.

# List network namespaces
ip netns list

# Run a command in a specific namespace
ip netns exec mynamespace ip addr show

# For Docker containers
docker exec -it container_name ip addr show
docker exec -it container_name ss -tlnp

Networking troubleshoot checklist

Service is not reachable — work through this in order:

  1. Is the service running and listening?ss -tlnp | grep PORT
  2. Is it listening on the right interface? — check for 127.0.0.1:PORT vs 0.0.0.0:PORT
  3. Is the firewall blocking it?firewall-cmd --list-all
  4. Is it reachable from the target host?nc -zv host port from the client
  5. Is DNS resolving?dig hostname
  6. Is the route correct?ip route get TARGET_IP
  7. Is traffic actually arriving?tcpdump -i eth0 port PORT on the server
  8. Is the interface itself healthy?ip -s link show eth0 and ethtool eth0 — look for errors, drops, wrong speed/duplex
  9. Protocol-level problem (TLS, HTTP, auth)? — capture a pcap and open in Wireshark
  10. Don't know what's listening on the remote host?nmap -sV host from inside your scope
  11. Is SELinux blocking it? — check /var/log/audit/audit.log for AVC denials

Netplan — network configuration on Debian/Ubuntu

Debian/Ubuntu 18.04+ uses Netplan as the network configuration front-end. YAML files in /etc/netplan/ are rendered into NetworkManager or systemd-networkd configuration.

# List netplan config files
ls /etc/netplan/

# Example: /etc/netplan/00-installer-config.yaml
# Static IP configuration
network:
  version: 2
  renderer: networkd   # or: NetworkManager
  ethernets:
    eth0:
      dhcp4: false
      addresses:
        - 192.168.1.100/24
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]
        search: [example.com]

# Apply changes (test first)
netplan try        # applies config; rolls back in 120s if you don't confirm
netplan apply      # apply permanently (no rollback)

netplan try is the safe way to apply network changes remotely — if the new config breaks connectivity you will be disconnected, the timer expires, and the old config is restored automatically. Always use netplan try before netplan apply on production servers.

ARP / neighbour table

The ARP table maps IP addresses to MAC addresses. It is useful for diagnosing duplicate IP issues, identifying which physical host is at an IP, and verifying L2 connectivity.

# View the ARP / neighbour table
ip neigh show
ip neigh show dev eth0    # limit to one interface

# Example output:
# 192.168.1.1 dev eth0 lladdr 00:11:22:33:44:55 REACHABLE
# 192.168.1.50 dev eth0 lladdr FAILED   ← host not responding at L2

# Delete a stale ARP entry (forces re-resolution)
ip neigh del 192.168.1.50 dev eth0

# Flush all entries on an interface
ip neigh flush dev eth0

# Check for duplicate IPs (two different MACs for same IP)
ip neigh show | grep 192.168.1.1

A FAILED or missing ARP entry means the host is not responding at Layer 2 — either the host is down, the MAC address changed (VM migration, NIC replacement), or there is a VLAN mismatch. An IP showing two different MACs is a duplicate IP conflict.

Bonding / teaming

Bonding (the kernel bonding driver) and teaming (the userspace teamd alternative) combine two or more physical NICs into a single logical interface for redundancy (active-backup) or throughput (LACP 802.3ad). One link fails, traffic keeps flowing over the other.

# Quick active-backup bond with nmcli
nmcli con add type bond ifname bond0 mode active-backup
nmcli con add type bond-slave ifname eno1 master bond0
nmcli con add type bond-slave ifname eno2 master bond0
nmcli con mod bond0 ipv4.method manual ipv4.addresses 10.0.0.5/24

# Check bond state
cat /proc/net/bonding/bond0

Full worked examples, mode trade-offs (active-backup vs LACP vs balance-xor), and integration with ifcfg/NetworkManager/systemd-networkd on Bonding & Bridges.

Bridges

A bridge is a software L2 switch — you attach physical or virtual interfaces to it and they share a broadcast domain. This is how KVM hosts expose VM NICs to the same L2 as the host, and how Podman/Docker create the default container network.

# Minimal bridge
nmcli con add type bridge ifname br0
nmcli con add type bridge-slave ifname eno1 master br0
nmcli con mod br0 ipv4.method manual ipv4.addresses 10.0.0.5/24

# Inspect
bridge link show
ip -d link show br0

See Bonding & Bridges for STP, MAC address strategy, VLAN-aware bridges, and the "bridge on top of a bond" pattern used on hypervisors.

VRF — Virtual Routing and Forwarding

A VRF is a completely separate routing table attached to a set of interfaces, inside the same kernel. Useful when a single host needs to talk to two isolated networks with overlapping address space (classic: management VRF for iLO/iDRAC traffic, data VRF for application traffic) without running a full namespace.

# Create a VRF bound to routing table 10
ip link add vrf-red type vrf table 10
ip link set dev vrf-red up

# Enslave an interface to the VRF
ip link set dev eth1 master vrf-red

# Give that VRF a default route inside its own table
ip route add default via 10.10.0.1 dev eth1 table 10

# Run a command scoped to the VRF (uses table 10 for lookups)
ip vrf exec vrf-red ping 10.10.0.1
ip vrf exec vrf-red ss -tlnp

Everything in a VRF is isolated at the routing level — a packet received on eth1 (in vrf-red) cannot reach an application bound to 0.0.0.0 in the default VRF unless you explicitly leak routes between tables. Bind services to a specific VRF with systemd's NetworkNamespacePath (for namespaces) or by starting them under ip vrf exec.

ip rule — policy routing

By default, the kernel picks a route using just the destination IP. ip rule lets you send traffic through a different routing table based on source address, interface, firewall mark, or other selectors — the foundation of "out-interface routing" and the mechanism VRFs build on.

# Show active rules (default: local -> main -> default)
ip rule show
# 0:      from all lookup local
# 32766:  from all lookup main
# 32767:  from all lookup default

# Source-address policy: traffic from 10.20.0.0/24 uses table 20
ip rule add from 10.20.0.0/24 table 20
ip route add default via 10.20.0.1 dev eth2 table 20

# Fwmark policy: packets marked 0x1 by iptables use table 30
iptables -t mangle -A OUTPUT -d 203.0.113.0/24 -j MARK --set-mark 0x1
ip rule add fwmark 0x1 table 30
ip route add default via 192.0.2.1 dev eth3 table 30

# Remove a rule (use -p to match exactly)
ip rule del from 10.20.0.0/24 table 20

Rules are matched top-down by priority (lower number = higher priority). The lookup continues only if a rule matches but its target table doesn't contain a route — so you can chain specific rules above main and fall through naturally.

Multi-homed default route pitfall

Two NICs, two default routes, one silent outage. When a host has interfaces on two networks (e.g. eth0 on the management LAN and eth1 on the storage/app LAN) and both get a default route from DHCP, the kernel picks one of them and sends all egress traffic through it — typically whichever has lower metric. Incoming TCP on the other interface replies over the chosen default route, packets leave via a different source IP than they arrived on, firewalls drop them as spoofed, and the connection stalls.

This is asymmetric routing, and it's almost always a misconfiguration. Fixes:

  • Only one default route. Delete or never assign a default on the second interface; add specific-subnet routes for the networks you need to reach via that NIC.
  • Policy routing. Use ip rule to give each source IP its own routing table so replies exit via the interface they arrived on (rp_filter must be set to loose (2) or off for this to work).
  • VRF. The cleanest long-term answer when the two networks are truly independent — put each NIC in its own VRF with its own default, and services bind explicitly to the VRF they belong to.

Diagnose quickly with ip route get 8.8.8.8 from <remote-client-ip> and tcpdump -i any icmp — if ingress is on eth1 and egress on eth0, you've found it.