IP Addressing & Subnets - Understanding CIDR, Masks and Network Math
Status: Active
Last Updated: 2026-08-14
Category: Networking - Phase 1: Network Fundamentals
Prerequisites: tcp-ip-fundamentals
Time: 3-4 hours
Tags: networking, subnetting, cidr, ipv4, ipv6, vlsm, addressing
Summary
Everything about IP addresses you need to design, read, and debug real networks: binary math behind subnet masks, CIDR notation, public vs private space, calculating networks/broadcasts/host counts by hand, VLSM for splitting subnets, planning address space for a homelab or small business, and IPv6 prefixes in practice. This is the lesson that turns "192.168.1.x works somehow" into "here is our addressing plan for the next five years."
๐ฏ What You'll Learn
By the end of this guide, you'll understand:
- โ How an IP address and its mask combine into network + host portions
- โ CIDR notation and how to convert between /24-style prefixes and masks
- โ Public vs private vs reserved address space
- โ Calculating network address, broadcast, first/last host, and total hosts โ by hand
- โ Splitting a subnet with VLSM to fit multiple networks of different sizes
- โ Planning a real homelab/small-office addressing scheme with VLANs
- โ Reading IPv6 prefixes without fear
Prerequisites: TCP/IP fundamentals (tcp-ip-fundamentals)
Time Investment: 3-4 hours + practice until the math becomes reflex
Table of Contents
- One Address, Two Meanings
- Binary Refresher (The Only Part You Need)
- Subnet Masks and Prefix Lengths
- The Four Questions (Network Math by Hand)
- CIDR Cheat Table
- Public vs Private vs Reserved Space
- Subnetting: Splitting a Network
- VLSM: Different Sizes for Different Needs
- A Real Addressing Plan
- IPv6 Prefixes in Practice
- Hands-On Exercises
- Common Gotchas
- Next Steps
๐ Related
One Address, Two Meanings
An IP address never travels alone โ it always carries an implicit or explicit mask that splits it:
192.168.1.50/24
โโโโโโโโโโโโ network โโโโโโโโโโโโ host โโ
11000000 . 10101000 . 00000001 . โโ00110010
192 . 168 . 1 . โโ 50
โ
mask = 255.255.255.0 (/24)
- Network portion: which neighborhood the machine lives in
- Host portion: which doorbell in that neighborhood
Two machines can talk directly (no router) only if their network portions are identical. That single sentence explains most home networking behavior:
# Same network โ ARP + direct delivery
192.168.1.50 โ 192.168.1.87 โ direct
# Different network โ must go through the gateway
192.168.1.50 โ 10.0.0.5 โ needs a router
Your machine makes this decision for every single packet: "is the destination in one of my local networks? Then deliver directly via ARP. Otherwise hand it to the default gateway." You saw this in ip route show in the previous lesson.
Binary Refresher (The Only Part You Need)
You don't need general binary arithmetic โ just how one byte (8 bits) maps to 0โ255:
| Bit position | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|---|---|---|---|---|---|---|---|---|
| Value if set | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
A byte is just which positions are switched on:
192 = 11000000 โ 128 + 64 = 192
168 = 10101000 โ 128 + 32 + 8 = 168
1 = 00000001 โ 1 = 1
50 = 00110010 โ 32 + 16 + 2 = 50
255 = 11111111 โ 128+64+32+16+8+4+2+1 = 255
And the reverse โ decimal to bits โ is subtracting powers of two from largest to smallest:
50 โ 32 fits (18 left), 16 fits (2 left), 2 fits (0 left)
โ 00110010
Practice this until 172 instantly reads as 10101100. Every subnetting calculation in this lesson is just counting these bits.
Subnet Masks and Prefix Lengths
A subnet mask marks where the network portion ends. It's always a contiguous run of 1s from the left, then all 0s:
/24 = 11111111.11111111.11111111.00000000 = 255.255.255.0
/26 = 11111111.11111111.11111111.11000000 = 255.255.255.192
If someone hands you 255.255.255.240, count the 1s: twenty-eight โ /28.
โ ๏ธ Masks like
255.0.255.0are invalid โ the 1s must be contiguous. Some old systems accepted them; modern kernels reject them. If you ever see one in a config, it's a typo or sabotage.
Converting Both Directions
Prefix โ Mask: fill 1s from the left, count to prefix, rest 0s.
/20 โ 11111111.11111111.11110000.00000000 โ 255.255.240.0
Mask โ Prefix: count the 255 octets ร8, then count 1s in the odd octet.
255.255.255.252 โ 8+8+8+2 = /30
You never have to do this under time pressure forever โ every OS will tell you (ip -brief addr) โ but reading /27 fluently is a daily skill when working with cloud VPCs, Kubernetes CNI config, and firewall rules.
The Four Questions
Given any address/prefix, there are four things you almost always want to know:
- What network is it on? (network address)
- What's the broadcast address?
- Which IPs can I actually give to hosts?
- How many hosts fit?
The Method
For prefix length P:
- Block size = 256 โ (mask value of the interesting octet)
- Network address = round your IP's octet down to the nearest multiple of block size
- Broadcast = network address + block size โ 1
- Usable hosts = 2^(host bits) โ 2 (network + broadcast reserved)
Worked Example: 192.168.1.130/26
/26 โ last octet mask = 192 โ block size = 256โ192 = 64
Networks in the last octet step by 64: 0, 64, 128, 192
130 falls in the 128-block:
Network: 192.168.1.128
Broadcast: 192.168.1.191 (128 + 64 โ 1)
Hosts: 192.168.1.129 โ 190 (62 usable)
Count: 2^6 โ 2 = 62
Verify yourself โ 130 is indeed between 129 and 190. This four-line procedure answers every subnetting exam question and, more importantly, every real-world "why can't these two machines talk" question.
Why โ2?
The all-zeros host bits form the network address (identifies the network itself โ routing tables point here), and all-ones form the broadcast (delivered to every host in the subnet). Neither can belong to a machine.
Modern footnote: on point-to-point links (/31, per RFC 3021) both addresses are usable because there's no broadcast domain of consequence. Linux happily uses
10.0.0.4/31on WAN links. But for LANs, stick to โ2.
CIDR Cheat Table
Memorize this table or tape it to your monitor. It compresses everything above:
| CIDR | Mask | Block size | Usable hosts | Typical use |
|---|---|---|---|---|
| /8 | 255.0.0.0 | 256 in 1st octet | 16,777,214 | Huge ISP/corp (10.0.0.0/8) |
| /12 | 255.240.0.0 | โ | 1,048,574 | Docker's 172.17 range |
| /16 | 255.255.0.0 | 256 in 3rd octet | 65,534 | Large site (192.168.0.0/16) |
| /20 | 255.255.240.0 | 16 in 3rd octet | 4,094 | Cloud VPC |
| /22 | 255.255.252.0 | 4 in 3rd octet | 1,022 | Medium office |
| /23 | 255.255.254.0 | 2 in 3rd octet | 510 | Small office |
| /24 | 255.255.255.0 | 1 in 4th octet | 254 | Classic LAN โ memorize cold |
| /25 | 255.255.255.128 | 128 | 126 | Half a /24 |
| /26 | 255.255.255.192 | 64 | 62 | Quarter of a /24 |
| /27 | 255.255.255.224 | 32 | 30 | Eighth of a /24 |
| /28 | 255.255.255.240 | 16 | 14 | DMZ / small VLAN |
| /29 | 255.255.255.248 | 8 | 6 | Tiny cluster |
| /30 | 255.255.255.252 | 4 | 2 | Point-to-point link |
| /31 | 255.255.255.254 | 2 | 2* | Modern p2p (RFC 3021) |
| /32 | 255.255.255.255 | 1 | 1 | Single host route |
Pattern worth seeing: each +1 to the prefix halves the size. /24=254, /25=126, /26=62, /27=30, /28=14, /29=6, /30=2. Halving chain โ no multiplication needed.
Public vs Private vs Reserved Space
Not all 4.3 billion IPv4 addresses are yours to use. IANA partitions them:
| Range | Class | Size | Routable on internet? | Who uses it |
|---|---|---|---|---|
0.0.0.0/8 |
Reserved | 16.7M | No | "Unspecified"/default routes |
10.0.0.0/8 |
Private | 16.7M | No | Corporations, big labs, cloud VPCs |
100.64.0.0/10 |
CGNAT | 4.2M | No | Carrier NAT (some ISPs hand these to you!) |
127.0.0.0/8 |
Loopback | 16.7M | No | Localhost |
169.254.0.0/16 |
Link-local | 65k | No | DHCP failure fallback, mDNS-ish |
172.16.0.0/12 |
Private | 1M | No | Cloud VPCs (AWS default), Docker |
192.0.2.0/24 |
Docs (TEST-NET-1) | 256 | No | Documentation examples |
192.88.99.0/24 |
Reserved | 256 | No | Legacy 6to4 relay |
192.168.0.0/16 |
Private | 65k | No | Home networks everywhere |
198.18.0.0/15 |
Benchmarking | 131k | No | Perf testing |
198.51.100.0/24 |
Docs (TEST-NET-2) | 256 | No | Documentation examples |
203.0.113.0/24 |
Docs (TEST-NET-3) | 256 | No | Documentation examples |
224.0.0.0/4 |
Multicast | 268M | Special | mDNS (224.0.0.251), OSPF (224.0.0.5) |
240.0.0.0/4 |
Reserved | 268M | No | Future use |
Notes that matter in practice:
- Documentation ranges (
192.0.2.x,198.51.100.x,203.0.113.x) are what you should use in docs, blog posts, and KB articles so examples can't collide with real networks. This course uses them deliberately. - CGNAT gotcha: some ISPs put customers behind
100.64.x.xโ you cannot port-forward through carrier NAT. If your "public IP" starts with 100.64, call your ISP or get a business line. - Everything not listed above (e.g.,
203.0.114.x) is public space owned by someone via regional registries. Using it internally invites bizarre bugs when a VPN peer actually owns that space.
Check Your Own Public IP
curl -4 ifconfig.me && echo
curl -6 ifconfig.me && echo
ip route get 1.1.1.1 # shows which src IP + interface would be used
Compare against ip addr: if they differ, you're behind NAT (you are, unless you're running BGP).
Subnetting: Splitting a Network
Now the skill itself: taking one network and cutting it into pieces.
Example: Split 192.168.1.0/24 into 4 equal subnets
Need 4 subnets โ 2 extra bits (2ยฒ = 4). New prefix = /24 + 2 = /26.
Subnet 1: 192.168.1.0/26 hosts .1 โ .62 broadcast .63
Subnet 2: 192.168.1.64/26 hosts .65 โ .126 broadcast .127
Subnet 3: 192.168.1.128/26 hosts .129 โ .190 broadcast .191
Subnet 4: 192.168.1.192/26 hosts .193 โ .254 broadcast .255
Each subnet gets 62 usable hosts. Notice the pattern: subnets start at multiples of the block size (64), and each new subnet begins immediately after the previous broadcast.
The General Procedure
To carve N subnets out of X/Y:
- Extra bits needed: ceil(logโ N)
- New prefix: Y + extra bits
- Subnet boundaries land on multiples of the new block size
- Apply the four questions to each piece
Reverse Problem: "I need a subnet for 100 hosts"
Hosts needed H โ find smallest n where 2โฟ โ 2 โฅ H โ prefix = 32 โ n.
100 hosts โ 2โทโ2 = 126 โฅ 100 โ 7 host bits โ /25 (128-block)
500 hosts โ 2โนโ2 = 510 โฅ 500 โ 9 host bits โ /23
2 hosts โ /30 or /31 (router-to-router links)
14 hosts โ /28 (classic DMZ size)
Cloud providers ask exactly this question in their VPC wizards ("subnets must be /16โ/28"), so this direction is the practically common one.
VLSM: Different Sizes for Different Needs
Equal splitting wastes space: a guest Wi-Fi doesn't need 254 addresses when a DMZ needs 60 and point-to-point links need 2. Variable Length Subnet Masks let each subnet have its own size.
Task: From 192.168.10.0/24, allocate
- Sales VLAN: 100 hosts
- Servers VLAN: 50 hosts
- Management VLAN: 20 hosts
- Printer/IoT VLAN: 10 hosts
- Router links: 2 hosts each ร 2
Rule: allocate largest first. Sorting descending prevents overlap chaos:
Sales needs โฅ101 โ /25 (126) โ 192.168.10.0/25 .1โ.126
Servers needs โฅ52 โ /26 (62) โ 192.168.10.128/26 .129โ.190
Management needs โฅ22 โ /27 (30) โ 192.168.10.192/27 .193โ.222
IoT needs โฅ12 โ /28 (14) โ 192.168.10.224/28 .225โ.238
Link A needs โฅ2 โ /30 โ 192.168.10.240/30 .241โ.242
Link B needs โฅ2 โ /30 โ 192.168.10.244/30 .245โ.246
(spare: .248/29 free for growth)
Every allocation lands cleanly on its own boundary; nothing overlaps; 8 addresses remain for expansion. Draw it as a ruler and it's obvious why largest-first matters โ try allocating the /30s first and watch the /25 no longer fit anywhere clean.
Verify With Tooling
# ipcalc shows everything about any prefix (apt install ipcalc)
ipcalc 192.168.10.128/26
# Address: 192.168.10.128
# Network: 192.168.10.128/26
# HostMin: 192.168.10.129
# HostMax: 192.168.10.190
# Broadcast: 192.168.10.191
# Hosts/Net: 62
# sipcalc does IPv4 + IPv6; python has it built in:
python3 - <<'EOF'
import ipaddress
for net in ["192.168.10.0/25","192.168.10.128/26","192.168.10.192/27",
"192.168.10.224/28","192.168.10.240/30","192.168.10.244/30"]:
n = ipaddress.ip_network(net)
print(f"{str(n):22} {n.num_addresses:>4} addrs {list(n.hosts())[0]} โ {list(n.hosts())[-1]}")
EOF
Use tools for verification, not for thinking โ the hand method stays fast enough and catches config typos that blind trust in calculators misses.
A Real Addressing Plan
Here's the plan we'll reuse across the firewall, Traefik, and Pi-hole lessons. A small self-hosted environment on 10.10.0.0/16 private space (room to grow far beyond a /24):
10.10.0.0/16 โ overall allocation (routed nowhere directly)
VLAN 10 10.10.10.0/24 Management (switches, hypervisors, iDRAC/iLO)
GW 10.10.10.1 ~254 hosts
VLAN 20 10.10.20.0/24 Servers (Docker hosts, VMs, storage)
GW 10.10.20.1 static .10-.99, DHCP pool .100-.199
VLAN 30 10.10.30.0/24 Users/Wired (workstations)
GW 10.10.30.1 DHCP .50-.250
VLAN 40 10.10.40.0/24 Wi-Fi trusted (laptops, phones)
GW 10.10.40.1 DHCP .50-.250
VLAN 50 10.10.50.0/24 IoT/Guest (cameras, TVs, visitors)
GW 10.10.50.1 DHCP .50-.250, heavily firewalled
VLAN 60 10.10.60.0/24 DMZ (anything internet-reachable)
GW 10.10.60.1 static .10-.49
Conventions baked into the plan:
- Gateways are always
.1โ predictable, greppable in configs - Static ranges documented per-VLAN โ DHCP pools never overlap static space
- Internet-facing services live in the DMZ, nothing else does (see firewall-basics)
- IoT isolated from servers by default โ cameras phoning home can't reach your NAS (enforced later with firewall rules)
- Room to add VLAN 70+ without renumbering anything
Write your plan down before assigning addresses. "Whatever the DHCP gave me" is not an addressing plan; it's tomorrow's 3 AM troubleshooting session. Document it alongside DNS records once you reach local-dns-records and pihole-setup.
IPv6 Prefixes in Practice
IPv6 subnetting follows the same logic with different conventions:
2001:db8:abcd:0012::/64
โโโโโโโฌโโโโโโโโโโฌโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ
routed to you your interface IDs (64 bits,
by your ISP subnet usually SLAAC/randomized)
Key differences from v4 habits:
- The standard subnet is /64 โ not because you need 18 quintillion hosts, but because SLAAC autoconfiguration requires it. Don't subnet smaller than /64 on LANs even though the math allows it.
- ISPs typically delegate a /56 (256 subnets) or /48 to homes/businesses. Your router subdivides it, one /64 per VLAN/VSSID.
- No mask games โ you don't do VLSM inside your delegation; you burn whole /64s profligately. There are enough.
- Link-local
fe80::/10exists on every interface regardless; it's for neighbor discovery and local protocols only.
ip -6 route show
# 2001:db8:abcd:12::/64 dev eth0 proto kernel metric 256
# fe80::/64 dev eth0 proto kernel metric 256
# default via fe80::1 dev eth0 proto ra metric 1024 โ learned from Router Advertisement
python3 -c "import ipaddress; print(ipaddress.ip_network('2001:db8::/32').subnets(new_prefix=64).__next__())"
# 2001:db8::/64
The same Python ipaddress module handles v6 calculations โ useful since hex math is worse for humans than decimal.
Hands-On Exercises
Do these on paper first, verify after:
# 1. Four questions, no calculator:
# a) 172.16.55.77/20 โ network? broadcast? usable range? count?
# b) 10.1.1.199/26 โ same four
# c) 192.168.100.240/28 โ same four
# Answers below (no peeking):
# a) 172.16.48.0/20 ยท bcast 172.16.63.255 ยท .48.1โ.63.254 ยท 4094
# b) 10.1.1.192/26 ยท bcast 10.1.1.255 ยท .193โ.254 ยท 62
# c) 192.168.100.240/28 ยท bcast .255 ยท .241โ.254 ยท 14
# 2. Can these pairs talk directly? (same network?)
python3 - <<'EOF'
import ipaddress
pairs = [("192.168.1.50/24","192.168.1.87/24"),
("192.168.1.50/24","192.168.2.87/24"),
("10.10.20.5/24","10.10.21.5/24"),
("172.16.5.9/22","172.16.7.200/22")]
for a,b in pairs:
print(a, "<->", b, ":",
"DIRECT" if ipaddress.ip_interface(a).network == ipaddress.ip_interface(b).network
else "NEEDS ROUTER")
EOF
# 3. Carve 192.168.50.0/24 into: 60, 60, 30, 12, 2 hosts. Largest-first.
# Answer: .0/26, .64/26, .128/27, .160/28, .176/30 โ with room left.
# 4. Confirm your own box's understanding matches reality:
ip -brief addr; ip route show; ipcalc $(ip -brief addr show eth0 | awk '{print $3}')
Speed goal: question set 1 should take under 90 seconds total. That's the level of fluency where subnet stops being a chore.
Common Gotchas
| Mistake | Symptom | Fix |
|---|---|---|
| Wrong mask on one end (/25 vs /24) | "Works sometimes" โ some destinations direct, others via gateway, asymmetric weirdness | Compare masks on both hosts; ping + ip route get |
| Static IP inside DHCP pool | Random "IP conflict" storms hours later | Reserve static ranges outside pools (or DHCP reservations) |
| Using documentation IPs (192.0.2.x) for real | Things break mysteriously when VPN routes appear | Use 10.x/172.16/192.168 space internally |
| Overlapping subnets after VPN connect | Traffic black-holes toward one branch office | Plan non-overlapping allocations before any site-to-site VPN |
| Assuming /24 means "last octet changes" | Confusion with /23, /25 boundaries mid-octet | Always compute the block size, don't pattern-match |
Forgetting gateway .1 isn't magic |
Renumbered network, scripts still hardcode old gw | Config management / document the convention |
| IPv6 /64 split into smaller LANs | SLAAC breaks; devices self-assign wrong addresses | Keep /64 minimum for any LAN segment |
| Double-counting network+broadcast in cloud consoles | AWS "subnet too small" errors | Remember cloud reserves 5 addresses per subnet, not 2 |
The deepest one deserves emphasis: overlapping subnets across sites is the classic multi-location failure. Site A uses 192.168.1.0/24, Site B uses the same, then a WireGuard tunnel connects them โ now 192.168.1.1 means two different machines depending on who answers first. Preventing this costs ten minutes of planning in this lesson; fixing it costs a weekend of renumbering later.
Next Steps
Addressing is the vocabulary; now learn the directory service that makes names work:
- dns-fundamentals โ how names become the addresses you now fully understand
- network-troubleshooting โ apply today's math to real breakage
- nat-port-forwarding โ what happens when private-space networks meet the public internet
๐ Related
- Prerequisite: tcp-ip-fundamentals
- Next: dns-fundamentals
- firewall-basics โ rules match on the networks you can now calculate
- pihole-setup โ putting your addressing plan to work
- kb/security/network-segmentation โ VLAN security deep-dive