What Is a Subnet? β Definition and How It Works
Learn what a subnet is, how a mask divides an address into network and host parts, and why subnet-level blocking matters.
A subnet is a subdivision of an IP network. A subnet mask splits each address into a network part, shared by every host in the subnet, and a host part that identifies the individual host.
1. Network and Host Parts
For 192.168.10.42 with mask 255.255.255.0 β equivalently /24:
| Component | Value |
|---|---|
| Network | 192.168.10.0 |
| Host | .42 |
| Broadcast | 192.168.10.255 |
| Usable hosts | 254 |
| Total addresses | 256 |
The first address is the network identifier and the last is the broadcast address, so usable hosts are two fewer than the total.
2. Why Networks Are Subdivided
Broadcast containment. Broadcast traffic reaches every host in a subnet, so a very large flat network wastes capacity on it.
Routing. Routers forward between subnets, which is what makes a hierarchy of networks possible at all.
Security boundaries. Traffic between subnets passes a router where policy can be applied; traffic within one does not.
Allocation. Address space is delegated in subnets, matching organisational structure.
3. Reading a Mask
The mask is a run of ones followed by a run of zeroes. The count of ones is the prefix length.
| Mask | Prefix | Addresses |
|---|---|---|
| 255.0.0.0 | /8 | 16,777,216 |
| 255.255.0.0 | /16 | 65,536 |
| 255.255.255.0 | /24 | 256 |
| 255.255.255.128 | /25 | 128 |
| 255.255.255.252 | /30 | 4 |
Modern practice writes the prefix rather than the dotted mask, since the two are equivalent and the prefix is less error-prone.
4. Working With Subnets in Code
import ipaddress
net = ipaddress.ip_network("192.168.10.0/24")
print(net.netmask, net.num_addresses, net.network_address, net.broadcast_address)
print(ipaddress.ip_address("192.168.10.42") in net)
# Split one /24 into four /26 subnets
for sub in net.subnets(new_prefix=26):
print(sub)
strict=False is needed when constructing a network from a host address rather than a network address β the usual case when classifying an address you were given.
5. Why It Matters for Blocking and Rate Limiting
The practical point for anyone working with proxies. Defences frequently operate at subnet granularity rather than per address, because addresses within one subnet are usually controlled by one party.
So blocking a /24 blocks 256 addresses in one action, and rate limiting per /24 makes rotation within that subnet worthless β every request lands in the same bucket.
A pool of 500 addresses inside two /24s has two units of diversity, not 500. Counting addresses without checking their subnet distribution routinely overstates a pool's real variety by orders of magnitude.
6. Assessing Real Diversity
import ipaddress
from collections import Counter
def diversity(addresses):
nets = Counter(str(ipaddress.ip_network(f"{a}/24", strict=False)) for a in addresses)
return {"addresses": len(addresses), "distinct_24s": len(nets),
"largest_bucket": nets.most_common(1)[0] if nets else None}
Run this against any pool you are given. The gap between the address count and the distinct-subnet count is the honest measure of what rotation buys you.
7. Private and Reserved Subnets
| Subnet | Purpose |
|---|---|
| 10.0.0.0/8 | Private |
| 172.16.0.0/12 | Private |
| 192.168.0.0/16 | Private |
| 127.0.0.0/8 | Loopback |
| 169.254.0.0/16 | Link-local |
| 100.64.0.0/10 | Carrier-grade NAT |
These never appear as public internet sources, so an inbound request appearing to come from one indicates a forwarded-address header being trusted when it should not be.
8. Summary
A subnet divides an IP network using a mask that separates the shared network part from the host part, providing broadcast containment, routing boundaries, and delegated allocation.
Its importance for collection work is that blocking and rate limiting commonly apply per subnet, so rotating within one subnet gives no benefit β measure a proxy pool by the number of distinct subnets and ASNs it spans, not by how many addresses it contains.