Networking ๐Ÿ“– 19 min read

Networking Fundamentals

Subnet masks get copied from forum posts into configs all the time without anyone knowing what /24 means, and it usually works, until it doesn't: containers end up on the wrong range, two machines a few centimetres apart can't ping each other, and nobody knows where to start looking. This guide explains the handful of ideas behind almost every home and small-office network (addresses, subnets, gateways, NAT, DNS and ports) and then turns them into a troubleshooting order you can follow with the commands on this page.

To Follow Along

  • Hardware: A computer on your network; a second device makes the tests more useful
  • Software: A Linux terminal (the commands use iproute2's ip and ss, dig from the dnsutils package and nc, as found on Ubuntu 24.04 and Debian 12/13); macOS and Windows equivalents are noted. Access to your router's admin page helps but isn't required.
  • Time: 30 to 60 minutes

Underneath all the acronyms, a network has one job: get a packet from one machine to another. Addresses say where the packet should go, routes say which way to send it, and DNS turns the names people type into addresses.

None of these ideas is hard on its own. The confusion comes from how they stack: when something breaks low down, the symptom shows up at the top, and you end up debugging a web app when the real problem is a bad cable.

IP Addresses Explained

An IPv4 address such as 192.168.1.100 is four numbers separated by dots. Each number ranges from 0 to 255 because it's 8 bits: the whole address is 32 bits, written as four decimal "octets".

That gives roughly 4.3 billion combinations, which sounded like plenty when IPv4 was standardised in 1981 and is nowhere near enough now. IPv6 fixes this with 128-bit addresses, and many ISPs and mobile networks already use it, but home LANs, labs and most internal networks still revolve around IPv4. This guide stays there.

Private vs Public Addresses

Three ranges are set aside for private networks by RFC 1918, and they're worth knowing by heart:

  • 10.0.0.0 to 10.255.255.255 (10.0.0.0/8)
  • 172.16.0.0 to 172.31.255.255 (172.16.0.0/12)
  • 192.168.0.0 to 192.168.255.255 (192.168.0.0/16)

None of these are routed on the public internet. Anyone can use them inside their own network, which is why every home router hands out 192.168.x.x or 10.x.x.x addresses. Your ISP typically gives your router one public IPv4 address, and the router performs NAT (Network Address Translation) so every device in the house can share it.

Your phone wants to load a webpage. It sends the request from 192.168.1.50 to the router. The router swaps that private source address for its public one (in the examples here, 203.0.113.15, an address from a range reserved for documentation) and sends the request out. When the response comes back, the router looks up which internal device and port that connection belongs to and forwards it there. The diagram in How a Request Leaves Your Network shows the whole path.

Subnet Masks: What the /24 Means

You'll see notation like 192.168.1.0/24 everywhere. It's CIDR notation (Classless Inter-Domain Routing, defined in RFC 4632), and the number after the slash is the prefix length.

What it means: the /24 says "the first 24 bits of this address identify the network." The remaining 8 bits identify individual devices on that network. With a /24, that lines up neatly with the dots: the first three numbers are the neighborhood, and the last number is the house. The same idea written as a dotted mask is 255.255.255.0: 24 one-bits followed by 8 zero-bits.

Diagram: how 192.168.1.0/24 splits into network and host bits The address 192.168.1.0/24 is shown as four octets. The first three octets, 192, 168 and 1, are 11000000, 10101000 and 00000001 in binary and form the 24 network bits, matching the mask 255.255.255.0. The last octet is the 8 host bits. Those 8 bits give 256 values: 192.168.1.0 is the network address, 192.168.1.255 is the broadcast address, and 192.168.1.1 through 192.168.1.254 are the 254 usable host addresses. 192.168.1.0/24 prefix length 24 ยท mask 255.255.255.0 192 168 1 0 โ€“ 255 11000000 10101000 00000001 hhhhhhhh mask 11111111 (255) mask 11111111 (255) mask 11111111 (255) mask 00000000 (0) Network part: 24 bits, identical for every device on this subnet Host part: 8 bits = 256 values 192.168.1.0 network address (host bits all 0) 192.168.1.1 โ€“ 192.168.1.254 254 usable host addresses 192.168.1.255 broadcast (host bits all 1)
Diagram: the page's example subnet, 192.168.1.0/24, split into network and host bits.

192.168.1.0/24 breaks down like this:

  • Network: 192.168.1.x
  • Available hosts: 192.168.1.1 through 192.168.1.254
  • 254 usable addresses total: .0 is the network address and .255 is the broadcast address

The general rule: a prefix of length n leaves 32 โˆ’ n host bits, so 232โˆ’n addresses, minus 2 for the network and broadcast addresses. Cloud providers reserve a few more; AWS keeps five per subnet, as the 3-tier VPC guide notes.

Common Subnet Sizes

CIDR Subnet Mask Usable Hosts Use Case
/24 255.255.255.0 254 Home networks, homelabs, small offices: the usual default
/25 255.255.255.128 126 Splitting a /24 in half, for example for two VLANs
/16 255.255.0.0 65,534 Corporate networks, cloud VPCs

For a home network or a small lab, a /24 per network is plenty and keeps the arithmetic easy. Elaborate subnetting schemes rarely pay off for a handful of devices. Where more structure helps is separating traffic you don't want mixed (IoT devices, guests, servers), which is what VLANs are for; the OpenWrt guide and Linux Router Setup show how a router serves several subnets.

How Devices Find Each Other

Same Network (Direct Communication)

Two devices on the same subnet talk directly. No router involved. Device A broadcasts an ARP request ("who has 192.168.1.50?"), Device B answers with its MAC address, and from then on they send Ethernet frames straight to each other. Each machine keeps the answers in its neighbour (ARP) cache for a while, which you can see with ip neigh.

Different Networks (Routing)

Different subnet? The packet has to go through a router. Your machine compares the destination IP with its own address and prefix, sees it's not local, and sends the packet to its default gateway instead. The gateway (often 192.168.1.1 on home networks) decides where to forward it next. ip route shows your routing table; the line starting with default via is the gateway.

If your default gateway is wrong or missing, nothing outside your local subnet works, while everything on the subnet still does. That pattern is a strong hint. Likewise, if two machines have addresses in different subnets (say a /24 typo puts one on 192.168.2.x), they won't talk directly even when they're plugged into the same switch.

How a Request Leaves Your Network

Putting addresses, the gateway, NAT and DNS together, this is what happens when a laptop on the example network opens a website:

Diagram: path of a web request from a LAN device through the home router's NAT to DNS and a web server On the left is the home LAN, 192.168.1.0/24, with a laptop at 192.168.1.50. In the middle is the home router: its LAN side is 192.168.1.1, the default gateway, which also hands out addresses by DHCP and often forwards DNS; its WAN side has the public address 203.0.113.15 and performs NAT. On the right is the internet, with a DNS resolver and a web server, www.example.com at 198.51.100.20. Step 1: the laptop asks for the address of www.example.com, and the query goes through the router to the resolver. Step 2: the resolver answers 198.51.100.20. Step 3: the laptop sends the HTTPS request from 192.168.1.50 port 51515 to the router. Step 4: the router rewrites the source to 203.0.113.15 port 40001 and forwards it to 198.51.100.20 port 443. Step 5: the reply comes back to 203.0.113.15 port 40001, and the router uses its NAT table to send it to 192.168.1.50 port 51515. All addresses and ports are examples. Home LAN ยท 192.168.1.0/24 Laptop 192.168.1.50 gateway 192.168.1.1 DNS server from DHCP Home router LAN side: 192.168.1.1 default gateway ยท DHCP ยท DNS forwarder NAT table WAN side: 203.0.113.15 public address from the ISP Internet DNS resolver ISP's, or a public one www.example.com 198.51.100.20 : 443 1 1 2 3 4 5 1 Laptop asks "address of www.example.com?" via the router to a resolver. 2 Answer: 198.51.100.20. 3 HTTPS request leaves the laptop: from 192.168.1.50:51515 to 198.51.100.20:443, sent to the gateway. 4 Router rewrites the source to 203.0.113.15:40001, records the mapping in its NAT table, and forwards it. 5 Reply returns to 203.0.113.15:40001; the NAT table maps it back to 192.168.1.50:51515. Example addresses (203.0.113.0/24 and 198.51.100.0/24 are reserved for documentation) and example port numbers.
Diagram: a LAN device's request going through the default gateway, NAT and DNS.

Two consequences of NAT are worth knowing. First, devices on the internet can't open connections to your laptop, because the router has no NAT entry telling it where unsolicited traffic should go; that's what port forwarding adds. Second, some ISPs put customers behind their own carrier-grade NAT, in which case the router's "public" WAN address isn't public either, and port forwarding can't work. For reaching home from outside in either case, a VPN is the usual answer (see WireGuard Cloud Deployment).

DNS: Turning Names into Addresses

This section is the longest in the guide because DNS problems are so easy to mistake for something else.

Captured terminal output: Resolving a name
getent asks the system resolver, so it shows what applications actually get back. Captured on Ubuntu 26.04.1 under WSL 2.

The basic idea: nobody types an IP address into a browser. You type example.com, and something has to translate that name into an IP address before any connection happens. That something is DNS.

The lookup chain goes like this:

  1. Your browser checks its own cache. Already resolved this domain recently? Use that.
  2. Cache miss. Ask the OS resolver. On Linux, /etc/resolv.conf says which DNS server to query; on Ubuntu and other systems running systemd-resolved, it points at the local stub 127.0.0.53, and resolvectl status shows the real upstream servers.
  3. The configured DNS server (your router, a public resolver, or a Pi-hole) either has the answer cached or does a recursive lookup: root servers, then TLD servers, then the authoritative nameserver for that domain.
  4. Answer comes back. Browser gets the IP. Connection proceeds.

Usually that's fast enough that you never notice it. When it fails, everything stalls. Web pages won't load. APIs time out. Docker containers can't pull images. apt update fails. And the error messages rarely say "DNS failure": you get "could not resolve host" if you're lucky, or "connection timed out", or a silent hang.

Working connectivity doesn't help if DNS is down. ping 8.8.8.8 works. ping example.com doesn't. That gap points at name resolution.

Caching causes the other common surprise. You update a DNS record, but the old answer is cached at several levels: your browser, your OS, your upstream resolver. The record's TTL says how long caches may keep it, so lowering the TTL a while before a planned change makes the switch faster. Flushing your local cache only fixes one layer. Running your own filtering resolver is covered in the Pi-hole Deployment Guide.

Testing DNS

# Look up a domain
nslookup example.com

# Or with dig (more detailed)
dig example.com

# Test a specific DNS server
dig @8.8.8.8 example.com

# Check what your system is actually using
cat /etc/resolv.conf
resolvectl status          # on systems with systemd-resolved

# Flush DNS cache on Linux (systemd-resolved)
sudo resolvectl flush-caches

# Flush on macOS
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder

A useful habit: if something network-related breaks, run dig early. If dig @8.8.8.8 example.com works but dig example.com doesn't, your local DNS server or config is the issue. If neither works, the problem is outbound connectivity, or the domain itself. In dig's output, the status: field in the header (NOERROR, NXDOMAIN, SERVFAIL) and the SERVER: line near the bottom tell you what was answered and by whom.

One more thing. Containers often resolve names differently from their host. On a user-defined Docker network, containers use Docker's embedded DNS server at 127.0.0.11, which also resolves other containers by name; on the default bridge network they get a copy of the host's resolver settings. Kubernetes uses its own cluster DNS. When a container can't resolve hostnames but the host machine can, check the container's /etc/resolv.conf first.

Ports: Addressing Applications

IP gets you to the machine. Port gets you to the application running on it. Think of the IP as the building address and the port as the apartment number.

Captured terminal output: Listening sockets
Listening sockets. The 127.0.0.53 entries are systemd-resolved's local DNS stub. Captured on Ubuntu 26.04.1 under WSL 2.

The ports you'll actually encounter:

  • 22 - SSH
  • 80 - HTTP
  • 443 - HTTPS
  • 53 - DNS
  • 3306 - MySQL
  • 5432 - PostgreSQL

Notation like 192.168.1.100:8080 means "port 8080 on that machine." Your browser, when connecting to a web server, uses a temporary high-numbered (ephemeral) port on your end and connects to 443 on the server's end. You only see your side's port number in tools like ss or packet captures.

Checking Port Connectivity

# Quick check โ€” is something listening on this port?
nc -zv 192.168.1.100 80

# Telnet works too (old school but reliable)
telnet 192.168.1.100 80

# PowerShell on Windows
Test-NetConnection -ComputerName 192.168.1.100 -Port 80

How it fails tells you something: "Connection refused" comes back immediately and means the host answered but nothing listens on that port; a long wait followed by a timeout means something (usually a firewall) dropped the packets.

DHCP: Automatic IP Assignment

Plug a device into a network and it doesn't magically have an address. It broadcasts a DHCP request, basically "someone give me an IP." A DHCP server, usually your router, responds with an available address plus the gateway and DNS server to use.

Device: "I need an IP."
DHCP Server: "Take 192.168.1.50. Gateway is 192.168.1.1. DNS is 192.168.1.1. Lease lasts 24 hours." (The lease time is whatever the server is configured with.)

That lease part matters. DHCP addresses aren't permanent. They expire and get renewed. For most client devices (laptops, phones) this is fine. For servers, you want an address that never changes: either a static IP configured on the machine (outside the DHCP pool) or a DHCP reservation on the router that always hands that machine the same address. Otherwise your database server can end up on a new address after a lease runs out, and everything pointing at the old one breaks.

Key Troubleshooting Commands

Captured terminal output: Your address and default gateway
The machine's address and its default gateway, here on a WSL 2 virtual network. Captured on Ubuntu 26.04.1 under WSL 2.
Captured terminal output: Testing reachability with ping
Three replies and 0% packet loss: the path to 1.1.1.1 works. Captured on Ubuntu 26.04.1 under WSL 2.

Check Your Own IP

# Linux (modern)
ip addr
ip route        # default gateway is the "default via" line

# Linux (legacy) or macOS
ifconfig

# Windows
ipconfig

On Linux, the ip(8) command replaces the older ifconfig, route and arp tools. In ip addr output, look for state UP on the interface and an inet line with an address and prefix such as 192.168.1.50/24. An address starting with 169.254. means the machine gave up waiting for DHCP and picked a link-local address itself.

Where same-subnet problems hide: ARP

Most guides say "ARP resolves IPs to MAC addresses" and move on. In practice, ARP is where same-subnet problems hide: two devices accidentally given the same IP address answer ARP requests in turn, so connections to that address work intermittently; a stale cache entry after you swap hardware sends traffic to a MAC that's no longer there. ip neigh lists the cache (entries marked FAILED or INCOMPLETE got no reply), and sudo ip neigh flush dev eth0 clears it for one interface. If you suspect an address conflict, arping -D -I eth0 192.168.1.50 (from the iputils package) checks whether another machine answers for that address.

Test Basic Connectivity

# Step 1: Can I reach my gateway?
ping 192.168.1.1

# Step 2: Can I reach something on the internet by IP?
ping 8.8.8.8

# Step 3: Can I resolve a hostname?
ping example.com

Run these in order. Step 1 fails? Local network problem: cable, Wi-Fi, VLAN, switch, or wrong address/prefix. Step 2 fails but 1 works? Routing, the router's internet connection, or a firewall. Step 3 fails but 2 works? DNS. (Some networks block ping, so a failed ping on its own isn't proof; confirm with the next steps.)

