Linux System Administration

Networking Configuration

18 min Lesson 6 of 28

Networking Configuration

Networking is the circulatory system of every production server. A misconfigured interface, a wrong DNS resolver, or an unexpected routing table entry will take down services silently — no crash, no core dump, just unreachable endpoints at 3 AM. This lesson gives you the full mental model and hands-on command set that senior DevOps engineers use to configure, inspect, and debug Linux networking on bare metal, VMs, and cloud instances.

The ip Command: Your Primary Tool

The ip command from the iproute2 package is the modern replacement for the long-deprecated ifconfig, route, and arp. Every major distribution ships it; every cloud provider's stock images have it. Do not use ifconfig — it hides secondary addresses, ignores modern routing tables, and is simply not installed on minimal images anymore.

The ip command uses a consistent object-verb grammar: ip <object> <verb>. The primary objects are link (layer 2 interfaces), addr (IP addresses), route (routing table), and neigh (ARP/NDP cache).

# --- Interfaces (link layer) --- ip link show # All interfaces: state, MTU, MAC ip link show eth0 # Single interface detail ip link set eth0 up # Bring interface up ip link set eth0 down # Bring interface down ip link set eth0 mtu 9000 # Set jumbo frames (for 10GbE/25GbE in DC) # --- IP addresses --- ip addr show # All addresses on all interfaces ip addr show eth0 # Addresses on eth0 only ip addr add 192.168.1.10/24 dev eth0 # Add an address (not persistent — survives only until reboot) ip addr del 192.168.1.10/24 dev eth0 # Remove an address # --- Routing table --- ip route show # Full routing table ip route show default # Just the default gateway ip route add default via 192.168.1.1 # Add default route ip route add 10.0.0.0/8 via 10.8.0.1 dev eth1 # Add a specific route (e.g., to a VPN subnet) ip route del 10.0.0.0/8 # Remove a route ip route get 8.8.8.8 # Which interface & gateway will be used for this destination? # --- ARP / neighbour cache --- ip neigh show # ARP table (MAC <-> IP mappings) ip neigh flush dev eth0 # Clear ARP cache on an interface
Pro tip — ip route get: When a service cannot reach a remote endpoint, run ip route get <remote-ip> before anything else. It tells you exactly which source IP and interface Linux will use for that destination. At large companies with multiple NICs, routing table asymmetry is a common and easy-to-miss failure mode.

Understanding Network Interfaces

On a modern Linux server you will encounter several types of network interfaces:

  • Physical NICs: named by predictable network interface names (PNI) — e.g. eno1 (on-board), enp3s0 (PCI bus/slot), ens3 (hot-plug slot). PNI was introduced to eliminate the old eth0/eth1 naming, which was non-deterministic across reboots on multi-NIC servers.
  • Virtual/cloud NICs: AWS names them ens3/eth0; GCP names them ens4. The exact name depends on the hypervisor and kernel driver.
  • Loopback: lo — always 127.0.0.1/8. Services binding to 127.0.0.1 are only reachable locally.
  • Docker/container bridges: docker0, cni0, br-xxxx — virtual bridges created by container runtimes.
  • Bonding/teaming: two or more physical NICs merged into one logical interface for redundancy or bandwidth aggregation.
  • VLANs: tagged sub-interfaces, e.g. eth0.100.
Key idea — flags matter: When you run ip link show, look for the flags in the angle brackets: UP means the interface is administratively enabled; LOWER_UP means physical carrier is detected (cable plugged in or wireless associated). A flapping NIC shows UP but alternating LOWER_UP/NO-CARRIER — a hardware or cable problem, not a software one.

Persistent Configuration: Netplan and NetworkManager

Changes made with ip are ephemeral — they vanish on reboot. Persistent network configuration is managed by one of two stacks depending on your distribution:

  • Netplan (Ubuntu 17.10+, default on Ubuntu Server) — YAML declarations in /etc/netplan/; Netplan generates config for a back-end renderer (either networkd or NetworkManager) and applies it.
  • NetworkManager (Red Hat/CentOS/Fedora, and optionally Ubuntu Desktop) — managed via nmcli, nmtui, or connection profiles in /etc/NetworkManager/system-connections/.
