Networking basics · Lesson 3 of 12 · about 25 minutes

Subnets and CIDR

How networks are built from ranges of addresses: what 10.0.0.0/16 means, how many addresses a range holds, how to split a range into subnets, and how to tell whether an address is inside one. Includes an interactive slider for exploring ranges.

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/24 or 10.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.1 is the network part, the street name. Every device in the house starts with it.
  • 23 is 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:

TEXT
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:

Try it: drag the prefix

network bits: 24, fixedhost bits: 8, free to change
Addresses in the range
256
Usable for devices
254
First address
192.168.1.0
Last address
192.168.1.255
Subnet mask
255.255.255.0
The range, written out
192.168.1.0/24

Room for a home network, a small office, or one cloud subnet.

"Usable" leaves out the first and last addresses, which are kept for the network itself.

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 /16 only the first two octets are fixed, and the range is 65,536 addresses. At /8 it's over 16 million.
  • Type 192.168.1.77 into the address box and look at the first address. The range still starts at 192.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:

PrefixAddressesWhere you'll see it
/321One single address, often in firewall rules
/2816A tiny subnet, for a few servers
/24256A home network, or one cloud subnet
/204,096A large subnet, for a busy cluster
/1665,536A whole cloud network, split into subnets
/816,777,216All 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:

TEXT
/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:

BASH
ipconfig getoption en0 subnet_mask

As in Lesson 2, try en1 if nothing prints. On a home network you'll most likely see:

OUTPUT
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:

SubnetThe 25th bitAddresses
192.168.1.0/250192.168.1.0 to 192.168.1.127
192.168.1.128/251192.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.

One /16 network, split into /24 subnetsA large box labelled 10.0.0.0/16, a cloud network with 65,536 addresses. Inside it are three smaller boxes: 10.0.0.0/24 for web servers, 10.0.1.0/24 for applications, and 10.0.2.0/24 for databases, each with 256 addresses. A dashed box shows 253 more /24 subnets still free, from 10.0.3.0/24 to 10.0.255.0/24. Below, the address 10.0.1.15 is shown inside the applications subnet, because its first three octets match.10.0.0.0/16: one cloud network, 65,536 addressesWeb servers10.0.0.0/2410.0.0.0 to10.0.0.255Applications10.0.1.0/2410.0.1.0 to10.0.1.255Databases10.0.2.0/2410.0.2.0 to10.0.2.255253 more, still free10.0.3.0/24all the way to10.0.255.0/2410.0.1.15starts with 10.0.1, so it's in the applications subnet
A cloud network is usually one big range, split into smaller subnets with different jobs. Each /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.20 inside 10.0.0.0/16? /16 fixes the first two octets, 10.0. It matches, so yes.
  • Is 10.0.5.20 inside 10.0.4.0/24? /24 fixes 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:

PYTHON
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:

BASH
python3 cidr.py 10.0.0.0/16 10.0.5.20 10.1.0.1
OUTPUT
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:

BASH
python3 cidr.py 172.16.0.0/12 172.31.255.1 172.32.0.1
OUTPUT
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:

BASH
python3 cidr.py 10.0.0.5/24
OUTPUT
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

  1. In 192.168.1.0/24, what does the 24 mean?

  2. How many addresses are in a /26?

  3. Which subnet mask means the same as /24?

  4. Is 10.0.5.20 inside 10.0.4.0/24?

  5. You split 192.168.1.0/24 into two /25s. Where does the second one start?

  6. 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.0 is /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