Subnets Do Not Catch Fish!

Despite the rumors, I can definitively state, for the record, that subnets do not catch fish, unless one uses the term "fish" to mean "newbies"!

The Context

I was in the process of setting up a demo Amazon Web Services (AWS) Elastic Cloud 2 (EC2) instance, and came across a situation that I believe might stump many PHP developers. My educative instincts kicked in when I went to launch the instance, but was stopped because I hadn't yet defined a VPC (Virtual Private Cloud). The potential show stopper for PHP developers wanting to launch a PHP website in a cloud container is the general lack of understanding of IP addressing and of subnets in particular.

IP Addressing

In this article I won't get into IPv6 (Internet Protocol version 6) as it's an entirely different subject! Instead I'll stick with IPv4 as that's what I saw when launching my instance.

IPv6 Essentials As an aside, Silvia Hagen, a student of Laura Chapell, wrote an excellent book on IPv6. You can find more information on it here: IPv6 Essentials, 3rd Edition.

Most of you know the history of TCP/IP (Transmission Control Protocol/Internet Protocol) networking. Originally a US Department of Defense project, TCP/IP originated from ARPANET research in the 1970s. Adopted as ARPANET's standard in 1983, TCP/IP became the foundation of what we now know of as the Internet.

IP addressing refers to the assignment of numbers to Internet servers or other end points.

Class Act

In its original conception, IP address blocks were visualized as being broken down into three classes:

In addition, a Class D was devised for multicasting, and a Class E for "experimentation." A more recent addition to the class system was the introduction of Private Networks, which I'll address later in this article.

Where it gets interesting is how subnets work, and how they apply to the different address classes. But, before diving into this, we need to have a look at what's happening at the binary bit level.

32 Bits

IPv4 addresses take the form of 4 numbers, from 0 to 255, represented in a "dot" format: nnn.nnn.nnn.nnn. It so happens that each number in this dot format represents 8 bits (i.e. a byte).

Here's a table that summarizes the range of various classes:

Class First Octet* Range Leading Bits Default Mask Purpose
A1–1260/8Very large networks
B128–19110/16Medium-large networks
C192–223110/24Small networks
D224–2391110N/AMulticast
E240–2551111N/AExperimental/reserved

* An "octet" refers to 8 consecutive bits. A "host" is any device that needs to be contactable via the Internet (e.g., a server, a PC, or any device with a network interface that wants to be Internet accessible).

How Subnet Masks Work

The idea of a subnet mask is actually absurdly simple. A subnet mask is a 32 bit number that's applied against an incoming IP address using a logical AND operation. This allows IP routers to determine which portion of the IP address refers to the network and which to the hosts. The value that follows the slash ("/") an IPv4 address range represents the number of bits that represents the network portion of that address range. Here are three examples where the network portion matches full 8-bit bytes:

Class A, B, C subnets
Class A, B, C subnets
Private Address Blocks Private address blocks (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) are reserved IP ranges for internal networks. The key feature of Private Address Blocks is that IP routers will refuse to route these addresses through the Internet.

Most of us encounter private address blocks when setting up home routers. When you activate the NAT feature, the router "translates" the IP addresses of packets originating from inside the privately addressed into a valid routable address.

Back to AWS

Finally I can circle back to the entire reason behind writing this article! When setting up my AWS EC2 instance, I needed to set up a VPC. This makes complete sense in that in most instances you might be building an orchestrated system of cloud containers that privately exchange information.

Here's what I saw when setting up the EC2 instance:

AWS EC2 VPC CIDR setup dialog
AWS VPC CIDR configuration dialog

Breaking this down, the higher 16 bits (i.e. 2 bytes) of the larger VPC address block represent the network portion of the address. This leaves the lower 16 bits to the host portion. This means that this VPC can support IP addresses that range from 172.31.0.1 all the way up to 172.31.255.255. However, the AWS interface also asked what subnets within that address range were needed. Fortunately Amazon creates defaults, but I strongly feel this is where confusion can creep in.

Subnet Masks That Cross the Byte Boundary

Have a look at the next dialog box where you can set up subnets:

AWS EC2 Subnet CIDR setup dialog
AWS Subnet CIDR configuration dialog

You'll notice that the number of bits representing the network do not fall evenly within the "byte boundary." In order to determine the range of allowed host IP addresses within this subnet, you'll need to go down to the bit level ... so here goes! 172.31.32.0/20 allocates the first 20 bits to the network and the remaining 12 bits to the hosts. Here's how it can be visualized in binary:

10101100.00011111.00100000.00000000

Accordingly, with this subnet mask, IP addresses can range from 10101100.00011111.00100000.00000001 to 10101100.00011111.00101111.11111111 or, using decimal numbers, 172.31.32.0 to 172.31.47.255.

Final Words

A thorough understanding of networking is a must for any PHP developer wishing to move towards being a so-called full stack developer. For the most comprehensive work on TCP/IP networking, and digital communications technologies in general, have a look at Data and Computer Communications, 10th edition by William Stallings. He also provides coverage of IPv6, although I would recommend having a look at IPv6 Essentials by Silvia Hagen, referenced towards the start of this article.