// linux fundamentals — module 08

Module 8 — Networking on Linux (a Checkpoint)

Thesis: You already know networking theory (IP, routing, DNS, TCP/UDP) — this module is deliberately a checkpoint, not a course: how those concepts surface on Linux specifically — which files, which daemons, which commands — so that the theory connects to the machine in front of you. If any theory itself feels shaky, patch it externally before proceeding; this module assumes it.

Prerequisite: Module 7 — systemd — network state on a modern system is managed by services, and you can now inspect services.


8.1 Where networking lives: the kernel, driven from userland

Fit networking into the course's map: the entire TCP/IP stack is in the kernel (§0.2's list, last item). Packets arrive at a NIC → the driver (a module, §2.6) hands them to kernel code that does IP, routing, TCP — all in kernel space. Userland programs get network access the only way anything gets anything: syscallssocket, bind, connect, listen, accept (§2.2's table). An open socket is held as a file descriptor (§5.5) — "everything is a file," including network connections.

So the division of labor is: the kernel does the networking; userland tools configure and query it. The modern query/config tool is ip (from iproute2; it replaced the crusty ifconfig/route you'll still see in old tutorials):

ip addr        # (ip a) interfaces and their addresses
ip link        # interfaces at layer 2: state UP/DOWN, MAC
ip route       # (ip r) the routing table

Reading ip addr, connected to what you know: expect loloopback, 127.0.0.1/::1, the machine talking to itself — plus your real NICs with names like enp3s0 or wlp2s0 (predictable interface names: en=ethernet, wl=wifi, the rest encodes the PCI location — courtesy of udev, §2.6). Each shows its state, MAC, and IPv4/IPv6 addresses with prefix length.

Reading ip route: the default via 192.168.1.1 dev enp3s0 line is your gateway; the 192.168.1.0/24 dev enp3s0 … line says the local subnet is reached directly. Kernel routing decision = most-specific prefix wins, default as the fallback — your existing theory, in one screen of text.

8.2 Who configures it: management daemons

A NIC with no configuration does nothing. Something must bring links up, run DHCP, set addresses and routes — and on a modern system that something is a service you can now inspect with Module 7 skills. One of, typically:

  • NetworkManager — desktops/laptops: WiFi roaming, VPNs; CLI is nmcli (nmcli device, nmcli connection show).
  • systemd-networkd — servers and declarative setups: plain config files, no GUI ambitions.
  • (Embedded/minimal systems may run a bare DHCP client; the idea is the same.)

The point of this section is the reflex: "network is down" on a modern box is a service question first — systemctl status NetworkManager (or systemd-networkd), then journalctl -u NetworkManager -b — before it is a cable question. Your Module 7 debugging loop applies verbatim.

8.3 Name resolution: what actually happens on a lookup

DNS theory you have; here is the Linux-specific chain, which surprises most people with how many stops it has. When a program resolves example.com, it calls libc's resolver (§2.2 — everything routes through libc), which consults:

  1. /etc/nsswitch.conf — the dispatcher: its hosts: line lists sources in order, e.g. hosts: files resolve dns. Meaning:
  2. files = /etc/hosts — a local static table, checked first. This is why adding 127.0.0.1 ads.example.com there "blocks" a site, and why a stale test entry in this file causes legendary "but it works on my machine" mysteries — it silently outranks DNS.
  3. dns = classic path: read /etc/resolv.conf for nameserver addresses and query them.
  4. On many modern systems, systemd-resolved (a Module 7 service, resolve in nsswitch) sits in between: a local caching stub — /etc/resolv.conf is then a symlink (§3.5, everywhere forever) pointing at 127.0.0.53, and the real upstream servers live in resolvectl status.

Diagnostic consequence, worth the whole section: getent hosts example.com asks through the full libc chain — exactly what real programs experience — while dig example.com speaks raw DNS only, skipping /etc/hosts and nsswitch. When those two disagree, the discrepancy itself tells you which layer is lying. That pair of tools plus this chain solves most "DNS is weird" tickets.

8.4 Sockets, ports, and who is listening

Theory: a TCP/UDP endpoint = address + port; a server listens, a client connects. Linux practice: the tool is ss (socket statistics; successor of netstat), and one incantation covers most needs:

ss -tlnp

t TCP · l listening only · n numeric (no name lookups) · p which process (§2.5) owns each socket. Output reads: local address 0.0.0.0:22 (listening on all interfaces) vs 127.0.0.1:5432 (loopback only — unreachable from outside, the classic "why can't I connect to the database" answer), and the owning process/PID at the end. Variants: -u for UDP, drop -l (or ss -tnp) for established connections.

Two kernel-enforced rules that tie back to earlier modules: ports below 1024 require root or CAP_NET_BIND_SERVICE (§4.8's example capability, in context), and one socket per address:port — the "address already in use" error is the kernel refusing a second bind.

Also name the last resident of this layer: the kernel firewall — nftables (successor of iptables), rules over packets, usually managed via a frontend (firewalld, ufw, or NixOS's networking.firewall). Deep rules-writing is beyond a fundamentals course; knowing "a packet can be dropped by the kernel before any process sees it" belongs in your debugging checklist forever: if ss shows a listener but remote connections fail, suspect the firewall.

8.5 The debugging ladder

Assembling all of it — when "the network doesn't work," walk up the stack, one question per layer, each answerable with one command:

  1. Link up? ip link (state UP? cable/WiFi associated?)
  2. Address? ip addr (real address, or nothing/169.254.x.x = DHCP failed → §8.2, check the manager service)
  3. Route? ip route (is there a default via …?)
  4. Gateway reachable? ping <gateway-ip>
  5. Internet by IP? ping 1.1.1.1 (works while step 6 fails ⇒ the problem is DNS, nothing lower)
  6. Names? getent hosts example.com vs dig example.com (§8.3 — and the disagreement diagnostic)
  7. The service itself? ss -tlnp on the server side (listening? on the right address?); firewall (§8.4); then curl -v http://… to watch a full connection attempt narrated.

This ladder is the module. Everything above exists so each rung is meaningful.

8.6 → NixOS

Networking on NixOS is declared — networking.hostName, networking.firewall.allowedTCPPorts = [ 22 80 ];, networking.networkmanager.enable = true; or the systemd.network.* tree — and NixOS generates the daemon configs, hosts file, and firewall rules you've just learned to read. The declarations are one layer up; everything underneath is unchanged: the same kernel stack, the same ip/ss/getent for inspection, the same journalctl on the same services when it misbehaves. You now speak both layers.


Lab 8

  1. Map your machine. ip addr and ip route. Identify: loopback; each real interface (decode its name per §8.1); your IP and prefix; your default gateway. Cross-check the gateway with your router's known address.

  2. Identify your manager. Is it NetworkManager or networkd? (systemctl status NetworkManager systemd-networkd — one will be active.) Run systemctl status on the winner and read it with Module 7 eyes; skim journalctl -u <it> -b and find the moment your interface got its address at boot (the DHCP lease lines).

  3. Trace the resolution chain. Read the hosts: line of /etc/nsswitch.conf and translate it. ls -l /etc/resolv.conf — file or symlink? If symlink: resolvectl status for the real upstreams. Then run both getent hosts example.com and dig example.com and confirm agreement.

  4. Poison and heal /etc/hosts. Add 127.0.0.1 example.com to /etc/hosts (sudo). Run the §8.3 pair again: getent now returns 127.0.0.1 while dig still returns the real address — the disagreement diagnostic, demonstrated. Try curl -v http://example.com and watch it connect to yourself and fail. Remove the line, verify healing. You will remember this the day a hosts-file mystery bites.

  5. Census the listeners. sudo ss -tlnp. For every line: which process, which port, and — the important read — 0.0.0.0/[::] vs 127.0.0.1: say which listeners are reachable from the network and which are loopback-only. Anything listening you can't explain? Investigate it (what's its service? systemctl status <pid's unit>) — that's a genuine security-audit habit.

  6. Watch a socket be born. In one terminal: python3 -m http.server 8080. In another: find it in ss -tlnp, fetch from it (curl localhost:8080), see the established pair in ss -tnp, then Ctrl-C the server (§5.4 — you know exactly what that sent) and confirm the listener is gone.

  7. Climb the ladder. Run the full §8.5 ladder on your healthy machine, one rung at a time, saying what each result rules out. If you have a VM: break it (disconnect the virtual NIC, or set a bogus nameserver in resolv.conf), and use the ladder to locate the break before fixing it. Diagnosing a fault you planted is practice; the ladder is the takeaway.


✅ Mastery Check — do not proceed until true

Answer out loud, without notes:

  1. Where does the TCP/IP stack run — and by which two syscall-and-fd facts does a userland program touch it?
  2. Read any ip addr / ip route output: interface names decoded, addresses, and how the kernel picks a route for a given packet.
  3. What daemon manages your network config, and what's the Module-7 move when an interface has no address?
  4. Recite the full name-resolution chain — nsswitch, hosts file, resolv.conf, resolved — and explain what getent vs dig disagreement tells you.
  5. Decode ss -tlnp flag by flag, and explain 0.0.0.0:80 vs 127.0.0.1:80 for reachability.
  6. Which two kernel rules govern binding (low ports; exclusivity), and which module's concepts do they belong to?
  7. Recite the seven-rung debugging ladder with the command for each rung, and what "ping 1.1.1.1 works but browsing doesn't" isolates.

And perform cold:

  • Map any machine's interfaces, routes, and listeners in under a minute.
  • Determine whether a resolution problem is hosts-file, resolver config, or upstream DNS.
  • Locate a planted network fault using the ladder, narrating each elimination.

When all of that is effortless: Module 9 — Package Management and Shared Libraries