Every cloud console asks you for a CIDR block and gives no help if you get it wrong. The arithmetic is small and worth being able to do without a calculator.
1. What the prefix actually means
An IPv4 address is 32 bits. The prefix length says how many leading bits are the network; the rest identify a host inside it.
ipcalc 10.0.1.0/24 2>/dev/null || echo "install ipcalc to check answers"For 10.0.1.0/24: 24 network bits, 8 host bits. That gives 2^8 = 256 addresses, of which 254 are usable — the first is the network address and the last is broadcast.
The table worth memorising, because these are the sizes you will actually type:
| Prefix | Addresses | Usable | Typical use |
|---|---|---|---|
/32 | 1 | 1 | A single host, a security group rule |
/30 | 4 | 2 | A point-to-point link |
/28 | 16 | 14 | A small subnet |
/24 | 256 | 254 | The default mental unit |
/20 | 4096 | 4094 | A large subnet |
/16 | 65536 | 65534 | A whole VPC |
Each step down in prefix doubles the size. /24 → /23 is 512 addresses.
Verify
2. Do it with the tool, then without
ipcalc 192.168.10.130/26Now by hand. A /26 has 6 host bits, so blocks are 64 addresses wide and start at multiples of 64: .0, .64, .128, .192. The address .130 falls in the block starting at .128.
- Network:
192.168.10.128 - First usable:
192.168.10.129 - Last usable:
192.168.10.190 - Broadcast:
192.168.10.191
The general method: block size is 2^(32 - prefix); the network address is the largest multiple of the block size at or below your address.
python3 - <<'PY'
import ipaddress
n = ipaddress.ip_network("192.168.10.130/26", strict=False)
print("network ", n.network_address)
print("broadcast", n.broadcast_address)
print("usable ", list(n.hosts())[0], "-", list(n.hosts())[-1])
print("size ", n.num_addresses)
PYVerify
3. Decide whether two addresses can talk directly
This is what the prefix is _for_. Two hosts reach each other without a router only if they share a network.
python3 - <<'PY'
import ipaddress
pairs = [
("10.0.1.5/24", "10.0.1.200"),
("10.0.1.5/24", "10.0.2.10"),
("10.0.1.5/16", "10.0.2.10"),
]
for cidr, other in pairs:
iface = ipaddress.ip_interface(cidr)
same = ipaddress.ip_address(other) in iface.network
print(f"{cidr:16} -> {other:12} same network: {same}")
PYThe second and third rows differ only in the prefix. Same addresses, opposite answer. A wrong netmask is why a host can reach the internet but not the server in the next rack.
Verify
4. Split a VPC the way you would deploy it
Given 10.0.0.0/16 and three availability zones, each needing a public and a private subnet:
python3 - <<'PY'
import ipaddress
vpc = ipaddress.ip_network("10.0.0.0/16")
subnets = list(vpc.subnets(new_prefix=20))
names = ["public-a", "public-b", "public-c",
"private-a", "private-b", "private-c"]
for name, net in zip(names, subnets):
print(f"{name:11} {str(net):18} {net.num_addresses - 5:>5} usable")
print(f"\nunused: {len(subnets) - len(names)} more /20 blocks")
PYTwo details that matter in practice. AWS reserves five addresses per subnet, not two — the network address, the broadcast address, the VPC router, the DNS server, and one for future use. And leave blocks unallocated: you cannot resize a subnet after creation, so the spare /20s are what let you add a zone later.
Verify
5. Private ranges, and why you will meet them
python3 - <<'PY'
import ipaddress
for cidr in ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16",
"100.64.0.0/10", "169.254.0.0/16", "127.0.0.0/8"]:
n = ipaddress.ip_network(cidr)
print(f"{cidr:18} {n.num_addresses:>11,} addresses private={n.is_private}")
PYThe first three are RFC 1918 — the only ranges you may use inside your own network. 100.64.0.0/10 is carrier-grade NAT and shows up in some managed services. 169.254.0.0/16 is link-local: an address in that range means DHCP failed, and on a cloud instance 169.254.169.254 is the metadata endpoint.
Overlapping ranges is the mistake that cannot be fixed later: two VPCs both using 10.0.0.0/16 can never be peered. Pick non-overlapping blocks per environment on day one.
Verify
Where this goes next
You can size and split a network. Next: how a name becomes one of these addresses.