All posts

CIDR notation and subnet masks explained

How /24 maps to 255.255.255.0, how to find network, broadcast and usable hosts, private ranges, splitting subnets, cloud reserved IPs and overlapping CIDRs.

By Last reviewed 7 min readNetworkingCIDRSubnettingCloud

CIDR notation writes a network as an address, a slash and a prefix length: 192.168.1.0/24. The prefix is the number of leading bits that identify the network; the remaining bits identify hosts inside it. A /24 fixes the first 24 of 32 bits, which is the same thing as the subnet mask 255.255.255.0, and leaves 8 bits, or 256 addresses, for hosts.

The IP subnet calculator for IPv4 and IPv6 CIDR ranges does every calculation in this guide. Enter 10.20.30.40/20, 10.20.30.40/255.255.240.0 or an IPv6 prefix, and it shows the network and broadcast addresses, the usable host range, the wildcard mask and a binary breakdown. It can also divide a network into 2 to 256 equal subnets, check whether two addresses share a subnet, and list every IPv4 prefix from /0 to /32.

From prefix to mask to network address

An IPv4 address is 32 bits. The mask has a 1 for every network bit and a 0 for every host bit, so /24 is 24 ones followed by 8 zeros, written as 255.255.255.0. When the prefix ends inside an octet, that octet can only be 128, 192, 224, 240, 248, 252, 254 or 255, for 1 to 8 network bits.

The network address is the address AND the mask, and the broadcast address is the network with every host bit set to 1. Take 192.168.10.77/26:

Address    192.168.10.77     11000000.10101000.00001010.01001101
Mask       255.255.255.192   11111111.11111111.11111111.11000000
Network    192.168.10.64     11000000.10101000.00001010.01000000
Broadcast  192.168.10.127    11000000.10101000.00001010.01111111

Between them sit the hosts, 192.168.10.65 to 192.168.10.126, 62 in all. The calculator colours network and host bits in its binary view, and the number base converter turns any octet into binary if you want to check by hand.

You rarely need binary in practice. Find the octet where the mask isn't 255 or 0 and subtract it from 256 to get the block size: 256 − 192 = 64. Networks start at multiples of 64 (.0, .64, .128, .192), and 77 falls in the block that starts at .64. The trick works in any octet. For 10.20.30.40/255.255.240.0, a /20, the block size is 256 − 240 = 16 in the third octet, so blocks start at 0, 16, 32 and so on. 30 falls in 16–31, giving network 10.20.16.0 and broadcast 10.20.31.255.

Usable hosts, and the /31 and /32 exceptions

A /n prefix holds 2^(32 − n) addresses. The first (network) and last (broadcast) are not assigned to hosts, so usable hosts are 2^(32 − n) − 2. Two prefixes break the formula:

  • /31 has two addresses, and under RFC 3021 both are usable on point-to-point links. There is no broadcast address.
  • /32 is exactly one address. You see it in routes, firewall rules and security groups: 203.0.113.10/32 means "this host only".

The calculator counts 2 and 1 for these. Here are the prefixes you will actually meet; the tool's CIDR table mode lists all 33.

PrefixSubnet maskWildcardAddressesUsable hosts
/8255.0.0.00.255.255.25516,777,21616,777,214
/12255.240.0.00.15.255.2551,048,5761,048,574
/16255.255.0.00.0.255.25565,53665,534
/20255.255.240.00.0.15.2554,0964,094
/22255.255.252.00.0.3.2551,0241,022
/24255.255.255.00.0.0.255256254
/25255.255.255.1280.0.0.127128126
/26255.255.255.1920.0.0.636462
/27255.255.255.2240.0.0.313230
/28255.255.255.2400.0.0.151614
/29255.255.255.2480.0.0.786
/30255.255.255.2520.0.0.342
/31255.255.255.2540.0.0.122
/32255.255.255.2550.0.0.011

Private ranges, CGNAT and other special blocks

BlockRangePurpose
10.0.0.0/810.0.0.0 – 10.255.255.255Private (RFC 1918)
172.16.0.0/12172.16.0.0 – 172.31.255.255Private (RFC 1918)
192.168.0.0/16192.168.0.0 – 192.168.255.255Private (RFC 1918)
100.64.0.0/10100.64.0.0 – 100.127.255.255Shared space for carrier-grade NAT (RFC 6598)
169.254.0.0/16169.254.0.0 – 169.254.255.255Link-local; 169.254.169.254 is the cloud instance metadata address
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24three /24sDocumentation (RFC 5737), safe for examples

Two mistakes come up again and again. 172.16.0.0/12 stops at 172.31.255.255, so 172.32.0.1 is a public address, and the calculator's IP Type row says so. And 100.64.0.0/10 is not RFC 1918: ISPs use it behind carrier-grade NAT and Tailscale assigns node addresses from it, so it may already be in use on the path.

Splitting a network into subnets

Each bit you add to the prefix halves the block: a /24 is two /25s, four /26s or eight /27s. Dividing 192.168.1.0/24 into 4 in the calculator gives:

SubnetUsable rangeBroadcastHosts
192.168.1.0/26192.168.1.1 – 192.168.1.62192.168.1.6362
192.168.1.64/26192.168.1.65 – 192.168.1.126192.168.1.12762
192.168.1.128/26192.168.1.129 – 192.168.1.190192.168.1.19162
192.168.1.192/26192.168.1.193 – 192.168.1.254192.168.1.25562