Network configuration stack layers Ubuntu Server / Debian YAML in /etc/netplan/*.yaml Netplan (translator) netplan apply systemd-networkd renderer: networkd RHEL / Fedora / Rocky Connection profiles / nmcli NetworkManager nmcli / nmtui Linux Kernel Network Stack
Both Netplan (Ubuntu) and NetworkManager (RHEL/Rocky) ultimately configure the same Linux kernel network stack.

Netplan example — a server with a static IP on one interface and DHCP on another:

# /etc/netplan/01-netcfg.yaml network: version: 2 renderer: networkd ethernets: enp3s0: # Static IP for the primary NIC (public-facing) addresses: - 203.0.113.10/24 routes: - to: default via: 203.0.113.1 nameservers: addresses: [1.1.1.1, 8.8.8.8] enp4s0: # DHCP for the management/internal NIC dhcp4: true dhcp6: false
# Validate the YAML syntax without applying it netplan try # Applies for 120 s; reverts if you do not confirm (safest way to test) netplan generate # Just generate the back-end configs, do not apply netplan apply # Apply immediately (no rollback — use only when confident) # On Ubuntu, after editing a Netplan file, always prefer: netplan try --timeout 30 # Press Enter to accept, or wait for auto-revert

NetworkManager via nmcli — the command-line approach preferred in automation:

# Show all connections (active and inactive) nmcli connection show # Show active devices and their state nmcli device status # Create a new static IP connection on enp3s0 nmcli connection add type ethernet ifname enp3s0 con-name prod-eth \ ipv4.addresses 10.0.1.50/24 \ ipv4.gateway 10.0.1.1 \ ipv4.dns "1.1.1.1 8.8.8.8" \ ipv4.method manual # Bring it up nmcli connection up prod-eth # Modify an existing connection (e.g., change DNS) nmcli connection modify prod-eth ipv4.dns "8.8.8.8 8.8.4.4" nmcli connection reload # Delete a connection profile nmcli connection delete prod-eth
Production pitfall — cloud instances: On cloud VMs (AWS EC2, GCP, Azure), never change the primary NIC to a static IP manually. The instance metadata service and cloud-init manage DHCP; overriding it breaks cloud-agent communication, SSH key delivery, and instance monitoring. If you need a fixed IP on a cloud VM, assign an Elastic IP (AWS) or a static internal IP via the cloud console — do not change the OS-level DHCP configuration.

Hostnames and DNS Resolution

Name resolution in Linux flows through a layered resolver chain. Understanding the chain is essential for debugging service discovery failures in production:

  1. /etc/hosts — static table, checked first by default. Useful for local overrides and container hostnames, but a maintenance nightmare at scale.
  2. NSS (Name Service Switch) — configured in /etc/nsswitch.conf. The hosts: line controls resolution order, typically files dns myhostname.
  3. DNS resolver — queries the nameservers listed in /etc/resolv.conf. On modern systems this file is managed by systemd-resolved and is a symlink to /run/systemd/resolve/stub-resolv.conf.
# Set or change the system hostname hostnamectl set-hostname prod-api-01.us-east-1.internal hostnamectl status # Show static, transient, and pretty hostnames # Inspect /etc/hosts cat /etc/hosts # Check the effective resolv.conf cat /etc/resolv.conf # Often a symlink on systemd-resolved systems resolvectl status # Full systemd-resolved status: per-interface DNS, DNSSEC state resolvectl query github.com # Resolve a name through systemd-resolved (with debug info) # DNS diagnostics dig github.com # Full DNS query output (use this, not nslookup) dig github.com @1.1.1.1 # Force a specific resolver (bypass the local cache) dig +short github.com # Just the IP dig -x 8.8.8.8 # Reverse lookup dig github.com MX # Query a specific record type # Network connectivity quick checks ping -c 3 8.8.8.8 # Layer 3 reachability (ICMP) traceroute -n 8.8.8.8 # Path to destination (use -n to skip reverse DNS lookups) ss -tulnp # All listening sockets with owning process (replaces netstat)
Key idea — systemd-resolved and the stub resolver: On Ubuntu 18.04+ and modern RHEL systems, /etc/resolv.conf points to 127.0.0.53:53, the stub resolver run by systemd-resolved. This gives you per-interface DNS, DNSSEC, and caching. If you replace /etc/resolv.conf with a plain file pointing to a corporate DNS server, you lose all of that. The correct way to configure DNS is through Netplan (nameservers:) or nmcli so that systemd-resolved learns about it per-interface.

Putting It Together: Diagnosing a Network Failure

When a service is unreachable, work through this mental model layer by layer:

  1. Is the interface up? ip link show <if> — look for LOWER_UP.
  2. Does it have the right IP? ip addr show <if>.
  3. Is the route correct? ip route get <destination>.
  4. Does ARP/L2 work? ip neigh show — is the gateway MAC resolved?
  5. Does DNS resolve? dig <hostname> — compare with dig @8.8.8.8 <hostname> to isolate local resolver issues.
  6. Is the port open? ss -tulnp | grep <port> on the server; nc -zv <host> <port> from the client.
  7. Is a firewall blocking? iptables -L -n -v or nft list ruleset — covered in the Security Hardening lesson.
Pro tip — ss over netstat: netstat is deprecated and often not installed on minimal images. ss (socket statistics) is faster, always present, and shows the owning process via -p. The flags -tulnp mean: TCP + UDP, Listening only, Numeric (no DNS), with Process. Memorise this combination — you will run it many times per day.