Interfaces and Addressing
Topic 47

Interfaces and Addressing

NetworkingConcept

A network interface is the kernel's handle on a link — a physical NIC, a VLAN, a bridge, a tunnel, or the loopback. You attach addresses to it, bring it up or down, and the kernel routes packets through it. Addressing is the layer above: an IPv4 or IPv6 address plus a prefix length that tells the kernel which destinations sit directly on the link and which must go through a gateway. On a current Debian or Ubuntu server you manage both through the ip command from the iproute2 suite and a declarative config layer — Netplan on Ubuntu, systemd-networkd or ifupdown underneath.

The operational consequence is that runtime and persistence are two separate worlds, and confusing them costs you. An ip addr add takes effect instantly and survives nothing — one reboot and it is gone. The config files survive reboots but do nothing until a renderer or daemon applies them. Every "the network came back wrong after a reboot" incident lives in that gap.

Interface Naming and Types

Predictable Network Interface Names replaced the old eth0/eth1 scheme on Debian and Ubuntu years ago, because kernel probe order is non-deterministic and eth0 could land on a different card between boots. Names now encode the hardware path: enp3s0 is a PCI Ethernet device on bus 3 slot 0, eno1 is onboard NIC 1, ens5 is a hot-plug slot, and wlp2s0 is wireless. The loopback is always lo at 127.0.0.1/8 and ::1/128. The names stay stable across reboots and hardware reseating, which is exactly what a server needs.

Not every interface is a NIC. The kernel exposes virtual interfaces of several kinds, and a server host usually runs a fistful of them.

TypeExamplePurpose
Physicalenp3s0A real NIC, one per port
LoopbackloHost-local traffic, always present
VLANenp3s0.100802.1Q tag 100 on a trunk port
Bridgebr0Software switch joining ports and VMs
Bondbond0Aggregated links for redundancy or throughput
Tunnel/pairwg0, veth*WireGuard, container pairs, overlays

Inspecting State with iproute2

The iproute2 suite is the current interface. The deprecated net-tools commands — ifconfig, route, netstat — are not installed by default on a minimal Debian or Ubuntu and show an incomplete picture: ifconfig hides secondary addresses and IPv6 detail that ip addr prints in full. Learn the ip object model and you stop reaching for the old tools.

# list interfaces, addresses, and link state
ip addr show
ip -br addr            # one terse line per interface
ip link show enp3s0    # L2: MAC, MTU, UP/DOWN

# add a runtime address (gone on reboot)
sudo ip addr add 10.0.5.20/24 dev enp3s0
sudo ip link set enp3s0 up

# remove it again
sudo ip addr del 10.0.5.20/24 dev enp3s0

A field worth reading closely is link state versus carrier. ip link can report a link as administratively UP while NO-CARRIER shows in the flags — the interface is enabled but no cable or peer is detected. That distinction tells you instantly whether a dead link is your config or a physical fault upstream.

Addresses, Prefixes, and Scope

An address is meaningless without a prefix length. 10.0.5.20/24 means the first 24 bits are the network, so the host treats 10.0.5.0 through 10.0.5.255 as directly reachable on the link and sends everything else to a gateway. Get the prefix wrong — a /16 where the LAN is really a /24 — and the host tries to ARP for addresses that live behind a router, so they silently time out instead of routing. CIDR is not optional knowledge here; it is the difference between a host that talks and one that half-talks.

IPv6 changes the shape of the problem. An interface normally holds several addresses at once: a link-local fe80::/10 address the kernel auto-generates and uses for neighbor discovery, plus one or more global addresses from SLAAC or DHCPv6. There is no ARP — Neighbor Discovery over ICMPv6 replaces it — and the link-local address must stay reachable for the link to function, so never blanket-filter fe80::/10 in a host firewall. Dual-stack servers run both protocols side by side, and a service bound only to IPv4 is invisible to IPv6 clients.

# every address on every interface, with scope
ip -6 addr show
# scope global vs scope link tells you which is routable

Persistent Configuration with Netplan

On Ubuntu the persistence layer is Netplan: YAML files in /etc/netplan/ that a renderer compiles into the active backend — systemd-networkd on servers, NetworkManager on desktops. You write intent, not commands. netplan generate renders the backend config and netplan apply brings it live without a reboot. Debian without Netplan uses either /etc/network/interfaces (ifupdown) or systemd-networkd unit files directly; the YAML below is the Ubuntu default. On Red Hat the equivalent role belongs to NetworkManager keyfiles managed with nmcli.

# /etc/netplan/01-netcfg.yaml  (mode 0600 — it can hold secrets)
network:
  version: 2
  renderer: networkd
  ethernets:
    enp3s0:
      addresses: [10.0.5.20/24, "2001:db8:5::20/64"]
      routes:
        - to: default
          via: 10.0.5.1
      nameservers:
        addresses: [10.0.5.1, 1.1.1.1]

Two Netplan habits make a config change survivable. First, netplan try applies the new config and automatically rolls back after 120 seconds unless you confirm — so a mistake that kills your SSH session repairs itself instead of stranding the box. Second, before you make a risky change on a remote host with no console, queue a delayed safety net: sudo sh -c 'sleep 300 && netplan apply' from the last known-good file, so a lockout self-heals in five minutes.