Trace the Route

# Linux/macOS
traceroute example.com

# Windows
tracert example.com

This lists the routers between you and the destination. When packets die somewhere in the middle (reaching your ISP but not beyond, for example), traceroute shows roughly where. Rows of * * * mean that hop didn't reply, which many routers are configured not to do, so look at where the trace stops making progress rather than at single silent hops.

Check What's Listening

# Linux
ss -tuln
sudo ss -tulnp   # also shows which process owns each socket

# macOS
netstat -an | grep LISTEN

# Windows
netstat -an | findstr LISTENING

This answers the question "is my application actually listening on the port I think it is?" Check the address column too: a service bound to 127.0.0.1:8080 only accepts connections from the same machine, while 0.0.0.0:8080 or [::]:8080 accepts them on every interface. ss(8) documents the filters, such as ss -tn state established.

The Layered Model (Quick Version)

The OSI model has seven layers. For everyday troubleshooting, five of them map onto concrete checks; the session and presentation layers rarely come up outside exams:

  • Physical (1) - Is the cable plugged in? Is the link light on? Is Wi-Fi associated? ip link shows whether the interface sees a carrier. Unglamorous, and a surprisingly common cause of "network outages".
  • Data Link (2) - MAC addresses, switches, VLANs. The layer where ARP lives.
  • Network (3) - IP addresses, routing. Can I ping it?
  • Transport (4) - TCP/UDP, port numbers. Is the port open?
  • Application (7) - HTTP, DNS, SSH. Is the service actually responding correctly?