Real networks rarely want equal pieces. Suppose 10.0.0.0/24 must hold one segment of about 100 hosts, one of 50 and two of 25. Allocate the largest first, each starting on a multiple of its own size:

10.0.0.0/25     126 usable   .0   – .127
10.0.0.128/26    62 usable   .128 – .191
10.0.0.192/27    30 usable   .192 – .223
10.0.0.224/27    30 usable   .224 – .255

In the calculator, divide the /24 into 2, load 10.0.0.128/25 and divide it into 2, then do the same with 10.0.0.192/26. The alignment rule is not optional. 10.0.0.96/26 is not a network, because 96 isn't a multiple of 64: the calculator reports its network as 10.0.0.64, and Python's ipaddress.ip_network("10.0.0.96/26") raises "has host bits set". The EC2 API silently rewrites such input, turning 100.68.0.18/18 into 100.68.0.0/18, so check that what you typed is what you meant.

Cloud subnets reserve more addresses

The −2 rule is for classic networks. Cloud providers keep extra addresses for routers and DNS:

  • AWS reserves the first four and the last address of every subnet. In 10.0.1.0/24 those are .0 (network), .1 (VPC router), .2 (reserved; the DNS server sits at the VPC range's base plus two), .3 (future use) and .255 (broadcast, which VPCs don't support). That leaves 251 addresses, starting at 10.0.1.4. Subnets can be /16 to /28, and a /28 has just 11.
  • Azure also reserves five: the network address, .1 for the default gateway, .2 and .3 for Azure DNS, and the broadcast address. Its smallest IPv4 subnet is a /29.
  • Google Cloud reserves four in a subnet's primary range: the network address, the default gateway, the second-to-last address and the broadcast address. Secondary ranges reserve none.

So subtract 3 more from the calculator's usable count on AWS and Azure, and 2 more for a Google Cloud primary range. Leave room to grow, too: on AWS, load balancers and EKS pods using the VPC CNI plugin draw addresses from the same subnets as your instances.

Overlapping CIDRs: peering, VPNs and Docker

Routing needs every destination to be unambiguous, so networks you connect must not overlap. AWS won't create a VPC peering connection between VPCs with matching or overlapping CIDR blocks, and a site-to-site VPN hits the same wall when the office and the VPC both picked 10.0.0.0/16.

Checking is easier than it looks, because CIDR blocks never partially overlap: two blocks are either disjoint or one contains the other. Take the shorter prefix and compare both network addresses at that length. In the calculator's Range check mode, 10.0.0.0 and 10.0.128.0 at /16 are in the same subnet, so 10.0.128.0/17 sits inside 10.0.0.0/16. 10.0.0.0 and 10.1.0.0 at /16 are not, so those two VPCs can peer. In Python:

>>> import ipaddress
>>> vpc = ipaddress.ip_network("10.0.0.0/16")
>>> vpc.overlaps(ipaddress.ip_network("10.0.128.0/17"))
True
>>> vpc.overlaps(ipaddress.ip_network("10.1.0.0/16"))
False

Watch the defaults. Docker's default bridge network is 172.17.0.0/16, and the AWS default VPC is 172.31.0.0/16 with a /20 subnet per Availability Zone. If a corporate VPN routes 172.17.0.0/16, containers and the VPN collide; move Docker with bip or default-address-pools in daemon.json. For a new VPC, avoid 10.0.0.0/16, 192.168.0.0/24 and 192.168.1.0/24, the blocks every tutorial and home router already uses.

Wildcard masks for ACLs

A wildcard mask is the subnet mask inverted: 0 bits must match and 1 bits are "don't care". A /26 has mask 255.255.255.192 and wildcard 0.0.0.63. Cisco IOS access lists and OSPF network statements take wildcards:

access-list 10 permit 192.168.10.64 0.0.0.63
router ospf 1
 network 10.20.16.0 0.0.15.255 area 0

The calculator shows the wildcard for every result and in the CIDR table. IOS also accepts discontiguous wildcards such as 0.0.254.255, which match patterns no single CIDR block can describe.

IPv6: the same idea, with /64 subnets

IPv6 addresses are 128 bits written as eight hex groups, and prefixes work the same way. The difference is scale. A LAN subnet is almost always a /64, because stateless address autoconfiguration (SLAAC) expects a 64-bit interface identifier. Sites commonly receive a /48 or a /56, which hold 65,536 and 256 /64 subnets. There is no broadcast in IPv6, so no −2. The calculator accepts IPv6 with :: shorthand; for 2001:db8:abcd:12::1/64 it shows:

Expanded:        2001:0db8:abcd:0012:0000:0000:0000:0001
Network:         2001:db8:abcd:12::/64
First Address:   2001:db8:abcd:12::
Last Address:    2001:db8:abcd:12:ffff:ffff:ffff:ffff
Total Addresses: 18,446,744,073,709,551,616 (2^64)
Address Type:    Documentation

Divide and Range check work for IPv6 too. In the cloud, AWS reserves the first four and the last address of IPv6 subnets as well, and Azure requires IPv6 subnets to be exactly /64.

Next steps

Run your VPC and subnet plan through the subnet calculator one block at a time, and use Range check on every pair of networks that will ever be connected. If the servers in those subnets run deploy scripts, chmod 755 vs 644 covers the file-permission side.

Paste anything. devprix picks the tool.

Press ⌘K on any page, paste JSON, a JWT, a timestamp or a URL, and the right tool opens with your data filled in.