Module 13 — Networking
Updated 2 September 2026
A server that can't reach the network is just a warm brick. This module teaches you to see and diagnose a machine's networking from the ground up: its addresses, how it decides where to send packets, which ports are open, and how names become addresses. When "the service is up but nobody can reach it," these are the tools — and the mental model — that find the break in minutes instead of hours.
Legend used throughout: 🧠 concept → 🧩 analogy → 🧪 exercise → ✅ expected result (hidden) → 🎯 interview questions (hidden)
You need Modules Module 1 — What Linux Is–Module 12 — Storage, Disks, and Filesystems — especially processes and the ports they listen on (Module 8), services (Module 11: a "port" is a service listening), and /etc config files (Module 2). Tools: an Ubuntu 24.04 machine; ip and ss are built in, and we install dnsutils (for dig) in Part D. Read-only inspection (ip addr, ip route, ss, dig, reading /etc/resolv.conf) is safe anywhere. Firewall changes are marked — do those only where you won't lock yourself out. Your track already has dedicated DNS and SSL Certificates tracks — this module gives the working Linux-command view; those go deeper on the protocols.
Part A — Interfaces and addresses
A1. Network interfaces and the ip command
🧠 A machine talks to the network through interfaces — each a named connection point: lo (loopback, the machine talking to itself), eth0 or ens5 or enp0s3 (wired/virtual Ethernet — cloud VMs vary the name), wlan0 (wireless). The modern tool for all of it is ip (from the iproute2 package, Module 9): ip addr shows interfaces and their addresses, ip link shows the interfaces themselves (up/down, MAC address), ip -brief addr gives a clean one-line-per-interface summary. The old ifconfig you'll see in tutorials is deprecated — recognize it, but reach for ip.
Interfaces are a building's doors to different places: the front door to the street (eth0), a wireless side entrance (wlan0), and an internal door that just loops back into the same building's lobby (lo). Each door has an address so deliveries know where to go. ip addr is the directory of every door and its address.
Where the analogy stops working. A building's internal loop-door seems pointless — why walk out a door back into your own lobby? But lo is heavily used: it's the fast, private channel for programs on one machine to talk as if over the network, using the same tools, without exposure. And a door being present (interface up) doesn't mean it leads anywhere — an interface can be up with no route to the outside (Part B), the networking equivalent of a door that opens onto a bricked-up wall.
🧪 Exercise A1.1 — See the machine's interfaces (read-only, safe anywhere)
ip addr # full detail: interfaces and their addresses
ip -brief addr # the clean summary — one line per interface
ip link # the interfaces themselves (state, MAC address)✅ Expected result — click to reveal
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP 192.0.2.2/24(from ip -brief addr; ip addr shows the same with more detail. Your interface names and IPs differ — cloud VMs use ens5, enp1s0, etc.)
What to read out of it:
- lo with 127.0.0.1/8 — the loopback, always present. eth0 with 192.0.2.2/24 — the real interface and its address (the /24 is the network size, A2). 192.0.2.x is a documentation range; yours will be a real private or public IP.
- UP on eth0 means the link is active. An interface showing DOWN is your first suspect when a machine can't reach the network — before touching routing or DNS, confirm the interface is even up (ip link set eth0 up brings it up, but on a cloud VM that's usually managed for you).
- ip -brief is the operator's quick-look; full ip addr adds the broadcast address, scope, and lease details you need when things are actually broken.
A2. IP addresses, CIDR, and networks
🧠 An IP address is a machine's number on a network — 192.0.2.2 (IPv4, four bytes) or the longer IPv6 form (2001:db8::1). The /24 after it is CIDR notation: how many bits are the network part versus the host part. 192.0.2.2/24 means "the first 24 bits (192.0.2) identify the network; the last 8 bits (.2) identify this host on it" — so 192.0.2.0 through 192.0.2.255 are all on the same local network and can talk directly; anything else needs routing (Part B). Two ranges to recognize instantly: private addresses (10.x, 172.16–31.x, 192.168.x) that only exist inside a local network and never route on the public internet, and public addresses that do. This private/public split is why your laptop's 192.168.1.5 and a million other laptops' 192.168.1.5 don't collide — they're each private to their own network.
An IP address is a street address; the CIDR prefix is the postal district. Houses in the same district (192.0.2.0/24) can send mail directly hand-to-hand; mail to another district goes through the post office (the router/gateway). Private ranges are like internal office mail-stop numbers — "desk 192.168.1.5" is meaningful inside one building, and every building can reuse the same desk numbers because that mail never leaves the building.
Where the analogy stops working. Street addresses are globally unique; private IPs are deliberately not — the same 192.168.1.5 exists on millions of networks simultaneously, which works only because those packets never mix on the public internet (NAT, the address-translation at the boundary, is how a whole private network shares one public address — a Module-adjacent topic your DNS/networking tracks expand). The "address" metaphor breaks exactly where private addressing's cleverness lives: reuse without collision.
🧪 Exercise A2.1 — Read your addressing (read-only, safe anywhere)
ip -brief addr # note the /NN on each address
ip addr show eth0 # (use your real interface name from A1.1) — full detail for one interface✅ Expected result — click to reveal
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc pfifo_fast state UP ...
link/ether 02:fc:00:00:00:01 brd ff:ff:ff:ff:ff:ff
inet 192.0.2.2/24 brd 192.0.2.255 scope global eth0What to read out of it:
- inet 192.0.2.2/24 — the IPv4 address and its network size. /24 = 256 addresses on this local network (192.0.2.0–.255), of which .2 is this host.
- brd 192.0.2.255 is the broadcast address (the "everyone on this network" address); link/ether 02:fc:... is the MAC address — the interface's hardware-level ID, used for delivery within the local network (IPs are for the journey; MACs for the final local hop).
- mtu 1400 — the maximum packet size on this link. Usually 1500; a smaller MTU (common on cloud/VPN links, as here) that's mismatched somewhere causes a maddening class of bug where small requests work and large ones hang. Worth noting when "it works until the response is big."
Part A — Interview questions
🎯 "How do you check the IP address and network interfaces on a Linux system?" — asked verbatim in GeeksforGeeks' Linux Interview Questions (70+ questions, updated July 2026)
ip addr (or ip -brief addr for a summary) shows every interface and its IP addresses; ip link shows the interfaces and their state/MAC. The old ifconfig (from net-tools) does similar but is deprecated in favour of ip (from iproute2). To see just one interface: ip addr show eth0.
The details that separate candidates: reaching for ip over ifconfig and knowing why (net-tools is deprecated, ip is the maintained iproute2 tool); reading the output (the /NN CIDR, UP/DOWN state, loopback vs real interface); and the operational instinct — when a box is "off the network," ip -brief addr and ip link are the first checks (is the interface even up and addressed?) before blaming routing or DNS.
🎯 Corpus note — IP addressing and CIDR
The banks ask how to check addresses but rarely test understanding them — CIDR, private vs public ranges, loopback semantics — yet those are exactly what a real networking interview probes, and what you need to debug ("is this host even on the same network as the one it can't reach?"). Be ready to explain /24 from memory (network bits vs host bits, so same-prefix hosts talk directly), name the private ranges (10/8, 172.16/12, 192.168/16), and state the loopback trap (a service on 127.0.0.1 is unreachable remotely by design). That fluency turns a command-recall answer into a systems answer.
Part B — Routing and reachability
B1. Routes and the default gateway
🧠 An address gets a machine on a network; a route decides where to send each packet. The routing table (ip route) is a small list of rules: "packets for 192.0.2.0/24 — that's my local network, deliver directly"; "everything else — send to the default gateway." The default gateway (default via 192.0.2.1) is the router that forwards your packets toward the rest of the world; without a default route, a machine can talk to its own local network but nothing beyond it. This is the second thing to check when a box "can't reach the internet": it has an address (A1) but does it have a default route?
The routing table is the mailroom's sorting rules: "mail for this building — hand-deliver internally; mail for anywhere else — put it in the outgoing bin for the courier." The default gateway is that courier — the single exit through which everything not-local leaves. No courier arrangement (no default route), and internal mail flows fine while everything to the outside world piles up undelivered.
Where the analogy stops working. A mailroom clerk notices the outgoing bin overflowing and asks questions. A machine with no default route fails silently and specifically: local pings work, the machine seems "networked," but every connection to the outside times out — and the symptom (some things work, others don't) misleads people into blaming DNS or the remote server. The courier's absence is invisible until you read the routing table itself.
🧪 Exercise B1.1 — Read the routing table (read-only, safe anywhere)
ip route # the routing table
ip route get 8.8.8.8 # which route would a packet to 8.8.8.8 actually take?✅ Expected result — click to reveal
default via 192.0.2.1 dev eth0
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.2then ip route get shows the chosen route for that specific destination.
What to read out of it:
- Two rules, and every packet matches one. 192.0.2.0/24 dev eth0 — "my local network, deliver directly out eth0." default via 192.0.2.1 — "everything else, hand to the gateway 192.0.2.1." That gateway is the door to the wider world.
- ip route get 8.8.8.8 is the diagnostic gem: it tells you exactly which route and gateway a packet to a given destination would use — invaluable when a machine has multiple interfaces or VPNs and you need to know which way traffic actually goes. No guessing.
- Missing default line = the classic "local works, internet doesn't" state. Present but wrong gateway = traffic leaves but goes nowhere useful. Reading this table is a 5-second check that saves long detours into DNS.
B2. ping and traceroute — is it reachable?
🧠 ping host sends small probe packets and times the replies — the most basic "is it alive and reachable?" test. It tells you three things at once: whether the name resolved (Part D), whether packets get there and back, and the round-trip time. traceroute host (install traceroute) shows the path — every router hop between you and the destination — so you can see where connectivity breaks. But two caveats define ping's real usefulness: it uses ICMP, a protocol many firewalls and cloud providers block, so "ping fails" does not mean "the host is down" — plenty of perfectly healthy servers don't answer ping. It's a positive signal (a reply proves reachability) more than a negative one (no reply proves little).
ping is knocking on a shop's door to hear if anyone's inside. A knock-and-answer tells you the building is occupied and how fast they came to the door (latency). But it doesn't tell you the shop is open for business — the owner might answer the knock while the till is broken. And a shop with a "no soliciting, ignore knocks" policy (firewall blocking ICMP) is open and thriving while never answering your knock at all.
Where the analogy stops working. A person knocking uses judgment — they'd try the door handle, look in the window. ping does one rote thing and reports one bit. The skill is knowing what that bit does and doesn't mean, and reaching past it (traceroute for where it breaks, curl/ss for whether the service works) rather than concluding "ping failed, host is down" — a conclusion that's wrong often enough to be dangerous.
🧪 Exercise B2.1 — Probe reachability (needs normal internet; outputs shown are from a connected machine)
ping -c 3 8.8.8.8 # ping an IP directly (3 packets) — tests raw reachability, no DNS
ping -c 3 google.com # ping a NAME — also tests DNS resolution (Part D)
# traceroute google.com # (install: sudo apt install -y traceroute) — the path, hop by hop✅ Expected result — click to reveal
On a machine with normal connectivity:
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=117 time=8.42 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=117 time=8.11 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=117 time=8.30 ms
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 8.11/8.27/8.42/0.13 msWhat to read out of it:
- 0% packet loss and consistent time= values = healthy reachability with ~8ms latency. Rising or erratic times, or partial loss, point at a congested or flaky path.
- Pinging the IP vs the name is a deliberate two-step diagnosis: if ping 8.8.8.8 (no DNS needed) works but ping google.com fails, the network is fine and DNS is broken (Part D) — you've split the problem in half with two commands. This IP-then-name technique is the single most useful networking-debug reflex.
- In a locked-down environment (this authoring sandbox, many corporate networks, some clouds) ICMP is blocked, so you'd see 100% packet loss even though the machine reaches the internet fine via TCP — proof of the counter-intuition. On such a box, test with curl (Part C) instead of ping.
Part B — Interview questions
🎯 "How to check the default route and routing table?" — asked verbatim in Turing's 100+ Linux interview questions (2025)
ip route (or ip route show) prints the routing table; the line beginning default via <gateway> is the default route. ip route get <destination> shows which route a packet to a specific destination would actually take — the precise diagnostic. The legacy equivalents are route -n and netstat -rn. A missing default route is the classic "reaches the local network but not the internet" symptom.
The details that separate candidates: ip route get as the pinpoint tool (especially with multiple interfaces/VPNs) rather than just dumping the table; connecting a missing default route to its exact symptom; and knowing the routing table is consulted for every outbound packet — an address gets you on the network, a route decides where each packet goes, and both must be right.
🎯 Corpus note — ping and connectivity diagnosis
ping barely appears as a dedicated bank question, yet "walk me through debugging a machine that can't reach the internet" is one of the most common live networking interviews — and it's pure Part A+B: check the interface is up and addressed (ip addr), check there's a default route (ip route), ping the gateway, ping an external IP, then ping an external name to isolate DNS. Being able to narrate that ladder — each rung isolating a layer (link → address → route → reachability → DNS) — is exactly what the interviewer wants, and it's far more valuable than any single command. The IP-vs-name ping split (network vs DNS) is the star move.
Part C — Ports, sockets, and services
C1. Ports and the ss command
🧠 An IP address gets a packet to the machine; a port gets it to the right program on that machine. A port is a number (0–65535); a service listens on one (a web server on 80/443, SSH on 22, PostgreSQL on 5432), and a client connects to that port. The tool to see what's listening and connected is ss (socket statistics, the modern replacement for netstat). The command to memorize: ss -tulpn — tcp, udp, listening, processes (which program owns each port — needs sudo), numeric (don't resolve names, faster). It answers the two questions you'll ask constantly: "is my service actually listening?" and "what's using port X?"
The building has one street address (IP); inside, each department has a phone extension (port). Calling the main number gets you the building; dialing the extension reaches the right desk. ss is the switchboard operator's console: which extensions are staffed and ready to take calls (listening), and which are mid-conversation (established). A service on port 5432 is "the database department is at extension 5432, taking calls."
Where the analogy stops working. A phone extension rings at one desk. A listening socket has a subtlety no phone has — which doors it accepts calls through: 127.0.0.1 is an extension that only accepts internal calls from within the building, 0.0.0.0 accepts external calls too. The same extension number behaves completely differently depending on that binding, and the switchboard console (ss) shows it in the "Local Address" column — which is exactly the field beginners skip and seniors read first.
🧪 Exercise C1.1 — See what's listening (read-only; process names need sudo)
ss -tuln # listening TCP/UDP ports, numeric (no sudo needed)
sudo ss -tulpn # add the owning PROCESS for each port (the operator's full view)
ss -t state established # currently-open TCP connections✅ Expected result — click to reveal
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 4096 127.0.0.1:5432 0.0.0.0:*with sudo adding a Process column like users:(("sshd",pid=812,fd=3)).
What to read out of it:
- Read the Local Address:Port column first. 0.0.0.0:22 — SSH listening on all interfaces, reachable remotely (as it must be). 127.0.0.1:5432 — PostgreSQL listening on loopback only, reachable only from this machine. If a remote app can't reach that database, this line is the diagnosis — no packet capture needed.
- LISTEN = a service waiting for connections; the sudo version names the owning process (Module 8), so "what's using port 8080?" is one command. Peer Address:* on a listener means "will accept from any peer."
- Recv-Q/Send-Q on established connections show queued data — a persistently full queue can indicate a stuck or overwhelmed service. For now, the headline skill is reading listen-address-and-port fluently.
C2. curl and wget — talking to services
🧠 ping tests the host; curl tests the service. curl https://example.com fetches a URL; curl -I url fetches just the headers (is the web service responding, and with what status?); curl -v url shows the whole conversation — DNS, connection, TLS handshake, request, response — which makes it the single best web-debugging tool. It's how you answer "is the API actually up?" (not "does the host ping?"). wget is curl's cousin, better at downloading files (wget url saves the file); curl is better at inspecting and scripting HTTP. In DevOps, curl is the reflexive first test of any HTTP service, local or remote.
If ping was knocking on the shop door (B2), curl is walking in and actually trying to buy something. It exercises the whole transaction — find the shop (DNS), reach it (connect), verify credentials (TLS), make the request, get the goods (response). A successful curl means the service genuinely works, not just that the building is occupied.
Where the analogy stops working. A shopper gives up after one bad experience. curl reports precisely where the transaction failed — DNS lookup, TCP connect, TLS handshake, or an HTTP error code — each a different failure at a different layer, each pointing at a different fix. -v turns curl into a layer-by-layer diagnostic that a human shopper's "it didn't work" never provides. That structured failure reporting is why curl is a debugging instrument, not just a fetch tool.
🧪 Exercise C2.1 — Test a service, layer by layer (needs normal internet; canonical outputs shown)
curl -I https://example.com # just the headers — is it up? what status?
curl -s -o /dev/null -w "code=%{http_code} time=%{time_total}s\n" https://example.com # scriptable check
# curl -v https://example.com 2>&1 | head -20 # the full conversation for deep debugging✅ Expected result — click to reveal
On a connected machine:
HTTP/2 200
content-type: text/html; charset=UTF-8
...
code=200 time=0.183sWhat to read out of it:
- HTTP/2 200 — the service answered with status 200 (OK). The status code is the health signal: 200 good, 3xx redirect, 401/403 auth problem, 404 not found, 5xx the server is broken. curl -I is the fastest "is this HTTP service healthy?" test there is.
- The -w "%{http_code} ... %{time_total}" form prints just the code and timing — designed for scripts and monitoring (Module 10): a health-check script curls the endpoint and checks the code, exiting non-zero on failure. This one-liner is the skeleton of half the HTTP monitors in existence.
- If curl fails, how it fails localizes the problem: Could not resolve host = DNS (Part D); Connection refused = reached the host but nothing's listening on that port (check with ss, C1); Connection timed out = can't reach the host at all (routing/firewall, Part B); a TLS error = certificate problem (your SSL track). Four different failures, four different fixes — curl tells you which.
C3. Firewalls — controlling what gets through
🧠 A firewall controls which ports accept connections from where — the enforced version of "only these doors open, only to these people." Under the hood Linux uses netfilter (configured by iptables or the newer nftables); on Ubuntu, ufw (uncomplicated firewall) is the friendly front-end most people use: sudo ufw allow 22/tcp (permit SSH), sudo ufw allow 80,443/tcp (web), sudo ufw enable, sudo ufw status (see the rules). The security principle is default-deny: block everything, then open only the specific ports a service needs — so a machine exposes the minimum surface (Module 15's whole theme).
A firewall is the security desk deciding who gets in which door. Default-deny is "all doors locked; you get in only through doors you're explicitly cleared for." Adding a rule is issuing a pass for one door (port). It's the boundary between the wild street (the internet) and the offices inside.
Where the analogy stops working. A security guard who accidentally locks the CEO out will let them back in on sight. A firewall has no such judgment — enforce a lock-out on a remote server and there's no guard to recognize you and relent; the door is simply shut, from thousands of miles away, and only physical/console access (which cloud servers may not easily offer) reopens it. The absence of "the guard knows me" is exactly why firewall changes on remote machines demand the allow-yourself-first discipline that human security never needs.
🧪 Exercise C3.1 — Inspect firewall state (read-only status is safe; enabling rules is marked)
sudo ufw status verbose 2>/dev/null || echo "ufw not installed/active (common on minimal images/containers)"
# The SAFE ORDER if you ever enable it on a remote box (do NOT run enable on a box you could lock yourself out of):
# sudo ufw allow OpenSSH # allow your own access FIRST
# sudo ufw show added # confirm the rule is staged
# sudo ufw enable # only now enforce✅ Expected result — click to reveal
On a machine with ufw active:
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
To Action From
-- ------ ----
22/tcp (OpenSSH) ALLOW IN Anywhere
80,443/tcp ALLOW IN AnywhereOn a minimal image or container, ufw is often absent — the fallback message is a valid result.
What to read out of it:
- Default: deny (incoming) is the security posture — nothing gets in except the explicitly-allowed ports. The rules below are the only open doors: SSH and web. Everything else is refused at the door, before it ever reaches a service.
- Read this together with ss (C1): ss shows what's listening, ufw status shows what's reachable through the firewall. A service can be listening on 0.0.0.0 (open to all interfaces) yet blocked by the firewall — the two layers combine, and "the service is up and bound correctly but still unreachable" is often the firewall. Check both.
- The commented enable-sequence is the muscle memory to build: allow-yourself → confirm → enable, never enable-then-hope. On production, firewall changes go through the same care as any change that can cause an outage.
Part C — Interview questions
🎯 "How do you check open ports?" / "How to check which ports are listening?" — asked verbatim in GeeksforGeeks (2026, ss -tuln) and Turing (2025) respectively; Adaface (2024) asks "Describe how to use netstat or ss to find which process is listening on a specific port."
ss -tulpn (or the legacy netstat -tulpn): tcp + udp, listening, process, numeric — lists every listening port and the program that owns it (process needs sudo). For a specific port: sudo ss -tulpn | grep :5432 or sudo ss -tlpn 'sport = :5432'. To find and kill whatever holds a port: sudo ss -tlpn | grep :8080 for the PID, then kill (Module 8), or sudo fuser -k 8080/tcp.
The details that separate candidates: reading the listen address (0.0.0.0 reachable vs 127.0.0.1 local-only — the standout answer to "service is up but I can't connect"); ss over netstat and why (ss is the maintained iproute2 tool, faster on busy systems); and combining it with the firewall view (ufw status) since listening ≠ reachable — the two-layer check that solves the real incident.
🎯 "What is the curl command?" / "How can you configure a Linux firewall to allow or block specific traffic?" — asked verbatim in GeeksforGeeks (2026) and Turing (2025) respectively
curl transfers data to/from a URL — the reflexive tool for testing HTTP services and APIs: curl -I for headers/status, curl -v for the full DNS→connect→TLS→request→response trace, -w '%{http_code}' for scriptable health checks; how it fails (resolve/refused/timeout/TLS) localizes the problem by layer. Firewall: on Ubuntu, ufw over netfilter — sudo ufw default deny incoming, sudo ufw allow 22/tcp (and only the ports you need), sudo ufw enable, sudo ufw status; the principle is default-deny + least exposure, and the discipline is allow-your-own-access before enabling on a remote box.
The details that separate candidates: for curl, using it as a layered diagnostic (the four failure modes → four fixes) rather than just "it fetches URLs," and the difference from ping (service vs host); for firewalls, default-deny as the posture, ufw as the front-end over iptables/nftables, and the lock-yourself-out warning that signals real remote-server experience.
Part D — DNS: names to addresses
D1. How a name becomes an address
🧠 You type google.com; the machine needs 142.250.x.x. DNS (Domain Name System) is the lookup that translates names to IP addresses. On a Linux machine the resolution order is: first /etc/hosts (a local, hand-maintained name→IP file — checked before DNS), then the DNS servers listed in /etc/resolv.conf (or managed by systemd-resolved on modern Ubuntu). The tool to query DNS directly is dig (from dnsutils/bind9-dnsutils): dig name shows the full answer, dig +short name just the IP. Your track has a whole DNS track for the protocol depth; here you learn the Linux commands to see and debug resolution.
Resolving a name is looking up a phone number. Linux checks your personal contacts (/etc/hosts) first — if you've saved "Mum → a number," that wins, no matter what the public directory says. Only if it's not in your contacts does it call directory assistance (DNS). Your contacts are perfect for people you know and override; directory assistance handles everyone else.
Where the analogy stops working. A personal contact that's out of date, you know is yours — you'd suspect it. A stale /etc/hosts entry is invisible: every tool that shows "the number" might show your saved-but-wrong one, and you'd swear the directory is broken when it's your own contacts. And unlike a phone contact, a hosts entry affects every program on the machine silently — which is why "works here, breaks everywhere else" so often traces to a personal override nobody remembered was there.
🧪 Exercise D1.1 — Trace a name to an address (dig needs the dnsutils package; getent/hosts work anywhere)
cat /etc/resolv.conf # which DNS servers does this machine use?
cat /etc/hosts # the local overrides checked BEFORE DNS
sudo apt install -y dnsutils >/dev/null 2>&1 # for dig (Module 9)
dig +short example.com # just the IP(s) from DNS
getent hosts example.com # the ACTUAL resolution (hosts + DNS) the system would use✅ Expected result — click to reveal
nameserver 8.8.8.8
nameserver 8.8.4.4then /etc/hosts (localhost lines plus any overrides), then dig:
172.66.147.243(example.com's IP at the time of writing; yours may differ as sites move)
What to read out of it:
- /etc/resolv.conf lists the DNS servers queried — here Google's 8.8.8.8/8.8.4.4. If this file is empty or wrong, no name resolves while raw IPs still work — which is exactly the "ping 8.8.8.8 works, ping google.com fails" split from B2. DNS broken, network fine.
- dig +short returns just the address DNS gives — the fast "what does DNS say?" check. Full dig example.com (try it) shows the whole answer: the query, the ANSWER SECTION with the record and its TTL (how long it's cached), and which server answered — the detail you need when resolution is misbehaving.
- getent hosts returns what the system actually resolves (checking /etc/hosts first, then DNS) — so if dig and getent disagree, you've found a /etc/hosts override. That two-command comparison is the cleanest way to catch the counter-intuition's trap.
D2. Debugging DNS
🧠 DNS is behind a huge share of "the internet is broken" incidents (the sysadmin joke: "it's always DNS"). The debugging ladder, built from what you now know: 1. Does a raw IP work but a name doesn't? (ping 8.8.8.8 vs ping google.com, or curl an IP vs a name) — if yes, it's DNS, not the network. 2. cat /etc/resolv.conf — are there DNS servers listed, and are they reachable? 3. dig name — does DNS resolve it, and does it return the right IP? 4. getent hosts name vs dig name — a mismatch means an /etc/hosts override. 5. dig @8.8.8.8 name — query a specific public server to check whether it's your configured resolver that's broken versus DNS globally. Each rung isolates a layer, turning "DNS is broken" into a precise cause.
DNS problems are a courier who has the right city and roads (network fine) but the wrong translation of the name to a street address. The parcel never arrives, not because the roads are blocked, but because "the Smith residence" got looked up wrong. Debugging DNS is checking each step of the name-lookup: is the directory itself reachable, does it have the right entry, is someone's private note (/etc/hosts) overriding it?
Where the analogy stops working. A courier with a wrong address gets "no such place" and reports back. DNS failures are sneakier: a stale cached answer resolves to an IP that used to be right and now points at a decommissioned server, so the connection "succeeds" to the wrong place — no error, just wrong. The TTL (cache lifetime) dig shows is exactly this dimension the courier metaphor lacks: names resolve to answers that were true and quietly expire, and "why is it still going to the old server?" is a caching question, not a reachability one.
🧪 Exercise D2.1 — The DNS debugging ladder (dig needs dnsutils; the IP-vs-name logic works anywhere)
dig +short google.com # does DNS resolve it, and to what?
dig google.com | grep -A2 'ANSWER SECTION' # the answer with its TTL
dig @1.1.1.1 google.com +short # query Cloudflare's DNS directly — bypasses your resolver
getent hosts google.com # what the system actually resolves (hosts + DNS)✅ Expected result — click to reveal
142.250.190.14
;; ANSWER SECTION:
google.com. term IN A 142.250.190.14(the specific IP and TTL vary; the term above is the TTL in seconds, e.g. 300)
What to read out of it:
- dig @1.1.1.1 queries a specific server directly, sidestepping whatever /etc/resolv.conf points at. If your configured resolver fails but @1.1.1.1 works, the problem is your resolver config, not DNS — you've isolated it to the machine. This "ask a known-good server directly" move is the DNS-debug power tool.
- The TTL (the number before IN A) is how long this answer stays cached — relevant when a DNS record was changed and some machines still see the old IP: they're within the TTL window, caching the pre-change answer. "Why does one server still hit the old IP after we updated DNS?" is almost always TTL/caching.
- getent vs dig one more time: getent is what the system uses (the truth for actual connections), dig is what DNS alone says. When an app "can't find" a host that dig resolves fine, suspect the resolution path (nsswitch, systemd-resolved, an /etc/hosts line) between them — getent shows which answer actually wins.
Part D — Interview questions
🎯 The DNS diagnosis question — "a user reports a website won't load; how do you determine if it's DNS?" (a live networking staple; the banks cover the tools — dig, /etc/hosts, resolution order — inside broader networking questions rather than as one verbatim item)
Isolate the layer with the IP-vs-name split: if the site's raw IP loads (or ping/curl an IP works) but the name doesn't, it's DNS. Then walk it: cat /etc/resolv.conf (are resolvers configured and reachable?), dig name (does DNS answer, with the right IP?), dig @1.1.1.1 name (is it your resolver or DNS globally?), getent hosts name vs dig (an /etc/hosts override?), and check the TTL if a recently-changed record still resolves to an old IP (caching). Each step isolates a cause.
The details that separate candidates: the resolution order (/etc/hosts before DNS — and the override trap it creates); getent (system truth) vs dig (DNS only) as distinct tools; querying a specific resolver with dig @ to split "my config" from "DNS itself"; and TTL/caching as the reason changed records don't take effect everywhere at once. "It's always DNS" is a joke because this ladder so often ends there — showing you can run the ladder is the answer.
🎯 "What is the netstat command?" — asked verbatim in GeeksforGeeks' Linux Interview Questions (70+ questions, updated July 2026)
netstat displays network connections, routing tables, interface statistics, and listening ports — the classic all-in-one network inspector (netstat -tulpn for listening ports+processes, netstat -rn for routes). It's deprecated in favour of the iproute2 tools: ss replaces netstat for sockets/connections (faster, more capable on busy systems) and ip route replaces netstat -rn for routing. Recognize netstat in older docs and on legacy systems; reach for ss/ip on modern ones.
The details that separate candidates: naming the modern replacements and why (net-tools deprecated, iproute2 maintained — the same ip-over-ifconfig story as Part A); mapping the old flags to new tools (netstat -tulpn → ss -tulpn, netstat -rn → ip route); and not being caught out when a minimal image lacks netstat entirely (it's often not installed now) while ss is always there.
Part E — Toolkit
E1. Production practice — symptoms and fixes
| Symptom | What is really happening | What to run | The fix |
|---|---|---|---|
| Machine reaches its local network but not the internet | Missing or wrong default route | ip route (look for the default via line) | Add/fix the default gateway; on cloud VMs, check the network config |
| Service is running but remote clients get "connection refused" | Bound to 127.0.0.1 (loopback) instead of 0.0.0.0 | sudo ss -tulpn | grep :PORT — read the Local Address | Change the service's bind/listen address to 0.0.0.0 or the real interface |
| Service is listening on 0.0.0.0 but still unreachable remotely | Firewall blocking the port | sudo ufw status; check cloud security groups too | sudo ufw allow PORT/tcp (and the cloud firewall/security group) |
| ping name fails but ping 8.8.8.8 works | Network is fine; DNS is broken | cat /etc/resolv.conf; dig name; dig @1.1.1.1 name | Fix resolver config; if @1.1.1.1 works, it's your resolver not DNS |
| One machine reaches a different server than everyone else | An /etc/hosts override, invisible to DNS tools | getent hosts name vs dig name (compare); cat /etc/hosts | Remove/fix the stale hosts entry |
| ping fails but the service actually works fine | ICMP blocked by firewall — ping ≠ service health | curl -I the service instead of pinging the host | Nothing to fix; test services with curl/ss, not ping |
| Changed a DNS record but some clients still hit the old IP | Cached answer within its TTL | dig name — read the TTL | Wait out the TTL, or flush caches; lower TTL before planned changes |
E2. Capstone — four tickets
🎫 Ticket 1 — "The app server can't connect to the database, but the DB is running fine"
Ticket text: "vm-app-1 gets 'connection refused' connecting to Postgres on vm-db-1:5432. On vm-db-1, systemctl status postgresql shows it active and healthy. What's wrong?"
Worked answer — "connection refused" means the packet reached the host but nothing accepted it on that port (contrast "timed out" = didn't reach the host). Since Postgres is confirmed running, it's almost certainly bound to loopback. On vm-db-1: sudo ss -tulpn | grep 5432 — expect 127.0.0.1:5432, the smoking gun: Postgres is listening on loopback only, so it accepts connections from vm-db-1 itself but refuses vm-app-1 by design. Fix: set listen_addresses = '0.0.0.0' (or the specific internal IP) in postgresql.conf, add the client's network to pg_hba.conf (Postgres's own access control), and sudo systemctl restart postgresql (Module 11). Then verify the firewall isn't the next wall: sudo ufw status should allow 5432 from the app network (and check the cloud security group). Re-test from vm-app-1 with curl -v telnet://vm-db-1:5432 or nc -zv vm-db-1 5432. The one-line diagnosis to lead with: the service was healthy but listening on the wrong address — read the Local Address column, not just "is it up."
🎫 Ticket 2 — "Website down for our office, fine from home — is the site broken?"
Ticket text: "Everyone in the office reports acme-portal.com won't load; it loads fine from people's home connections and phones. Is the site down or is it us?"
Worked answer — "works from some places, not others" points at local config, not the site. Diagnose from an affected office machine with the isolation ladder: network vs DNS — curl -I https://<the-site's-IP> (get the IP from a working machine's dig) versus curl -I https://acme-portal.com; if the IP works but the name doesn't, it's DNS. Whose DNS — dig acme-portal.com (does the office resolver answer, and with what?) vs dig @1.1.1.1 acme-portal.com (a public resolver); if the public one returns the right IP and the office resolver doesn't (or returns a wrong/old one), the office DNS is the culprit. Overrides — getent hosts vs dig, and cat /etc/hosts, in case a deployment pushed a bad hosts entry to office machines. Most likely outcome: the office DNS resolver has a stale or broken record (or the office resolver itself is down), which is why home connections using different DNS are fine. Fix is on the office DNS/network side; the site is up. The framing that reassures leadership: "the site is healthy — the problem is our office's name resolution, isolated to these commands."
🎫 Ticket 3 — "New service deployed, health check passes locally, load balancer says it's down"
Ticket text: "We deployed api-svc on port 8080. curl localhost:8080/health on the box returns 200. But the load balancer marks it unhealthy and no traffic flows. Debug."
Worked answer — curl localhost:8080 succeeding proves the service works and is reachable via loopback — which tells you nothing about whether it's reachable from off the box, exactly where the load balancer sits. Check the bind address: sudo ss -tulpn | grep 8080 — if it shows 127.0.0.1:8080, the service listens on loopback only, so localhost works but the load balancer (a different machine) gets refused. That's the bug in most cases: fix the app's bind config to 0.0.0.0:8080 and restart. If it's already 0.0.0.0, climb the layers: firewall (sudo ufw status — is 8080 allowed from the LB's network?), cloud security group (the off-host firewall the OS can't see), and the health-check path/port the LB is configured to hit (is it checking :8080/health or a different port/path?). Reproduce the LB's exact check from another host: curl -I http://<this-box-IP>:8080/health. The lesson threaded through: localhost working is a loopback test, not a reachability test — the LB and the loopback are different network paths, and the whole bug lives in that gap.
🎫 Ticket 4 — "We're locked out of a server after a firewall change"
Ticket text: "An engineer ran ufw enable on a remote production box to 'tighten security' and now nobody can SSH in. There's cloud console access. Recover it and write the prevention rule."
Worked answer — the cause is textbook: ufw enable with default-deny and no rule allowing port 22 refused all new SSH connections — the engineer's live session may have limped on (established connections are permitted) but every reconnection, and everyone else, was locked out. Recover via the cloud provider's console/serial access (the out-of-band path that doesn't go through SSH): log in there and either sudo ufw allow OpenSSH (add the missing rule — SSH comes back immediately) or sudo ufw disable (turn the firewall off to restore access, then reconfigure properly). Prevention rule for the runbook, the discipline this module drills: always allow your own access before enabling enforcement — sudo ufw allow OpenSSH, confirm with sudo ufw show added, then sudo ufw enable; and on remote boxes, stage a self-recovering safety net first (a scheduled ufw disable in 10 minutes that you cancel once you've confirmed you're still in — Module 10's at/cron, or a systemd timer). Note this is the same shape as Module 4 (don't chmod away your own access) and Module 12 (don't fstab yourself unbootable): never enable an enforcement mechanism that can sever your own access without a tested escape hatch. The postmortem line: the firewall did exactly what it was told — the process failure was enabling enforcement before securing the operator's own path.
E3. Documentation reference
| Topic | Authoritative source | Verified link |
|---|---|---|
| Interfaces, addresses, routing | ip(8) | ip(8) |
| Reachability | ping(8) | ping(8) |
| Ports and sockets | ss(8) | ss(8) |
| Talking to services | curl(1) | curl(1) |
| Firewall | ufw(8) | ufw(8) |
| DNS | resolv.conf(5), dig(1) | resolv.conf(5) · dig(1) |
| Protocol depth (companion tracks) | Your DNS & SSL tracks | Untitled · Untitled |
E4. Self-assessment
Answer out loud, without notes. The section number tells you where to re-read.
- Name three network interfaces and what each is for. Why is lo critical despite never touching a wire? (A1)
- Decode 192.0.2.2/24: which part is network, which is host, and which addresses can it talk to directly? (A2)
- What is a default gateway, and what exact symptom appears when it's missing? (B1)
- Give two reasons "ping failed" does not mean "the host is down." (B2)
- The IP-vs-name ping split — what does each outcome tell you, and why is it the star debugging move? (B2, D2)
- In ss output, what's the difference between 0.0.0.0:5432 and 127.0.0.1:5432, and which incident does it cause? (C1)
- curl vs ping — what does each actually test, and how do curl's four failure modes localize a problem? (B2, C2)
- Default-deny firewall + remote server — what's the lock-out trap and the safe enable order? (C3)
- What is the resolution order for a name, and why is /etc/hosts both useful and a trap? (D1)
- getent hosts vs dig — what does each show, and what does a mismatch mean? (D1–D2)
- Walk the DNS debugging ladder from "a name won't resolve" to a precise cause. (D2)
- netstat is deprecated — what replaces it for sockets and for routes, and why? (D interview)
E5. Sources
GeeksforGeeks — Linux Interview Questions (70+) (updated July 2026) · Turing — 100+ Linux Interview Questions (2025) · Adaface — 96 Linux Commands interview questions (September 2024).
Corpus honesty note: the banks cover the commands — check IP/interfaces, open ports, routing table, curl, netstat, firewall — all quoted above. They under-ask the diagnostic reasoning — the IP-vs-name split, loopback-vs-0.0.0.0, "it's always DNS," the connectivity ladder — which is exactly what live networking interviews are built around ("a machine can't reach X, debug it"). This module teaches to that live format, because networking competence is tested by reasoning through a break, not reciting flags. Your dedicated DNS and SSL tracks carry the protocol theory this module deliberately keeps at working depth.
All documentation links were fetched and confirmed reachable on 2 September 2026 (dig/ufw via the Ubuntu manpage archive, as they're not on man7.org). the ip, ss, and dig command formats were generated on a live Ubuntu 24.04 system; the specific service examples shown — sshd on :22, postgres on :5432, and the curl/ping success outputs — are canonical illustrations from a machine running those services with normal connectivity, since this authoring sandbox runs different services and blocks outbound ICMP and external HTTP.