Troubleshoot bottom-up. Start at the physical layer and work your way up to the application. Skipping ahead is how you end up reading application logs for a problem that lives two layers below.

Quick TCP vs UDP

TCP: connection-oriented, reliable and ordered, with retransmission when packets are lost. Used for web, SSH, file transfers. UDP: no connection and no delivery guarantees, so less overhead. Used for DNS queries, streaming, games and VPNs such as WireGuard. That's enough unless you're writing socket code. It also explains a common firewall mistake: allowing TCP 53 but not UDP 53 breaks most DNS.

VPNs and Tunneling

A VPN wraps your traffic in an encrypted tunnel. Your packets enter the tunnel on your device, travel across the internet in encrypted form, and emerge on the VPN server's end. From your machine's perspective, you're on the remote network. You get an IP on that network. You can reach internal resources as if you were sitting in the same building.

Practical uses: accessing your homelab from a coffee shop, connecting to a corporate network from home, or routing all your traffic through a trusted exit point on untrusted public Wi-Fi. WireGuard's configuration is much smaller than OpenVPN's, which makes self-hosting a VPN far more approachable; the WireGuard Cloud Deployment guide walks through a server on a VPS. Pick a VPN subnet that doesn't overlap the networks you connect from, or traffic for those addresses won't know which way to go.

