Linux: Network and Its Configuration
Table of Contents
- Networks, Packets and Layers
- IPv4 Addresses and Subnets
- Subnet Math (CIDR)
- Routing
- IPv6
- Basic ICMP and DNS Tools
- Name Resolution
- Transport Layer: TCP, UDP and Ports
- DHCP
- NetworkManager
- NAT
- Firewalls
- Cheat Sheet
1. Networks, Packets and Layers
A typical LAN
A local area network (LAN) connects hosts to each other. A router connects the LAN to other networks, such as the internet, through its uplink.
.───────────.
( Internet )
'─────┬─────'
LAN │ Uplink
│ │
▼ │
┌──────────────┬──────────────┬─────────────┐ │
│ │ │ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐ ┌───┴─────┴──┐
│ Host A │ │ Host B │ │ Host C │ │ Router │
└─────────┘ └─────────┘ └─────────┘ └────────────┘
Packets
Data travels in small chunks called packets. Each packet has:
- a header: who sent it, where it goes, which protocol, etc.
- a payload: the actual data.
Splitting data into packets lets many hosts share the same network and lets lost pieces be re-sent individually.
Network layers
Networking is split into layers. Each layer only talks to the layer directly above and below it.
| Layer (book / TCP/IP model) | OSI | What it does | Examples |
|---|---|---|---|
| Application | L7 | The “language” applications speak | HTTP, SSH, DNS, TLS |
| Transport | L4 | Data delivery between applications on two hosts (ports) | TCP, UDP |
| Network / Internet | L3 | Moving packets between hosts, across networks | IP, ICMP |
| Physical (+ link) | L1–L2 | Sending bits over a medium and frames on the local link | Ethernet, Wi-Fi, MAC addresses, ARP |
When data is sent, each layer wraps the data from the layer above with its own header (encapsulation). The receiver unwraps the headers in reverse order.
Application: ┌──────────────────┐
│ HTTP request │
└──────────────────┘
Transport: ┌────────────┬──────────────────┐
│ TCP header │ data │ segment
│ (ports) │ │
└────────────┴──────────────────┘
Network: ┌───────────┬────────────┬──────────────────┐
│ IP header │ TCP header │ data │ packet
│ (IP addrs)│ │ │
└───────────┴────────────┴──────────────────┘
Link: ┌──────────┬───────────┬────────────┬──────────────────┬─────┐
│ Ethernet │ IP header │ TCP header │ data │ FCS │ frame
│ (MACs) │ │ │ │ │
└──────────┴───────────┴────────────┴──────────────────┴─────┘
2. IPv4 Addresses and Subnets
Subnets
The internet’s topology is decentralized. It’s made up of smaller networks called subnets, all interconnected in some way. A LAN is normally a single subnet.
.───────────.
Subnet 10.23.2.0/24 (LAN) ( Internet )
│ '─────┬─────'
▼ │
┌───────────────┬────────────────┬─────────────┐ │
│ │ │ │ │
┌────┴──────┐ ┌────┴──────┐ ┌─────┴──────┐ ┌──┴──────┬┴───────┐
│ 10.23.2.4 │ │10.23.2.37 │ │10.23.2.132 │ │10.23.2.1│ Uplink │
├───────────┤ ├───────────┤ ├────────────┤ │ │ Address│
│ Host A │ │ Host B │ │ Host C │ ├─────────┴────────┤
└───────────┘ └───────────┘ └────────────┘ │ Router │
└──────────────────┘
The router has two addresses: one inside the LAN (10.23.2.1) and one on its uplink.
Viewing addresses
ip address show # short: ip a
ip -br address # brief, one line per interface
2: wlp0s20f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP ...
│ └─────────────┬─────────────────┘ └──┬───┘ └┬─┘
│ interface flags (UP = on) max packet size link is up
└─ interface name
link/ether 3c:58:c2:aa:bb:cc brd ff:ff:ff:ff:ff:ff
└──────┬────────┘
MAC address (layer 2)
inet 192.168.1.10/24 brd 192.168.1.255 scope global dynamic wlp0s20f3
└──────┬──────┘ └─────┬─────┘ └──┬──┘
IPv4 address/prefix broadcast assigned by DHCP
inet6 fe80::1a2b:3c4d:5e6f:7a8b/64 scope link
└────────────┬─────────────┘ └─┬──┘
IPv6 address link-local only
Special and private address ranges
| Range | Purpose |
|---|---|
10.0.0.0/8 | Private (RFC 1918) |
172.16.0.0/12 | Private (RFC 1918) |
192.168.0.0/16 | Private (RFC 1918), typical for home networks |
127.0.0.0/8 | Loopback (127.0.0.1 = this machine) |
169.254.0.0/16 | Link-local: self-assigned when DHCP fails |
100.64.0.0/10 | Carrier-grade NAT (also used by Tailscale) |
Private addresses are not routed on the internet. To get out, they need NAT (see section 11).
What the subnet mask is for
The subnet mask lets every device answer one question before it sends a packet: is the destination on my local network, or somewhere else?
An IPv4 address is 32 bits. The mask says how many of those bits identify the network and how many identify the host within it.
192.168.1.10/24 (mask 255.255.255.0)
11000000.10101000.00000001 . 00001010
└────────── 24 bits ─────┘ └─8 bits┘
network: 192.168.1 host: .10
How a host uses it
To reach another IP, the host ANDs both addresses with its mask and compares the results:
Me: 192.168.1.10 AND 255.255.255.0 = 192.168.1.0
Target: 192.168.1.50 AND 255.255.255.0 = 192.168.1.0 → same network
Target: 8.8.8.8 AND 255.255.255.0 = 8.8.8.0 → different network
Packet to send to IP X
│
▼
┌────────────────────────────────────┐
│ (my IP AND mask) == (X AND mask) ?│
└────────┬──────────────────┬────────┘
yes │ │ no
▼ ▼
┌─────────────────────────┐ ┌──────────────────────────┐
│ Same network │ │ Different network │
│ ARP: "who has X?" │ │ Send to default gateway │
│ → get X's MAC address │ │ (ARP for the router's │
│ → send frame directly │ │ MAC, not X's) │
│ via the switch │ │ → router forwards it │
└─────────────────────────┘ └──────────────────────────┘
Without a mask, a host couldn’t decide whether to ARP for the target directly or hand the packet to the router.
What else depends on the mask
- Network size and segmentation:
/24gives 254 usable hosts,/26gives 62,/16about 65k. This lets you split address space into separate subnets (servers, Wi-Fi, IoT, guests) that are isolated at L3 and routed or firewalled between each other. - Broadcast scope: the mask defines the broadcast address (e.g.
192.168.1.255), so broadcasts like ARP and DHCP stay inside the subnet. - Routing tables: routers match destinations by prefix (
10.0.0.0/8 → interface X). Longest-prefix match picks the most specific route.
What goes wrong if masks are mismatched
If one host has /24 and another on the same wire has /16, they can disagree about who is local. One side ARPs directly while the other sends via the gateway, which causes one-way or flaky connectivity. This is a classic source of confusing LAN bugs.
Kubernetes connection
k3s uses a pod CIDR (10.42.0.0/16) and a service CIDR (10.43.0.0/16) by default. These must not overlap with your LAN subnet. Otherwise the host can’t tell whether 10.x traffic should go to a pod or out to the network.
3. Subnet Math (CIDR)
Long form vs CIDR form
| Long form (mask) | CIDR |
|---|---|
255.0.0.0 | /8 |
255.240.0.0 | /12 |
255.255.0.0 | /16 |
255.255.255.0 | /24 |
255.255.255.192 | /26 |
The number after the slash is how many bits of the mask are 1s, counted from the left. An IPv4 mask is 32 bits, so the prefix ranges from /0 to /32.
From mask to prefix
Write each octet in binary and count the 1s:
255.255.255.0
11111111.11111111.11111111.00000000
8 + 8 + 8 + 0 = 24 → /24
255.255.0.0
11111111.11111111.00000000.00000000
8 + 8 + 0 + 0 = 16 → /16
A valid mask is always a solid block of 1s followed by a solid block of 0s. You never get 11110111.
Octet values to memorize
Only 9 values are possible for a single mask octet:
| Binary | Decimal | 1-bits |
|---|---|---|
00000000 | 0 | 0 |
10000000 | 128 | 1 |
11000000 | 192 | 2 |
11100000 | 224 | 3 |
11110000 | 240 | 4 |
11111000 | 248 | 5 |
11111100 | 252 | 6 |
11111110 | 254 | 7 |
11111111 | 255 | 8 |
So 255.255.255.192 is 8 + 8 + 8 + 2 = /26.
From prefix to mask
Take /20. That’s 20 ones: 8 + 8 + 4, then 0.
11111111 . 11111111 . 11110000 . 00000000
255 . 255 . 240 . 0 → 255.255.240.0
How many hosts fit
The leftover bits are host bits: 32 − prefix.
addresses = 2^(32 − prefix)
usable hosts = 2^(32 − prefix) − 2 (minus network and broadcast address)
| Prefix | Host bits | Addresses | Usable hosts |
|---|---|---|---|
/16 | 16 | 65,536 | 65,534 |
/24 | 8 | 256 | 254 |
/26 | 6 | 64 | 62 |
/30 | 2 | 4 | 2 |
/31 | 1 | 2 | 2 (point-to-point links, no broadcast) |
/32 | 0 | 1 | a single host |
Worked example: 192.168.1.77/26
- The mask is
255.255.255.192, so the last octet has 2 network bits and 6 host bits. - Block size = 256 − mask octet = 256 − 192 = 64. Subnets start at
.0,.64,.128,.192. - 77 falls into the
.64block.
.0 .64 .128 .192 .255
├───────────────┼───────────────┼───────────────┼───────────────┤
│ block 1 │ block 2 │ block 3 │ block 4 │
▲ ▲ ▲
│ │ └── .127 broadcast
│ └───────── .77 our host
└───────────────── .64 network address
Network: 192.168.1.64
Hosts: 192.168.1.65 – 192.168.1.126
Broadcast: 192.168.1.127
“256 minus the mask octet = block size” is the fastest way to do this in your head. Check your work with:
ipcalc 192.168.1.77/26
4. Routing
The routing table
ip route show # short: ip r
default via 192.168.1.1 dev wlp0s20f3 proto dhcp src 192.168.1.10 metric 600
└──┬──┘ └────┬────┘ └───┬───┘ └───┬───┘
│ gateway (router) interface lower = preferred
└─ matches everything not matched by a more specific route (0.0.0.0/0)
192.168.1.0/24 dev wlp0s20f3 proto kernel scope link src 192.168.1.10
└─────┬──────┘ └───┬────┘
local subnet directly reachable, no gateway needed
Each route says: “to reach destinations in this prefix, send packets out this interface, optionally via this gateway.”
Longest-prefix match
When several routes match, the most specific (longest prefix) wins:
Routes: Destination 10.42.0.15 matches:
default via 192.168.1.1 default (/0)
10.0.0.0/8 via 192.168.1.254 10.0.0.0/8 (/8)
10.42.0.0/24 dev cni0 10.42.0.0/24 (/24) ◄── wins
ip route get 8.8.8.8 # which route would be used for this destination?
Changing addresses and routes (temporary)
sudo ip address add 192.168.1.50/24 dev eth0 # add an address
sudo ip address del 192.168.1.50/24 dev eth0 # remove it
sudo ip link set eth0 up # bring interface up (down to disable)
sudo ip route add default via 192.168.1.1 dev eth0
sudo ip route del default
sudo ip route add 10.10.0.0/16 via 192.168.1.254 # static route to another subnet
ARP / neighbor table
ARP maps IP addresses to MAC addresses on the local network.
ip neigh show
# 192.168.1.1 dev wlp0s20f3 lladdr 9c:53:22:11:22:33 REACHABLE
Following the path
tracepath example.com # no root needed
traceroute example.com # classic tool
mtr example.com # continuous traceroute + ping
5. IPv6
| IPv4 | IPv6 | |
|---|---|---|
| Size | 32 bits | 128 bits |
| Notation | 192.168.1.10 | 2001:db8:0:1::10 (hex, :: = run of zeros) |
| Loopback | 127.0.0.1 | ::1 |
| Typical subnet | /24 | /64 |
| Local-only | private ranges + NAT | link-local fe80::/10 (every interface has one) |
| Address config | DHCP | SLAAC (auto from router advertisements) or DHCPv6 |
| ARP | ARP | Neighbor Discovery (NDP, via ICMPv6) |
ip -6 address show
ip -6 route show
Hosts often have several IPv6 addresses at once: link-local, global, and temporary “privacy” addresses.
6. Basic ICMP and DNS Tools
ping
ping sends ICMP echo requests and measures round-trip time and packet loss.
ping example.com
ping -c 4 example.com # stop after 4 packets
ping -4 example.com # force IPv4
ping -6 example.com # force IPv6
64 bytes from 93.184.215.14: icmp_seq=1 ttl=56 time=12.4 ms
│ │ └─ round-trip time
│ └─ hops left (TTL)
└─ gaps in sequence numbers = lost packets
No reply doesn’t always mean the host is down. Many firewalls block ICMP.
DNS lookups
host www.example.com # simple lookup
dig www.example.com # detailed DNS query
dig +short www.example.com # just the answer
dig @1.1.1.1 example.com # ask a specific DNS server
dig example.com MX # mail server records
dig -x 8.8.8.8 # reverse lookup (IP → name)
getent hosts example.com # resolve the way applications do (uses nsswitch)
dig and host query DNS directly. getent hosts follows the system resolution order, including /etc/hosts.
7. Name Resolution
How a hostname becomes an IP
Application calls getaddrinfo("example.com")
│
▼
┌──────────────────────────┐
│ /etc/nsswitch.conf │ hosts: files myhostname resolve [!UNAVAIL=return] dns
│ decides the ORDER │
└─────┬──────────────┬─────┘
1st │ │ then
▼ ▼
┌──────────────────┐ ┌──────────────────────────────┐
│ /etc/hosts │ │ DNS resolver │
│ static entries │ │ /etc/resolv.conf │
└──────────────────┘ │ → often 127.0.0.53 │
│ (systemd-resolved stub) │
└──────────────┬───────────────┘
▼
┌──────────────────────────────┐
│ DNS server (router, ISP, │
│ 1.1.1.1, …) from DHCP or │
│ manual config │
└──────────────────────────────┘
/etc/hosts
Static name-to-address mappings, checked before DNS (with the usual nsswitch order).
# Loopback entries; do not change.
# For historical reasons, localhost precedes localhost.localdomain:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
# See hosts(5) for proper format and other examples:
# 192.168.1.10 foo.example.org foo
# 192.168.1.13 bar.example.org bar
Format: IP canonical-name [aliases…]. Useful for local dev domains or homelab hosts without a DNS server.
/etc/resolv.conf
Tells the resolver which DNS servers to use:
nameserver 127.0.0.53
options edns0 trust-ad
search lan
nameserver: DNS server IP (up to 3).search: domains appended to short names (ping nas→nas.lan).
On systems with systemd-resolved (Fedora, Ubuntu), this file is usually a symlink pointing to the local stub 127.0.0.53. The real upstream servers are shown by:
resolvectl status # DNS servers per interface
resolvectl query example.com # resolve via systemd-resolved
resolvectl flush-caches # clear the DNS cache
/etc/nsswitch.conf
Controls the order of sources for name lookups: hosts, but also users (passwd), groups, etc.
hosts: files myhostname resolve [!UNAVAIL=return] dns
│ │ │ └─ classic DNS via resolv.conf
│ │ └─ systemd-resolved
│ └─ the machine's own hostname always resolves
└─ /etc/hosts first
8. Transport Layer: TCP, UDP and Ports
Ports
IP gets a packet to the right host. A port (0–65535) gets it to the right application on that host. A connection is identified by:
(protocol, source IP, source port, destination IP, destination port)
TCP, 192.168.1.10, 53122, 93.184.215.14, 443
| Range | Name | Notes |
|---|---|---|
| 0–1023 | Well-known | Need root to listen (22 SSH, 53 DNS, 80 HTTP, 443 HTTPS) |
| 1024–49151 | Registered | e.g. 5432 PostgreSQL, 6443 Kubernetes API |
| 49152–65535 | Ephemeral | Random source ports for outgoing connections (Linux uses 32768–60999) |
/etc/services maps port numbers to service names. That’s why tools can show ssh instead of 22.
grep -w 443 /etc/services
TCP vs UDP
| TCP | UDP | |
|---|---|---|
| Connection | Yes (handshake) | No |
| Reliability | Retransmits lost data, in order | Fire and forget |
| Overhead | Higher | Lower |
| Used by | HTTP, SSH, databases | DNS, DHCP, video/voice, QUIC (HTTP/3), WireGuard |
TCP three-way handshake:
Client Server (listening)
│ ──────── SYN ─────────────────► │
│ ◄─────── SYN-ACK ────────────── │
│ ──────── ACK ─────────────────► │
│ connection ESTABLISHED │
Inspecting connections: ss (and netstat)
netstat is deprecated on modern distros. ss replaces it with the same flags:
ss -nt # established TCP connections, numeric (same as netstat -nt)
ss -tlnp # listening TCP sockets + owning process (-p needs sudo for others)
ss -ulnp # listening UDP sockets
ss -tanp state established '( dport = :443 )' # filter
| Flag | Meaning |
|---|---|
-t / -u | TCP / UDP |
-l | Listening sockets only |
-a | All (listening + connected) |
-n | Numeric: don’t resolve names or port names |
-p | Show process |
A server bound to 127.0.0.1:8080 is only reachable locally. Bound to 0.0.0.0:8080 (or *:8080), it is reachable on all interfaces.
9. DHCP
DHCP (Dynamic Host Configuration Protocol) gives a host its IP address, subnet mask, default gateway and DNS servers automatically. The exchange is called DORA:
Client (no IP yet) DHCP server (usually the router)
│ ─── DISCOVER (broadcast) ──────────► │ "Is there a DHCP server?"
│ ◄── OFFER ────────────────────────── │ "You can have 192.168.1.10"
│ ─── REQUEST (broadcast) ───────────► │ "I'll take 192.168.1.10"
│ ◄── ACK ──────────────────────────── │ "Confirmed, lease: 24h,
│ │ gateway .1, DNS .1"
- Addresses are leased for a set time. The client renews the lease before it expires.
- Because DISCOVER is a broadcast, DHCP only works within one subnet unless a router runs a DHCP relay.
- If DHCP fails, a host may self-assign a
169.254.x.xlink-local address. - On desktops, NetworkManager handles DHCP itself. Older systems use
dhclient.
10. NetworkManager
NetworkManager is a daemon started at boot. Like most daemons, it doesn’t depend on a desktop. It listens to events from the system and users (cable plugged in, Wi-Fi available, VPN started) and changes the network configuration based on its rules. It stores configuration persistently, unlike ip.
Key terms:
- Device: a network interface (
eth0,wlp0s20f3). - Connection (profile): a saved configuration that can be applied to a device (IP settings, Wi-Fi password, DNS).
nmcli # overview of all devices
nmcli device status # devices and their state
nmcli connection show # saved connection profiles
nmcli connection show --active
nmcli device wifi list # nearby Wi-Fi networks
nmcli device wifi connect "SSID" --ask # connect, prompt for password
nmcli connection up "Home"
nmcli connection down "Home"
nmcli general hostname # show hostname
Set a static IP (persistent):
sudo nmcli connection modify "Wired connection 1" \
ipv4.method manual \
ipv4.addresses 192.168.1.50/24 \
ipv4.gateway 192.168.1.1 \
ipv4.dns "1.1.1.1 9.9.9.9"
sudo nmcli connection up "Wired connection 1"
Switch back to DHCP: ipv4.method auto.
On Fedora, profiles are stored as keyfiles in /etc/NetworkManager/system-connections/. nmtui offers a simple text-menu interface.
11. NAT
NAT (Network Address Translation) lets many hosts with private addresses share one public address. The router rewrites the source address and port of outgoing packets and remembers the mapping so replies can be sent back.
LAN (private) Router (NAT) Internet
┌────────────────────┐
192.168.1.10:53122 ────────► │ 192.168.1.1 │
→ 93.184.215.14:443 │ │ src rewritten to
│ NAT table: │ 203.0.113.7:40001
192.168.1.11:53122 ────────► │ .10:53122 ↔ :40001 │ ──────────────────► 93.184.215.14:443
→ 93.184.215.14:443 │ .11:53122 ↔ :40002 │ 203.0.113.7:40002
│ 203.0.113.7 │ ◄────────────────── replies to :40001
└────────────────────┘ → back to .10:53122
- Masquerading (source NAT) is the outgoing case above. Hosts inside can start connections out, but outsiders can’t start connections in.
- Port forwarding (destination NAT) is the reverse:
public:443 → 192.168.1.20:443. It exposes one internal service. - A Linux machine acts as a NAT router with IP forwarding enabled (
sysctl net.ipv4.ip_forward=1) plus a masquerade rule. Container runtimes and Kubernetes do exactly this for pod and container traffic.
12. Firewalls
The Linux kernel filters packets with netfilter. Its modern rule interface is nftables, which replaces iptables. The tools below are front-ends that write those rules for you.
┌──────────────┐ ┌────────────────┐
│ ufw │ │ firewalld │ friendly front-ends
│ (Ubuntu) │ │ (Fedora, RHEL) │
└──────┬───────┘ └───────┬────────┘
└─────────┬─────────┘
▼
┌───────────────────┐
│ nftables /iptables│ rule sets
└─────────┬─────────┘
▼
┌───────────────────┐
│ netfilter (kernel)│ filters every packet
└───────────────────┘
Use one front-end per machine. Mixing them leads to conflicting rules.
firewalld (Fedora / RHEL)
firewalld uses zones (e.g. public, home, trusted), each with its own rules. Interfaces and source networks are assigned to zones.
sudo firewall-cmd --state
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all # rules in the default zone
sudo firewall-cmd --add-service=http --permanent # allow a known service
sudo firewall-cmd --add-port=8080/tcp --permanent # allow a port
sudo firewall-cmd --remove-port=8080/tcp --permanent
sudo firewall-cmd --reload # apply --permanent changes
Without --permanent, a change is active immediately but lost at reload/reboot. With --permanent, it’s saved but only applied after --reload.
k3s note: the k3s docs recommend either disabling firewalld or trusting the pod and service networks, e.g.
firewall-cmd --permanent --zone=trusted --add-source=10.42.0.0/16and the same for10.43.0.0/16, plus opening6443/tcpfor the API server.
ufw (Ubuntu / Debian)
sudo ufw status verbose
sudo ufw allow 22/tcp # allow SSH before enabling!
sudo ufw allow from 192.168.1.0/24 to any port 5432
sudo ufw deny 23
sudo ufw enable
sudo ufw delete allow 22/tcp
⚠️ On a remote machine, always allow SSH before enabling a firewall, or you’ll lock yourself out.
13. Cheat Sheet
| Task | Command |
|---|---|
| Show addresses | ip a, ip -br a |
| Show IPv6 addresses | ip -6 address show |
| Show routes | ip r, ip -6 route show |
| Which route for a destination | ip route get 8.8.8.8 |
| Add address (temporary) | sudo ip address add 192.168.1.50/24 dev eth0 |
| Set default route (temporary) | sudo ip route add default via 192.168.1.1 dev eth0 |
| Remove default route | sudo ip route del default |
| ARP / neighbor table | ip neigh |
| Subnet calculator | ipcalc 192.168.1.77/26 |
| Test reachability | ping -c 4 host, ping -4 / ping -6 |
| Trace the path | tracepath host, mtr host |
| DNS lookup | host name, dig +short name |
| Resolve like applications do | getent hosts name |
| DNS servers in use | resolvectl status |
| Listening ports | sudo ss -tlnp |
| Active TCP connections | ss -nt (old: netstat -nt) |
| Port ↔ service name | /etc/services |
| NetworkManager overview | nmcli, nmcli device status |
| Connect to Wi-Fi | nmcli device wifi connect "SSID" --ask |
| Static IP (persistent) | nmcli connection modify … ipv4.method manual … |
| Firewall (Fedora) | sudo firewall-cmd --list-all |
| Firewall (Ubuntu) | sudo ufw status verbose |
Key files:
| File | Purpose |
|---|---|
/etc/hosts | Static hostname → IP mappings |
/etc/resolv.conf | DNS servers and search domains |
/etc/nsswitch.conf | Order of name lookup sources |
/etc/services | Port numbers ↔ service names |
/etc/NetworkManager/system-connections/ | Saved NetworkManager profiles |