// 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: syscalls — socket, 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 lo — loopback, 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:
/etc/nsswitch.conf— the dispatcher: itshosts:line lists sources in order, e.g.hosts: files resolve dns. Meaning:files=/etc/hosts— a local static table, checked first. This is why adding127.0.0.1 ads.example.comthere "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.dns= classic path: read/etc/resolv.conffor nameserver addresses and query them.- On many modern systems,
systemd-resolved(a Module 7 service,resolvein nsswitch) sits in between: a local caching stub —/etc/resolv.confis then a symlink (§3.5, everywhere forever) pointing at127.0.0.53, and the real upstream servers live inresolvectl 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:
- Link up?
ip link(state UP? cable/WiFi associated?) - Address?
ip addr(real address, or nothing/169.254.x.x = DHCP failed → §8.2, check the manager service) - Route?
ip route(is there adefault via …?) - Gateway reachable?
ping <gateway-ip> - Internet by IP?
ping 1.1.1.1(works while step 6 fails ⇒ the problem is DNS, nothing lower) - Names?
getent hosts example.comvsdig example.com(§8.3 — and the disagreement diagnostic) - The service itself?
ss -tlnpon the server side (listening? on the right address?); firewall (§8.4); thencurl -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
Map your machine.
ip addrandip 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.Identify your manager. Is it NetworkManager or networkd? (
systemctl status NetworkManager systemd-networkd— one will be active.) Runsystemctl statuson the winner and read it with Module 7 eyes; skimjournalctl -u <it> -band find the moment your interface got its address at boot (the DHCP lease lines).Trace the resolution chain. Read the
hosts:line of/etc/nsswitch.confand translate it.ls -l /etc/resolv.conf— file or symlink? If symlink:resolvectl statusfor the real upstreams. Then run bothgetent hosts example.comanddig example.comand confirm agreement.Poison and heal /etc/hosts. Add
127.0.0.1 example.comto/etc/hosts(sudo). Run the §8.3 pair again:getentnow returns 127.0.0.1 whiledigstill returns the real address — the disagreement diagnostic, demonstrated. Trycurl -v http://example.comand watch it connect to yourself and fail. Remove the line, verify healing. You will remember this the day a hosts-file mystery bites.Census the listeners.
sudo ss -tlnp. For every line: which process, which port, and — the important read —0.0.0.0/[::]vs127.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.Watch a socket be born. In one terminal:
python3 -m http.server 8080. In another: find it inss -tlnp, fetch from it (curl localhost:8080), see the established pair inss -tnp, thenCtrl-Cthe server (§5.4 — you know exactly what that sent) and confirm the listener is gone.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:
- Where does the TCP/IP stack run — and by which two syscall-and-fd facts does a userland program touch it?
- Read any
ip addr/ip routeoutput: interface names decoded, addresses, and how the kernel picks a route for a given packet. - What daemon manages your network config, and what's the Module-7 move when an interface has no address?
- Recite the full name-resolution chain — nsswitch, hosts file, resolv.conf, resolved — and explain what
getentvsdigdisagreement tells you. - Decode
ss -tlnpflag by flag, and explain0.0.0.0:80vs127.0.0.1:80for reachability. - Which two kernel rules govern binding (low ports; exclusivity), and which module's concepts do they belong to?
- 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