Firewalls: Several Layers of Rules

A firewall is an ordered list of rules, such as "allow port 22 from 10.0.0.0/8, drop everything else".

The catch: there are usually multiple firewalls between you and your destination. The host firewall (nftables/iptables, ufw, Windows Defender Firewall). The router's firewall. Cloud security groups and network ACLs (the 3-tier VPC guide shows both). Any one of them can silently drop your packets with zero feedback. When a connection just hangs, with no error and no rejection, a firewall silently discarding the traffic is the most likely explanation; a rule that rejects instead gives you an immediate "connection refused" or "no route to host".

Troubleshooting Flow

Put together, this is an order that works for most "the network is down" reports. Each step only makes sense if the one before it passed:

  1. Is the link up? - ip link: the interface should be UP with LOWER_UP. If not: cable, port, Wi-Fi association, or a disabled interface.
  2. Do I have an IP in the right subnet? - ip addr: no address, or a 169.254.x.x one, points at DHCP; an address in the wrong subnet points at a static-config typo.
  3. Can I hit the gateway? - ip route to find it, then ping 192.168.1.1. Failing here with a correct address points at layer 2: switch, VLAN, ARP (ip neigh).
  4. Can I hit the internet by IP? - ping 8.8.8.8. Failing here points at the router's uplink, its NAT, or a firewall.
  5. Does DNS resolve? - dig example.com, then dig @8.8.8.8 example.com to separate your resolver from the internet.
  6. Can I reach the target machine? - ping TARGET_IP (remember some hosts block ping) or traceroute TARGET_IP.
  7. Is the target port open? - nc -zv TARGET_IP PORT: refused means nothing listening; timeout means a firewall in the way.
  8. Is the application running and listening? - on the target, sudo ss -tulnp and the application's logs.

The first four steps are quick, and they tell you whether the problem is on your machine, on your network, or further away. Jumping straight to step 8 means reading application logs while the real issue may be a gateway misconfiguration several layers below.

What's Next

Where to go from here depends on what you're building:

  • VLANs: segment your homelab into isolated networks, the natural next step if you're running multiple services. Building your own router with Linux Router Setup or OpenWrt puts all of this page's concepts (gateway, DHCP, NAT, DNS) in one box you control.
  • NAT internals: port forwarding, hairpin NAT, the details that matter once you expose services to the internet.
  • Cloud networking: the same ideas with different names. Subnets, route tables and gateways reappear in the 3-tier VPC guide.
  • IPv6: increasingly common on ISP and mobile networks, and worth learning even if your LAN is IPv4-only today.