Netplan vs systemd-networkd vs NetworkManager

Netplan — Ubuntu's YAML front-end; it does not manage the network itself but renders config for a backend. Use it on Ubuntu servers; it is the default and the documented path.

systemd-networkd — the lightweight daemon that actually drives the link on a headless server, configured by .network unit files or rendered by Netplan. Use it directly on Debian, where Netplan is not installed by default.

NetworkManager — the dynamic manager built for laptops and roaming, and the Red Hat default managed with nmcli. Use it on desktops and on RHEL-family hosts; avoid running it and networkd on the same box, where they fight over the same interface.

Common Mistakes
  • Setting an address with ip addr add and assuming it is permanent — it lives only in kernel state and vanishes on the next reboot, leaving a "worked yesterday" host unreachable.
  • Wrong prefix length, such as a /16 on a /24 LAN — the host treats off-link hosts as directly reachable, ARPs for them, and they time out silently instead of routing through the gateway.
  • Hardcoding eth0 in scripts or configs on a box that uses predictable names like enp3s0 — the interface never comes up and nothing matches, because the name does not exist.
  • Editing a Netplan YAML and forgetting netplan apply — the file is correct but the running system still uses the old config, so the change appears to do nothing.
  • Running NetworkManager and systemd-networkd against the same interface — the two managers fight, and the address flaps or never settles.
  • Blanket-dropping fe80::/10 or all ICMPv6 in a host firewall — Neighbor Discovery breaks and IPv6 connectivity on the link dies, even though the global addresses look configured.
  • Indenting Netplan YAML with tabs or mismatched spaces — the renderer rejects the file and you can be left with no working network config after a reboot.
Best Practices
  • Use ip from iproute2 for every inspection and runtime change; treat ifconfig/route as legacy and do not install net-tools on new servers.
  • Make all permanent changes in /etc/netplan/ (or your distro's config layer) and apply with netplan apply — never leave a live address that exists only in kernel state.
  • Validate risky remote changes with netplan try, which auto-reverts after 120 seconds, so a config that kills SSH rolls itself back instead of stranding the host.
  • Always pin the prefix length deliberately and confirm it against the subnet's CIDR; verify with ip route get <dest> that traffic exits the interface you expect.
  • Run exactly one network manager per host — Netplan-plus-networkd on Ubuntu, NetworkManager on RHEL — and do not let a second one touch the same link.
  • Keep the loopback and IPv6 link-local reachable — scope host-firewall rules to global addresses and permit the ICMPv6 types that Neighbor Discovery needs.
  • Chmod Netplan files to 0600 and run netplan generate to catch YAML errors before they reach a backend you can't easily recover from remotely.
Comparable toolsWindowsnetsh and the Network Connections panel; addresses persist in the registry rather than a flat config filemacOSifconfig still primary, with networksetup and the System Settings panel for persistenceBSDifconfig for runtime and /etc/rc.conf for persistence, both far more capable than the Linux net-tools ifconfig

Knowledge Check

You run sudo ip addr add 10.0.5.20/24 dev enp3s0 and connectivity works. After a reboot the host is unreachable. Why?

  • ip addr add changes only live kernel state and is never persisted, so the address must also be declared in Netplan to survive a reboot
  • The address was correct but the prefix length resets to /32 on reboot unless you specify a gateway
  • Predictable interface names are reassigned by udev on every boot, so enp3s0 became a different interface and your address landed on the wrong one
  • A runtime address disables Netplan, which then fails to bring any interface up after reboot

A host is configured 10.0.5.20/16 but the LAN is actually a /24. What breaks?

  • The host treats addresses really behind the router as directly reachable, ARPs for them, and those connections time out instead of routing through the gateway
  • Nothing — a wider prefix is always a safe superset of a narrower one
  • The interface refuses to come up at all, because the kernel validates the configured /16 prefix against the /24 subnet mask the router advertises and rejects the mismatch
  • Only IPv6 traffic is affected; IPv4 ignores prefix length on the local link

Why is netplan try preferable to netplan apply when changing the network on a remote server with no console?

  • It applies the new config but automatically rolls back after 120 seconds unless you confirm, so a change that severs SSH repairs itself
  • It applies the config faster because it skips rendering the backend
  • It encrypts the YAML before applying, protecting credentials in transit
  • It validates the YAML syntax only and never once touches the running network interfaces, so it cannot possibly drop your live SSH session midway

On a dual-stack host, why should a firewall never blanket-drop fe80::/10?

  • Link-local addresses carry IPv6 Neighbor Discovery, the ARP replacement; dropping them breaks address resolution and kills IPv6 on the link
  • Link-local is the only routable IPv6 scope, so dropping it removes all internet access
  • fe80::/10 is the loopback range and the host needs it for local sockets
  • It is the dedicated DHCPv6 server range, so dropping it stops the host from ever leasing a global IPv6 address and leaves it stranded offline

You got correct