Every time you connect to Wi-Fi, your computer automatically gets four pieces of information. Without these four things, you have no internet.
Most people never see this happen. But understanding it is critical for AWS networking.
Let me show you what your computer needs and why.
IP Addresses Explained
An IP address is your computer's identity on the network.
Think of it like a mailing address. Without an address, no one can send you mail. Without an IP address, no one can send you data.
Structure:
IP address equals 32 bits (IPv4).
We display it as 4 octets (numbers 0-255):
192.168.1.100
Breaking it down:
192 . 168 . 1 . 100
↑ ↑ ↑ ↑
Octet 1 Octet 2 Octet 3 Octet 4
8 bits 8 bits 8 bits 8 bits
Each octet equals 8 bits. Total: 32 bits.
In binary:
11000000.10101000.00000001.01100100
↓
192.168.1.100
You never see the binary. But that is what computers use.
IP Address Hierarchy
IP addresses are organized hierarchically, like phone numbers with area codes.
Example: Acme Corporation
Acme Corporation: 10.0.0.0/8
├── New York Office: 10.20.0.0/16
│ ├── Sales: 10.20.55.0/24
│ │ └── Host: 10.20.55.44
│ ├── Engineering: 10.20.66.0/24
│ │ └── Host: 10.20.66.88
│ └── Marketing: 10.20.77.0/24
│ └── Host: 10.20.77.99
│
├── London Office: 10.30.0.0/16
│ ├── Sales: 10.30.55.0/24
│ ├── Engineering: 10.30.66.0/24
│ └── Marketing: 10.30.77.0/24
│
└── Tokyo Office: 10.40.0.0/16
├── Sales: 10.40.55.0/24
├── Engineering: 10.40.66.0/24
└── Marketing: 10.40.77.0/24
Looking at IP 10.30.55.50:
- First octet (10): Acme Corporation
- Second octet (30): London Office
- Third octet (55): Sales Team
- Fourth octet (50): Specific host
This hierarchy helps routers make forwarding decisions efficiently.
AWS Example:
When you create a VPC, you define this hierarchy:
import boto3
ec2 = boto3.client('ec2')
# Create VPC (top of hierarchy)
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
vpc_id = vpc['Vpc']['VpcId']
# Create subnets (subdivisions)
public_subnet = ec2.create_subnet(
VpcId=vpc_id,
CidrBlock='10.0.1.0/24', # Public subnet
AvailabilityZone='us-east-1a'
)
private_subnet = ec2.create_subnet(
VpcId=vpc_id,
CidrBlock='10.0.2.0/24', # Private subnet
AvailabilityZone='us-east-1a'
)
database_subnet = ec2.create_subnet(
VpcId=vpc_id,
CidrBlock='10.0.3.0/24', # Database subnet
AvailabilityZone='us-east-1b'
)
You just created IP address hierarchy in AWS.
Subnet Masks: Understanding Slash Notation
Subnet masks define the size of your network.
What does /24 mean?
The number after the slash tells you how many bits define the network portion.
Example: 10.20.55.0/24
/24 means first 24 bits define the network. Last 8 bits define hosts.
10 . 20 . 55 . 0 / 24
↑ ↑ ↑ ↑
8 bits 8 bits 8 bits 8 bits
First 24 bits = Network (10.20.55)
Last 8 bits = Hosts (0-255)
How many hosts?
8 bits for hosts equals 2^8 equals 256 addresses.
Network: 10.20.55.0/24
Can have: 10.20.55.0 through 10.20.55.255
(Actually 254 usable hosts. First and last are reserved.)
Common Subnet Sizes
/24 Network
Network: 10.20.55.0/24
First 24 bits = Network
Last 8 bits = Hosts
Usable range: 10.20.55.1 - 10.20.55.254
Total hosts: 254
AWS Example: Small subnet for a few EC2 instances
/16 Network
Network: 10.20.0.0/16
First 16 bits = Network
Last 16 bits = Hosts
Usable range: 10.20.0.1 - 10.20.255.254
Total hosts: 65,534
AWS Example: Entire VPC or large subnet
/8 Network
Network: 10.0.0.0/8
First 8 bits = Network
Last 24 bits = Hosts
Usable range: 10.0.0.1 - 10.255.255.254
Total hosts: 16,777,214
AWS Example: Massive corporate network
How Hosts Use Subnet Masks
Subnet masks help hosts determine: "Is the destination on my network or a foreign network?"
Example:
Host A:
IP: 10.1.1.22
Subnet Mask: 255.255.255.0 (which is /24)
Host A wants to send to: 10.1.1.33
Decision process:
My IP: 10.1.1.22
My network: 10.1.1.x (first 24 bits)
Destination: 10.1.1.33
Their network: 10.1.1.x (first 24 bits)
Same network? YES
Action: ARP for destination IP directly
Host A wants to send to: 192.168.1.44
Decision process:
My IP: 10.1.1.22
My network: 10.1.1.x
Destination: 192.168.1.44
Their network: 192.168.1.x
Same network? NO
Action: Send to default gateway (router)
This decision happens automatically. Every single packet.
Public vs Private IP Addresses
Not all IP addresses are equal. Some are public. Some are private.
Private IP Ranges (RFC 1918):
10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
192.168.0.0/16 (192.168.0.0 - 192.168.255.255)
Private IPs:
- Used inside networks
- Not routable on internet
- Can be reused (your home, my home, both use 192.168.1.x)
Public IPs:
- Unique across entire internet
- Routable on internet
- Must be obtained from ISP or cloud provider
AWS Example:
# Private IP (VPC internal)
ec2.run_instances(
ImageId='ami-xxxxx',
InstanceType='t3.micro',
SubnetId=private_subnet_id, # Gets private IP automatically
MaxCount=1,
MinCount=1
)
# Public IP (internet-accessible)
allocation = ec2.allocate_address(Domain='vpc')
public_ip = allocation['PublicIp']
# Associate public IP with instance
ec2.associate_address(
InstanceId=instance_id,
AllocationId=allocation['AllocationId']
)
Your EC2 instance now has:
- Private IP: 10.0.1.50 (internal VPC communication)
- Public IP: 54.123.45.67 (internet communication)
ARP: Address Resolution Protocol
ARP links Layer 3 (IP addresses) to Layer 2 (MAC addresses).
The Problem:
Your computer knows the destination IP address. But it needs the MAC address to send the frame.
The Solution: ARP
ARP resolves IP addresses to MAC addresses.
How ARP Works
Scenario:
Host A: 10.1.1.22 (MAC: AA:AA)
Host B: 10.1.1.33 (MAC: BB:BB)
Host A wants to send to Host B but does not know BB:BB MAC address.
Step 1: ARP Request (Broadcast)
Host A sends:
ARP Request:
Who has 10.1.1.33?
Tell 10.1.1.22 at MAC AA:AA
Layer 2 Header:
Source MAC: AA:AA
Destination MAC: FF:FF:FF:FF:FF:FF (broadcast)
Broadcast means everyone on the network receives it.
Step 2: Host B Responds
Host B sees the request:
"That is my IP (10.1.1.33). I will respond."
Host B sends:
ARP Response:
10.1.1.33 is at MAC BB:BB
Layer 2 Header:
Source MAC: BB:BB
Destination MAC: AA:AA (unicast - directly to Host A)
Step 3: Host A Updates ARP Cache
Host A stores:
ARP Cache:
10.1.1.33 → BB:BB
Now Host A can send data directly to Host B.
Future communication:
Host A already has BB:BB in its ARP cache. No ARP needed. Send immediately.
View Your ARP Cache
Linux/Mac:
$ arp -a
Output:
? (10.1.1.1) at e4:e4:e4:e4:e4:e4 on en0 ifscope [ethernet]
? (10.1.1.33) at bb:bb:bb:bb:bb:bb on en0 ifscope [ethernet]
Windows:
C:\> arp -a
This shows all IP to MAC mappings your computer learned.
Python example:
import subprocess
import re
def get_arp_table():
"""Get ARP table entries"""
result = subprocess.run(['arp', '-a'], capture_output=True, text=True)
entries = []
for line in result.stdout.split('\n'):
# Parse IP and MAC from output
match = re.search(r'\((\d+\.\d+\.\d+\.\d+)\) at ([0-9a-f:]+)', line)
if match:
ip = match.group(1)
mac = match.group(2)
entries.append({'ip': ip, 'mac': mac})
return entries
# Get and display ARP table
arp_table = get_arp_table()
for entry in arp_table:
print(f"{entry['ip']} → {entry['mac']}")
DNS: Domain Name System
DNS converts human-readable names to IP addresses.
The Problem:
Humans think in names: aws.amazon.com
Computers need IP addresses: 52.94.133.131
The Solution: DNS
DNS translates names to IP addresses automatically.
How DNS Works
Example: Browsing to www.google.com
Step 1: Browser Checks Cache
Your computer checks: "Do I already know google.com's IP?"
If yes: Use cached IP.
If no: Continue to Step 2.
Step 2: Query DNS Server
Your computer asks DNS server:
Query: What is the IP address for www.google.com?
Step 3: DNS Server Responds
Response: www.google.com is at 142.250.80.46
Step 4: Browser Connects
Browser now connects to 142.250.80.46 using HTTP/HTTPS.
You never saw the IP address. But it was used.
DNS in Python
import socket
# Resolve domain name to IP
hostname = 'aws.amazon.com'
ip_address = socket.gethostbyname(hostname)
print(f"{hostname} → {ip_address}")
Output:
aws.amazon.com → 52.94.133.131
Reverse DNS (IP to hostname):
import socket
# Resolve IP to hostname
ip = '8.8.8.8'
hostname = socket.gethostbyaddr(ip)
print(f"{ip} → {hostname[0]}")
Output:
8.8.8.8 → dns.google
DNS in AWS: Route 53
Route 53 is AWS's DNS service.
Create DNS record:
import boto3
route53 = boto3.client('route53')
# Create A record (domain → IP)
response = route53.change_resource_record_sets(
HostedZoneId='Z1234567890ABC',
ChangeBatch={
'Changes': [{
'Action': 'CREATE',
'ResourceRecordSet': {
'Name': 'api.example.com',
'Type': 'A',
'TTL': 300,
'ResourceRecords': [{'Value': '54.123.45.67'}]
}
}]
}
)
print(f"Created DNS record: api.example.com → 54.123.45.67")
Now when users visit api.example.com, DNS returns your EC2 instance IP.
DHCP: Dynamic Host Configuration Protocol
DHCP automatically configures network settings on your computer.
The Problem:
Every host needs four settings:
- IP Address
- Subnet Mask
- Default Gateway
- DNS Server
Manually configuring these on every device is tedious.
The Solution: DHCP
DHCP server automatically assigns all four settings when you connect to a network.
How DHCP Works
Step 1: DHCP Discover
Your computer connects to network and broadcasts:
"Is there a DHCP server here?"
Step 2: DHCP Offer
DHCP server responds:
"Yes. Here are your settings:
- IP Address: 192.168.1.50
- Subnet Mask: 255.255.255.0
- Default Gateway: 192.168.1.1
- DNS Server: 8.8.8.8
Valid for 24 hours."
Step 3: DHCP Request
Your computer responds:
"I accept these settings."
Step 4: DHCP Acknowledge
DHCP server confirms:
"Confirmed. They are yours for 24 hours."
Your computer now has all four settings. You have internet.
The Four Things Every Host Needs
This is critical. Every host on the internet needs these four settings:
1. IP Address
Your identity on the network.
Example: 192.168.1.50
2. Subnet Mask
Defines your network size.
Example: 255.255.255.0 (or /24)
Tells you: "My network is 192.168.1.x"
3. Default Gateway
Router's IP address on your network.
Example: 192.168.1.1
Your way out to reach other networks.
4. DNS Server
Converts domain names to IP addresses.
Example: 8.8.8.8 (Google DNS)
Allows you to browse by name instead of IP.
View Your Network Settings
Linux/Mac:
$ ifconfig en0
Output:
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet 192.168.1.50 netmask 0xffffff00 broadcast 192.168.1.255
View gateway:
$ netstat -nr | grep default
Output:
default 192.168.1.1 UGSc en0
View DNS servers:
$ cat /etc/resolv.conf
Output:
nameserver 8.8.8.8
nameserver 8.8.4.4
Windows:
C:\> ipconfig /all
Shows all four settings.
DHCP in AWS
AWS VPCs have built-in DHCP.
When you launch an EC2 instance, it automatically gets:
- Private IP address (from subnet range)
- Subnet mask (from subnet configuration)
- Default gateway (VPC router)
- DNS server (AWS-provided or custom)
Custom DHCP Options Set:
import boto3
ec2 = boto3.client('ec2')
# Create DHCP options set
dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[
{
'Key': 'domain-name-servers',
'Values': ['8.8.8.8', '8.8.4.4'] # Use Google DNS
},
{
'Key': 'domain-name',
'Values': ['example.com']
}
]
)
dhcp_options_id = dhcp_options['DhcpOptions']['DhcpOptionsId']
# Associate with VPC
ec2.associate_dhcp_options(
DhcpOptionsId=dhcp_options_id,
VpcId=vpc_id
)
print(f"Custom DHCP options applied to VPC")
Now all EC2 instances in this VPC use Google DNS instead of AWS default.
HTTP and HTTPS
HTTP (HyperText Transfer Protocol) is how web browsers communicate with web servers.
HTTP Request:
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
This is what your browser sends when you visit a website.
HTTP Response:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
<html>
<body>
<h1>Welcome</h1>
</body>
</html>
This is what the server sends back.
HTTP Methods
GET: Retrieve data
GET /api/users/123 HTTP/1.1
POST: Send data
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "John", "email": "john@example.com"}
PUT: Update data
PUT /api/users/123 HTTP/1.1
Content-Type: application/json
{"name": "John Updated"}
DELETE: Remove data
DELETE /api/users/123 HTTP/1.1
HTTP in Python
import requests
# GET request
response = requests.get('https://api.github.com/users/octocat')
print(f"Status: {response.status_code}")
print(f"Data: {response.json()}")
# POST request
data = {'name': 'Test Repository'}
response = requests.post(
'https://api.github.com/user/repos',
json=data,
headers={'Authorization': 'token YOUR_TOKEN'}
)
print(f"Created: {response.json()['name']}")
HTTPS: HTTP Secure
HTTPS equals HTTP inside an encrypted tunnel (TLS/SSL).
How it works:
Step 1: TLS Handshake
Client and server establish encryption keys.
Step 2: Encrypted Tunnel
All HTTP traffic flows through encrypted tunnel.
Step 3: Data Exchange
[Encrypted] GET /api/data HTTP/1.1
[Encrypted] HTTP/1.1 200 OK
No one in the middle can read the data.
Port numbers:
- HTTP: Port 80
- HTTPS: Port 443
AWS Example:
Application Load Balancer with HTTPS:
import boto3
elbv2 = boto3.client('elbv2')
# Create HTTPS listener
response = elbv2.create_listener(
LoadBalancerArn='arn:aws:elasticloadbalancing:...',
Protocol='HTTPS',
Port=443,
Certificates=[{
'CertificateArn': 'arn:aws:acm:us-east-1:...'
}],
DefaultActions=[{
'Type': 'forward',
'TargetGroupArn': 'arn:aws:elasticloadbalancing:...'
}]
)
print("HTTPS listener created on port 443")
Your load balancer now handles HTTPS traffic with TLS encryption.
TCP and UDP
Layer 4 (Transport Layer) uses two protocols:
TCP (Transmission Control Protocol)
Reliable transmission:
- Confirms delivery
- Retransmits if lost
- Guarantees order
- Slower but reliable
Used for:
- HTTP/HTTPS
- SSH
- Email (SMTP)
- File transfers (FTP)
UDP (User Datagram Protocol)
Fast transmission:
- No confirmation
- No retransmission
- No ordering guarantee
- Faster but unreliable
Used for:
- DNS queries
- Video streaming
- Online gaming
- VoIP calls
When to use which:
Need reliability? Use TCP.
Need speed? Use UDP.
Protocol Summary
ARP (Layer 2):
- Resolves IP to MAC
- Used for local network communication
- Broadcast request, unicast response
DNS (Layer 7):
- Resolves domain names to IPs
- Uses UDP port 53 (usually)
- Critical for web browsing
DHCP (Layer 7):
- Auto-configures network settings
- Uses UDP ports 67/68
- Provides IP, mask, gateway, DNS
HTTP (Layer 7):
- Web communication
- TCP port 80
- Request/response model
HTTPS (Layer 7):
- Secure web communication
- TCP port 443
- HTTP inside TLS tunnel
TCP (Layer 4):
- Reliable transmission
- Connection-oriented
- Used by HTTP, SSH, FTP
UDP (Layer 4):
- Fast transmission
- Connectionless
- Used by DNS, streaming
Complete AWS Networking Example
Let me tie everything together with a complete AWS setup:
import boto3
ec2 = boto3.client('ec2')
# 1. Create VPC (IP addressing)
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
vpc_id = vpc['Vpc']['VpcId']
print(f"VPC created: {vpc_id} with range 10.0.0.0/16")
# 2. Create subnet (subnet mask /24)
subnet = ec2.create_subnet(
VpcId=vpc_id,
CidrBlock='10.0.1.0/24',
AvailabilityZone='us-east-1a'
)
subnet_id = subnet['Subnet']['SubnetId']
print(f"Subnet created: {subnet_id} with range 10.0.1.0/24")
# 3. Create Internet Gateway (default gateway)
igw = ec2.create_internet_gateway()
igw_id = igw['InternetGateway']['InternetGatewayId']
ec2.attach_internet_gateway(InternetGatewayId=igw_id, VpcId=vpc_id)
print(f"Internet Gateway created and attached: {igw_id}")
# 4. Create route table (routing)
route_table = ec2.create_route_table(VpcId=vpc_id)
rt_id = route_table['RouteTable']['RouteTableId']
# Add default route to Internet Gateway
ec2.create_route(
RouteTableId=rt_id,
DestinationCidrBlock='0.0.0.0/0',
GatewayId=igw_id
)
# Associate with subnet
ec2.associate_route_table(RouteTableId=rt_id, SubnetId=subnet_id)
print(f"Route table created with default route to IGW")
# 5. Configure DHCP options (DNS)
dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[{
'Key': 'domain-name-servers',
'Values': ['8.8.8.8', '8.8.4.4']
}]
)
dhcp_id = dhcp_options['DhcpOptions']['DhcpOptionsId']
ec2.associate_dhcp_options(DhcpOptionsId=dhcp_id, VpcId=vpc_id)
print(f"DHCP options configured with Google DNS")
# 6. Create security group (Layer 4 rules)
sg = ec2.create_security_group(
GroupName='web-server-sg',
Description='Allow HTTP and HTTPS',
VpcId=vpc_id
)
sg_id = sg['GroupId']
# Allow HTTPS (TCP port 443)
ec2.authorize_security_group_ingress(
GroupId=sg_id,
IpPermissions=[
{
'IpProtocol': 'tcp',
'FromPort': 443,
'ToPort': 443,
'IpRanges': [{'CidrIp': '0.0.0.0/0'}]
},
{
'IpProtocol': 'tcp',
'FromPort': 80,
'ToPort': 80,
'IpRanges': [{'CidrIp': '0.0.0.0/0'}]
}
]
)
print(f"Security group created allowing HTTP/HTTPS")
# 7. Launch EC2 instance
response = ec2.run_instances(
ImageId='ami-0c55b159cbfafe1f0', # Amazon Linux 2
InstanceType='t3.micro',
SubnetId=subnet_id,
SecurityGroupIds=[sg_id],
MinCount=1,
MaxCount=1
)
instance_id = response['Instances'][0]['InstanceId']
print(f"EC2 instance launched: {instance_id}")
# The instance automatically gets via DHCP:
# - IP: 10.0.1.x (from subnet range)
# - Subnet Mask: 255.255.255.0 (/24)
# - Gateway: 10.0.1.1 (VPC router)
# - DNS: 8.8.8.8, 8.8.4.4 (from DHCP options)
This creates a complete working network with all the concepts we covered.
Troubleshooting Checklist
Problem: "Cannot reach internet from EC2 instance"
Check 1: Does instance have IP address?
$ aws ec2 describe-instances --instance-ids i-xxxxx
Look for PrivateIpAddress field.
Check 2: Does subnet have route to Internet Gateway?
$ aws ec2 describe-route-tables --filters "Name=association.subnet-id,Values=subnet-xxxxx"
Look for route: 0.0.0.0/0 → igw-xxxxx
Check 3: Does instance have public IP (if needed)?
$ aws ec2 describe-instances --instance-ids i-xxxxx
Look for PublicIpAddress field.
Check 4: Do security groups allow traffic?
$ aws ec2 describe-security-groups --group-ids sg-xxxxx
Check outbound rules allow destination ports.
Check 5: Can instance resolve DNS?
$ ssh ec2-user@instance
$ nslookup google.com
Should return IP address.
Key Takeaways
IP Addresses:
- 32-bit identifiers (IPv4)
- Organized hierarchically
- Public vs private ranges
Subnet Masks:
- Define network size
- /24 = 254 hosts
- /16 = 65,534 hosts
- Help determine local vs foreign
Four Things Every Host Needs:
- IP Address (identity)
- Subnet Mask (network size)
- Default Gateway (way out)
- DNS Server (name resolution)
Essential Protocols:
- ARP: IP to MAC resolution
- DNS: Name to IP resolution
- DHCP: Auto-configuration
- HTTP/HTTPS: Web traffic
- TCP: Reliable transport
- UDP: Fast transport
AWS provides all of these automatically in VPCs.
What Comes Next: Part 4
You now understand IP addresses, protocols, and how everything is configured.
Part 4 ties it all together with a complete data flow example.
In Part 4, I will show:
- Complete packet journey from your browser to AWS
- Every protocol in action
- Every header at every layer
- Every table lookup
- How DNS, ARP, routing, and switching work together
- Real-world troubleshooting scenario
Coming next.
Your Turn
What networking concept still confuses you?
Are there protocols I should cover in more detail?
Drop a comment. I am building this series based on your questions.
This series:
- Part 1: OSI Model Explained
- Part 2: Switches and Routers
- Part 3: IP Addresses and Protocols (this article)
- Part 4: Complete Data Flow (next)
Follow me for the final part and daily AWS learning.
Resources
Practice Labs:
AWS Documentation:
RFCs (Official Specs):
Stella Achar Oiro is a software developer with clinical healthcare experience, currently studying for AWS certifications while building HIPAA-compliant cloud infrastructure. She shares her learning journey to help other developers transition to cloud engineering.
This is Part 3 of a 4-part series on Networking Fundamentals for Cloud Engineers.
Top comments (0)