Cheatsheet

CIDR Notation Cheatsheet

This cheatsheet is a lookup table for CIDR (Classless Inter-Domain Routing) notation, the 192.168.1.0/24 form that writes an IP network as an address plus a prefix length. It is for developers setting up VPCs, firewall rules, Docker networks and allowlists. The one fact most people search for: /24 means the first 24 bits are the network, which leaves 8 bits for hosts, so 256 addresses and 254 usable hosts. The current specification is RFC 4632.

Quick reference

IPv4 prefix lengths

CIDR Subnet mask Total addresses Usable hosts
/8 255.0.0.0 16,777,216 16,777,214
/16 255.255.0.0 65,536 65,534
/20 255.255.240.0 4,096 4,094
/22 255.255.252.0 1,024 1,022
/23 255.255.254.0 512 510
/24 255.255.255.0 256 254
/25 255.255.255.128 128 126
/26 255.255.255.192 64 62
/27 255.255.255.224 32 30
/28 255.255.255.240 16 14
/29 255.255.255.248 8 6
/30 255.255.255.252 4 2
/31 255.255.255.254 2 2 (point-to-point links, RFC 3021)
/32 255.255.255.255 1 1 (a single host)
/0 0.0.0.0 4,294,967,296 the default route

The total is always 2 raised to the power of (32 minus the prefix). Usable hosts is the total minus 2, because the first address is the network address and the last is the broadcast address. The exceptions are /31 and /32.

Private and reserved IPv4 blocks

Block Range Addresses Note
10.0.0.0/8 10.0.0.0 to 10.255.255.255 16,777,216 Private, RFC 1918
172.16.0.0/12 172.16.0.0 to 172.31.255.255 1,048,576 Private, RFC 1918
192.168.0.0/16 192.168.0.0 to 192.168.255.255 65,536 Private, RFC 1918
100.64.0.0/10 100.64.0.0 to 100.127.255.255 4,194,304 Shared address space, listed in RFC 6890
127.0.0.0/8 127.0.0.0 to 127.255.255.255 16,777,216 Loopback, listed in RFC 6890
169.254.0.0/16 169.254.0.0 to 169.254.255.255 65,536 Link-local, listed in RFC 6890
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 each /24 256 each Documentation examples, listed in RFC 6890

Picking a prefix for a host count

Hosts needed Smallest prefix that fits Usable hosts
2 /30 2
10 /28 14
50 /26 62
100 /25 126
500 /23 510

Reading a CIDR block

Part Meaning Example `192.168.1.130/26`
Address Any address in the block 192.168.1.130
Prefix length Number of leading network bits 26
Network address Address with all host bits zero 192.168.1.128
Broadcast address Address with all host bits one 192.168.1.191
Wildcard mask Inverted subnet mask, used by some ACL syntaxes 0.0.0.63

IPv6 sizes

Prefix Addresses Where used
/32 79,228,162,514,264,337,593,543,950,336 A large block, such as the documentation prefix 2001:db8::/32
/64 18,446,744,073,709,551,616 One subnet. RFC 4291 requires 64-bit interface IDs for most unicast addresses
/128 1 A single host

Common patterns

Work out the range of a block

import ipaddress as ip
for c in ["192.168.1.0/24", "10.1.2.0/31", "10.1.2.3/32", "192.0.2.0/30"]:
    n = ip.ip_network(c, strict=False)
    h = list(n.hosts())
    print(c, "mask", n.netmask, "bc", n.broadcast_address, "total", n.num_addresses, "hosts", len(h), h[0], h[-1])
192.168.1.0/24 mask 255.255.255.0 bc 192.168.1.255 total 256 hosts 254 192.168.1.1 192.168.1.254
10.1.2.0/31 mask 255.255.255.254 bc 10.1.2.1 total 2 hosts 2 10.1.2.0 10.1.2.1
10.1.2.3/32 mask 255.255.255.255 bc 10.1.2.3 total 1 hosts 1 10.1.2.3 10.1.2.3
192.0.2.0/30 mask 255.255.255.252 bc 192.0.2.3 total 4 hosts 2 192.0.2.1 192.0.2.2

The Python hosts() method already handles the /31 and /32 exceptions, which is why those lines list 2 and 1 hosts. Note that the /30 line shows 2 usable hosts out of 4 addresses: .0 is the network and .3 the broadcast. That is why a /30 was the classic size for a link between two routers until /31 links were allowed.

