By the end you'll know
- What a subnet is, and why networks are split into them
- How to read CIDR notation, like
192.168.1.0/24or10.0.0.0/16 - How many addresses a range holds, and how many devices can use them
- What a subnet mask is, and how it matches a prefix
- How to split a range in half, and tell whether an address is inside it
Where you are
Lesson 2 ended on a promise: networks aren't built from single addresses, but from ranges of them, like "everything starting with 192.168.1.". Your laptop's address and your phone's address both started that way, because they're on the same home network.
This lesson is about those ranges. They're behind every cloud network you'll ever build, every Kubernetes cluster, and every firewall rule, so they turn up in nearly every lesson from here on. And they're where the binary from Lesson 2 really earns its place.
Network part and host part
On a street, every house shares the street name, and only the house number changes. An IP address in a range works the same way: part of it is shared by every device on that network, and the rest picks out one device.
Take your laptop's address from Lesson 2, 192.168.1.23, on a typical home network:
192.168.1is the network part, the street name. Every device in the house starts with it.23is the host part, the house number. Host is the networking word for any device with an address: your laptop is host 23, your phone might be host 24.
A subnet, short for subnetwork, is one of these ranges: a group of addresses that share the same network part. Devices in the same subnet can talk to each other directly. To reach anything outside it, they go through a router, which Lesson 6 covers.
Writing a range: CIDR
To describe a range, you need to say where it starts and how much of the address is the network part. The standard way to do both at once is CIDR (Classless Inter-Domain Routing) notation:
192.168.1.0/24
The address before the slash is where the range starts. The number after it is the prefix length: how many of the 32 bits are the network part. /24 means the first 24 bits are fixed, which is the first three octets, since each octet is 8 bits. The other 8 bits are the host part, free to be anything from 00000000 to 11111111. So 192.168.1.0/24 means every address from 192.168.1.0 to 192.168.1.255.
The bigger the prefix, the more bits are fixed and the smaller the range. Drag the slider and watch it happen:
A few things to try:
- Drag from /24 to /25. The range halves, from 256 addresses to 128. Each step to the right fixes one more bit, which halves the range. Each step left doubles it.
- Drag to /16 and to /8. At
/16only the first two octets are fixed, and the range is 65,536 addresses. At/8it's over 16 million. - Type
192.168.1.77into the address box and look at the first address. The range still starts at192.168.1.0, because a range always starts where its host bits are all 0.
How many addresses
Every host bit doubles the size of the range, so a range has 2 to the power of its host bits: 32 minus the prefix length. You don't need to work it out each time. These are the ones you'll see again and again:
| Prefix | Addresses | Where you'll see it |
|---|---|---|
/32 | 1 | One single address, often in firewall rules |
/28 | 16 | A tiny subnet, for a few servers |
/24 | 256 | A home network, or one cloud subnet |
/20 | 4,096 | A large subnet, for a busy cluster |
/16 | 65,536 | A whole cloud network, split into subnets |
/8 | 16,777,216 | All of 10., the biggest private range |
Not every address in a range can go to a device. The first address names the network itself, and the last is the broadcast address, used to send a message to every device on the subnet at once. So a /24 has 256 addresses, but 254 usable ones. Cloud providers keep a few more for themselves: AWS (Amazon Web Services) holds back 5 in every subnet: the first and last, plus three more, for its router, its DNS (Domain Name System) server and future use. Always check the provider's documentation before you size a subnet tightly.
Subnet masks
You'll sometimes see the same idea written a second, older way: as a subnet mask, which looks like an address. Write the prefix's fixed bits as 1s and the host bits as 0s, then turn each octet back into a number:
/24 = 11111111.11111111.11111111.00000000 = 255.255.255.0
So a mask of 255.255.255.0 means exactly the same as /24. The slider above shows the mask for every prefix: try /16, which is 255.255.0.0, and /25, which is 255.255.255.128, because the one extra fixed bit is the 128 switch from Lesson 2.
Your own computer knows its mask. On a Mac, for Wi-Fi:
ipconfig getoption en0 subnet_mask
As in Lesson 2, try en1 if nothing prints. On a home network you'll most likely see:
255.255.255.0
So your home network is a /24. On Linux or WSL, ip -4 addr shows the same thing in CIDR form, with your address written like 192.168.1.23/24. On Windows, ipconfig lists it as Subnet Mask.
Splitting a range
Big ranges get split into smaller subnets, the way a developer splits a plot of land into lots. Each lot gets its own purpose, like one subnet for web servers and another for databases, so they can be given different rules.
Splitting always works the same way: fix one more bit, and the range breaks into two halves. Here's 192.168.1.0/24 split into two /25s:
| Subnet | The 25th bit | Addresses |
|---|---|---|
192.168.1.0/25 | 0 | 192.168.1.0 to 192.168.1.127 |
192.168.1.128/25 | 1 | 192.168.1.128 to 192.168.1.255 |
The split falls at 128 because the 25th bit is the first switch of the last octet: the one worth 128. Fix more bits, and you get more, smaller pieces: a /24 makes four /26s of 64 addresses each, or sixteen /28s of 16.
The same goes for bigger ranges. Split 10.0.0.0/16 into /24s and you get 256 of them, one for each value of the third octet: 10.0.0.0/24, 10.0.1.0/24, 10.0.2.0/24, all the way to 10.0.255.0/24. That's how most cloud networks are laid out, and it's exactly what you'll build in Lesson 7.
/24 is one value of the third octet.Is this address inside the range?
This is the question you'll ask most: is this address part of that network? Is this server covered by that firewall rule? The test is simple: an address is inside a range if its network bits match the range's network bits.
When the prefix is /8, /16 or /24, that just means matching whole octets:
- Is
10.0.5.20inside10.0.0.0/16?/16fixes the first two octets,10.0. It matches, so yes. - Is
10.0.5.20inside10.0.4.0/24?/24fixes three octets,10.0.4. The third octet is 5, not 4, so no.
When the prefix isn't a multiple of 8, the boundary falls inside an octet, and the binary from Lesson 2 does the work. Remember the private range "172.16 to 172.31" from Lesson 2? In CIDR it's 172.16.0.0/12. Twelve bits means the whole first octet, 172, plus the first four bits of the second. 16 is 00010000, so the first four bits are 0001, and the last four, worth 8, 4, 2 and 1, are free. Turn all four on and you get 16 + 15 = 31. That's why the range stops at 172.31, not at a round number.
Let Python check it
You won't do the bit-matching by hand for long. Python has a built-in module for it, ipaddress, so you don't need to install anything. If you did the Python track, this will look familiar: create a file named cidr.py:
import sys
import ipaddress
network = ipaddress.ip_network(sys.argv[1])
print("Range:", network)
print("Addresses:", network.num_addresses)
print("Mask:", network.netmask)
print("First:", network[0])
print("Last:", network[-1])
for text in sys.argv[2:]:
address = ipaddress.ip_address(text)
if address in network:
print(text, "is inside")
else:
print(text, "is outside")
It takes a range, then any addresses you want to check, from the command line. Run it with the two examples from the section above:
python3 cidr.py 10.0.0.0/16 10.0.5.20 10.1.0.1
Range: 10.0.0.0/16
Addresses: 65536
Mask: 255.255.0.0
First: 10.0.0.0
Last: 10.0.255.255
10.0.5.20 is inside
10.1.0.1 is outside
Now check the private range that ends at an odd place:
python3 cidr.py 172.16.0.0/12 172.31.255.1 172.32.0.1
Range: 172.16.0.0/12
Addresses: 1048576
Mask: 255.240.0.0
First: 172.16.0.0
Last: 172.31.255.255
172.31.255.1 is inside
172.32.0.1 is outside
172.31 is the last that fits; one more and you're outside. Lesson 2's three private ranges, in CIDR, are 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16, and you'll see them written that way from now on.
You'll see this again
Kubernetes gives its pods and services address ranges of their own, separate from the network the servers sit on, and they all have to be chosen so they don't overlap. It's one of the settings you pick when you create a cluster, and Lesson 11 shows how the pieces fit together. Every one of those settings is written in CIDR.
Break it on purpose
Three cases. Work out the cause before you read the explanation.
A range that starts in the wrong place. Give the script a range that doesn't start at the beginning:
python3 cidr.py 10.0.0.5/24
Traceback (most recent call last):
...
ValueError: 10.0.0.5/24 has host bits set
A range starts where all its host bits are 0. In 10.0.0.5/24, the host part is the last octet, and 5 isn't 0, so Python refuses: "host bits set" means "this isn't the start of a range". You meant 10.0.0.0/24. Cloud consoles and Terraform give a similar error. The slider above handles this for you, by moving to the real start of the range: try typing 10.0.0.5.
A subnet that's too small. You're asked to create a cloud subnet for 20 servers, and you pick /28. Use the slider: how many addresses does /28 give you, and how many can servers use? 16 addresses, 14 usable, and on AWS only 11, after its 5. Not enough. Drag left one step: /27 gives 32 addresses, which fits 20 with room to grow. Changing a subnet's size after servers are using it usually means rebuilding it, so pick with room to spare.
Two networks with the same range. You're working from home on 192.168.1.0/24, and you connect to your office over a VPN (virtual private network), a private link to the office's network. The office printer is 192.168.1.50, but you can't reach it. Why? The office network is also 192.168.1.0/24. Your laptop sees 192.168.1.50, decides it's on your home network, and sends it there, where nothing has that address. When two networks have to connect, their ranges must not overlap. It's the same reason cloud networks need different ranges before you can join them, which comes up again in Lesson 7.
Where you are now
You can read a range like 10.0.0.0/16, work out how big it is, find its first and last addresses, split it into subnets, and tell whether an address belongs to it. That's the whole of the address side of networking. But an address only gets you to a machine, and one machine runs many programs at once. Lesson 4 is about ports: how data reaches the right program once it gets there, and what TCP, UDP and HTTP are.
Check yourself
In 192.168.1.0/24, what does the 24 mean?
How many addresses are in a /26?
Which subnet mask means the same as /24?
Is 10.0.5.20 inside 10.0.4.0/24?
You split 192.168.1.0/24 into two /25s. Where does the second one start?
Python says 10.0.0.5/24 has host bits set. What's wrong?
Key terms
- Subnet: a range of addresses that share the same network part. Devices in one subnet can talk directly.
- Network part and host part: the fixed bits that every address in the range shares, and the free bits that pick out one device.
- Host: any device with an address.
- CIDR (Classless Inter-Domain Routing): writing a range as a start address and a prefix length, like
10.0.0.0/16. - Prefix length: the number after the slash: how many bits are fixed. Bigger means a smaller range.
- Subnet mask: the same thing written like an address.
255.255.255.0is/24. - Broadcast address: the last address in a subnet, used to reach every device on it at once.
- Overlap: two ranges sharing some addresses. Networks that need to connect can't overlap.
Go deeper
- Python's documentation for the ipaddress module (opens in a new tab), if you'd like to do more with ranges in code.
- AWS's page on subnet sizing (opens in a new tab), which lists the five addresses it reserves. Lesson 7 comes back to it.