Why a /24 Is 254 Hosts
In one line
CIDR is a notation that writes how many leading bits of an IP address are the network. That one number decides how many machines can fit in that network.
Why it was needed
When you create a VPC, following the guide that says to enter 10.0.0.0/16 works for now. The problem comes two years later.
- It overlaps with another team's VPC, so peering is not possible
- It overlaps with the on-premises range, so a VPN connection is not possible
- It overlaps with an acquired company, blocking integration
An address range cannot be changed later. You have to create all the resources anew and move them. So the value of planning at the start is greater than any other decision.
Counting in bits
An IPv4 address is 32 bits. /24 means the first 24 bits are the network, and the remaining 8 bits are where the host goes.
10.0.1.0/24
└─ 네트워크 24비트 ─┘└ 호스트 8비트 ┘
호스트 자리 = 32 − 24 = 8비트 → 2^8 = 256개 주소
It is 256, so why 254 machines? The first address is the network address and the last is the broadcast address, and they cannot be used. Hence 254.
The cloud subtracts more. AWS reserves 5 addresses per subnet (network, VPC router, DNS, reserved for future use, broadcast). So the number of actually usable IPs in a /24 subnet is 251. If you plan for 250 machines without knowing this, it gets tight.
| CIDR | Total addresses | Available in AWS |
|---|---|---|
| /28 | 16 | 11 |
| /27 | 32 | 27 |
| /26 | 64 | 59 |
| /24 | 256 | 251 |
| /22 | 1,024 | 1,019 |
| /20 | 4,096 | 4,091 |
| /16 | 65,536 | — (VPC maximum) |
A trick for memorizing: /24 is 256, and each time the prefix decreases by 1, it doubles. /23 = 512, /22 = 1,024. Conversely, each increase of 1 halves it.
Private ranges
Only the three ranges defined by RFC 1918 are used internally.
| Range | Size | Common use |
|---|---|---|
10.0.0.0/8 |
16.77 million | Large organizations. Most cloud VPCs |
172.16.0.0/12 |
1.04 million | Docker's default bridge is here |
192.168.0.0/16 |
65,000 | Home routers |
The fact that 172.17.0.0/16 is Docker's default bridge range often causes incidents in practice — if you use 172.17.x.x for the internal network, you cannot reach that address from inside a container.
The order for making a plan
- Set the overall budget large — start by assigning
10.0.0.0/8to the whole organization. Addresses are free. Saving them is no benefit. - Cut by environment — production
10.0.0.0/12, staging10.16.0.0/12, development10.32.0.0/12, without overlap. - Cut by region — a different range for each region. It makes inter-region connections easy later.
- Be generous with the VPC —
/16is used as if it were the default. 65,000 addresses is usually enough. - Subnets by purpose — covered below.
- Write the on-premises and partner ranges in a document — they must not overlap with ranges you will connect later.
What happens when they overlap
If two VPCs use the same 10.0.0.0/16, peering is impossible. This is because a route table cannot send the same destination to two places. The only fix is to move one side to a new range, and that is effectively a rebuild.
That is why an organization needs an IP range ledger. A single spreadsheet is enough, and without one, incidents are certain.
Calculating quickly, and where mistakes happen
Once CIDR calculation becomes familiar, it takes a few seconds, and if it is not, you look for a calculator every time. There are only two lines to memorize.
The number of addresses is 2^(32-prefix). /24 is 256, /23 is 512, and /25 is 128. Each 1 less in the prefix doubles it.
A boundary can start only at a multiple of its size. For a /24, the third octet can be any value, but for a /23 the third octet must be even, and for a /22 it must be a multiple of 4. 10.0.3.0/23 is an invalid notation and would actually mean 10.0.2.0/23. This is the most common mistake.
| Prefix | Number of addresses | Values the third octet can take |
|---|---|---|
| /24 | 256 | Any value |
| /23 | 512 | 0, 2, 4, … |
| /22 | 1024 | 0, 4, 8, … |
| /20 | 4096 | 0, 16, 32, … |
The cloud takes a few at the front and back. Most clouds reserve 5 per subnet (network address, gateway, DNS, reserved for future use, broadcast). A /28 has 16, but only 11 are usable. The more you chop up small subnets, the larger this loss ratio becomes.
To see whether they overlap, cut with the larger side's prefix. To see whether 10.1.0.0/16 and 10.1.128.0/17 overlap, cut the latter at /16 and see whether 10.1.0.0 comes out. If it does, they overlap.
python3 -c "
import ipaddress as ip
a = ip.ip_network('10.1.0.0/16'); b = ip.ip_network('10.1.128.0/17')
print(a.overlaps(b), list(a.subnets(new_prefix=18))[:2])"
What to leave in the plan is not the ranges but the rules. A table saying "which team uses which range" soon becomes outdated. If you write down a rule the next person can apply on their own, such as "a /16 per region, a /20 per AZ, a /24 per purpose," collisions will not happen even without looking at the table.
What it looks like in the field
- Two teams each created a VPC with
10.0.0.0/16, and a year later when the two services had to be connected, peering was rejected. One side was rebuilt on a new range. - At a company that used
172.17.x.xfor its internal network, the internal API failed only from inside containers. It overlapped with Docker's default bridge, and because the symptom appeared only in containers, it took days to find the cause. - Subnets were cut into small
/28blocks, and as Pods increased the IPs ran out. It looked like 16, but only 11 were actually usable. - The range overlapped with an acquired company, and system integration slipped by half a year. A single spreadsheet would have avoided it from the start.
What to look at next
We split the inside of a VPC into subnets and decide what goes where.