Find the network address for a host inside a block

import ipaddress as ip
print(ip.ip_network("192.168.1.130/26", strict=False))
print(ip.ip_network("203.0.113.77/28", strict=False))
192.168.1.128/26
203.0.113.64/28

Use this to normalize an address with host bits set into its network form. The pair 192.168.1.130/26 is a host address and its subnet at once. Cloud consoles and firewalls usually want the network form, and some reject the other one.

Test whether an IP is inside a range

import ipaddress as ip
print(ip.ip_address("10.1.2.3") in ip.ip_network("10.0.0.0/8"))
print(ip.ip_address("172.32.0.1") in ip.ip_network("172.16.0.0/12"))
True
False

172.32.0.1 is outside the 172.16.0.0/12 private block, which ends at 172.31.255.255. This check is the core of an IP allowlist. In a real service, parse the client address once and compare it against a list of networks, rather than comparing strings. String prefix tests are fragile: startswith("10") without the dot also matches 100.64.0.1, which is not in 10.0.0.0/8, and no prefix test can express a block like 172.16.0.0/12.

Split a block into smaller subnets

import ipaddress as ip
print(list(ip.ip_network("192.168.0.0/24").subnets(new_prefix=26)))
[IPv4Network('192.168.0.0/26'), IPv4Network('192.168.0.64/26'), IPv4Network('192.168.0.128/26'), IPv4Network('192.168.0.192/26')]

Each extra prefix bit halves the block size, so going from /24 to /26 gives 4 subnets of 64 addresses. The reverse operation, a supernet, drops bits: 10.0.0.0/16 together with its sibling forms 10.0.0.0/15.

Merge adjacent blocks or summarize a range

import ipaddress as ip
print(next(ip.collapse_addresses([ip.ip_network("10.0.0.0/25"), ip.ip_network("10.0.0.128/25")])))
print(list(ip.summarize_address_range(ip.ip_address("10.0.0.5"), ip.ip_address("10.0.0.20"))))
10.0.0.0/24
[IPv4Network('10.0.0.5/32'), IPv4Network('10.0.0.6/31'), IPv4Network('10.0.0.8/29'), IPv4Network('10.0.0.16/30'), IPv4Network('10.0.0.20/32')]

Two sibling /25 blocks merge into one /24. A range that is not aligned to a power of two needs several CIDR blocks, here five.

Check whether two blocks overlap

import ipaddress as ip
print(ip.ip_network("10.0.0.0/8").overlaps(ip.ip_network("10.5.0.0/16")))
True

Run this before peering two VPCs or joining two VPNs. Overlapping ranges cause routing conflicts.

Pitfalls

  • Host bits set in a block: 192.168.1.130/26 is not a valid network. Python raises 192.168.1.130/26 has host bits set. Normalize it to 192.168.1.128/26, or accept the address as a host with a strict=False parse.
  • Counting 256 usable hosts in a /24: Only 254 are usable. The network and broadcast addresses are reserved, so /24 gives .1 through .254.
  • Assuming 172.x is all private: Only 172.16.0.0 to 172.31.255.255 is private. 172.32.0.1 is a public address, as the allowlist example shows.
  • Mixing up the mask and the wildcard: A /26 is 255.255.255.192 as a subnet mask and 0.0.0.63 as a wildcard. Some router ACL syntaxes want the wildcard form.
  • Overlapping ranges between environments: If two networks both use 10.0.0.0/16, they cannot be routed to each other without translation. Plan non-overlapping blocks early, and test with overlaps().
  • Using /32 in a firewall rule where you meant a network: /32 matches one address. Write /24 or the block you actually mean.
  • Using 0.0.0.0/0 as a harmless default: It matches every IPv4 address. In a security group or an ingress rule this opens the service to the whole internet.
  • Applying IPv4 host math to IPv6: RFC 4291 states that IPv6 has no broadcast addresses, and a /64 holds 18,446,744,073,709,551,616 addresses. Never size IPv6 subnets by host count.
  • Cutting a block off the bit boundary: A CIDR block must start at an address whose host bits are all zero. 10.0.0.5 cannot begin a /29.

Related ZipKit tools

Related cheatsheets