Module 16: Real-World Networking Scenarios
This module walks through complete networking scenarios, tracing packets from source to destination. Understanding these flows is crucial for debugging, architecture design, and interviews.
Estimated Time : 4-5 hours
Difficulty : Intermediate to Advanced
Prerequisites : All previous modules
Quick Reference: IP Addressing Fundamentals
Before diving into scenarios, let’s refresh the key concepts you’ll see throughout.
Private vs Public IP Addresses
Private IPs (RFC 1918) Not routable on the internet - used inside your network only.Range CIDR Typical Use 10.0.0.0 - 10.255.255.25510.0.0.0/8 Cloud VPCs, enterprises 172.16.0.0 - 172.31.255.255172.16.0.0/12 Medium organizations 192.168.0.0 - 192.168.255.255192.168.0.0/16 Home networks
Key insight : Millions of networks can use 192.168.1.1 simultaneously - they’re isolated!
Public IPs Globally unique and routable - your identity on the internet.
Assigned by ISPs (who get them from regional registries)
Required for any internet-facing service
Expensive and limited (IPv4 exhaustion)
Examples : 8.8.8.8 (Google DNS), 151.101.1.140 (Reddit)
CIDR Notation Cheat Sheet
CIDR tells you how many bits are for the network vs hosts:
192.168.1.0/24
└── 24 bits for network = 8 bits for hosts = 256 addresses (254 usable)
10.0.0.0/16
└── 16 bits for network = 16 bits for hosts = 65,536 addresses
10.0.0.0/8
└── 8 bits for network = 24 bits for hosts = 16.7 million addresses
CIDR Subnet Mask Usable Hosts Quick Math /8 255.0.0.0 16,777,214 2^24 - 2 /16 255.255.0.0 65,534 2^16 - 2 /24 255.255.255.0 254 2^8 - 2 /28 255.255.255.240 14 2^4 - 2 /32 255.255.255.255 1 Single host
Why -2? First address = Network ID (192.168.1.0), Last address = Broadcast (192.168.1.255). Neither can be assigned to a host.
Special Addresses You’ll See
Address Meaning 0.0.0.0”Any address” / default route 127.0.0.1Localhost (loopback) 255.255.255.255Broadcast to entire network 169.254.x.xLink-local (DHCP failed) 224.0.0.0/4Multicast range
NAT - The Bridge Between Private & Public
Your Home Network Internet
┌─────────────────┐ ┌─────────────┐
│ PC: 192.168.1.5 │ │ │
│ Phone: .6 │──► NAT ──► │ Website │
│ TV: .7 │ Router │ 8.8.8.8 │
└─────────────────┘ │ └─────────────┘
Private IPs │
▼
Public: 203.0.113.50
(One IP for all devices!)
NAT translates private IPs to your single public IP, tracking connections so responses return correctly.
Scenario 1: Typing “google.com” in Your Browser
This is the classic interview question. Let’s trace every step in detail.
The Setup
You: Laptop at home
Network: 192.168.1.0/24
Your IP: 192.168.1.10
Router: 192.168.1.1 (NAT gateway)
Public IP: 203.0.113.50
Step-by-Step Flow
Browser Parses URL
https://google.com
Protocol: HTTPS (port 443)
Host: google.com
Path: / (root)
DNS Resolution
Browser Cache Check: Cache lookup: google.com → Not found
OS Cache Check: OS DNS cache: google.com → Not found
DNS Query: Your PC (192.168.1.10:52431)
→ DNS Query for google.com
→ Router (192.168.1.1)
→ NAT translation
→ Public IP (203.0.113.50:10001)
→ ISP DNS Resolver (8.8.8.8)
Resolver → Root Server: "Where's .com?"
Root → Resolver: "Try TLD servers at x.gtld-servers.net"
Resolver → .com TLD: "Where's google.com?"
TLD → Resolver: "Try ns1.google.com"
Resolver → ns1.google.com: "What's google.com A record?"
ns1.google.com → Resolver: "142.250.190.46"
Resolver → Your PC: "142.250.190.46" (cached for TTL)
TCP Connection (3-Way Handshake)
Your PC Google
192.168.1.10:52432 142.250.190.46:443
│ │
│──── SYN (seq=100) ────────────────►│
│ │
│◄─── SYN-ACK (seq=300, ack=101) ───│
│ │
│──── ACK (seq=101, ack=301) ───────►│
│ │
│ Connection Established │
At your router (NAT translation): NAT Table Entry:
192.168.1.10:52432 → 203.0.113.50:10002 → 142.250.190.46:443
TLS Handshake
Client Server
│ │
│──── ClientHello ──────────────────►│
│ (supported ciphers, │
│ TLS version, random) │
│ │
│◄─── ServerHello ──────────────────│
│ (chosen cipher, certificate) │
│ │
│ Verify certificate chain │
│ (google.com → CA → Root CA) │
│ │
│──── Key Exchange ─────────────────►│
│ (ECDHE parameters) │
│ │
│◄─── Key Exchange ─────────────────│
│ │
│ Both derive session keys │
│ │
│──── Finished ─────────────────────►│
│◄─── Finished ─────────────────────│
│ │
│ Encrypted connection ready │
HTTP Request
Inside the encrypted TLS tunnel: GET / HTTP/2
Host : google.com
User-Agent : Chrome/120.0
Accept : text/html
Accept-Encoding : gzip, br
Cookie : NID=123...
Google's Infrastructure
Internet → Google's Edge (Anycast)
│
▼
Load Balancer
│
┌───────┼───────┐
▼ ▼ ▼
Server Server Server
(generates response)
HTTP Response
HTTP/2 200 OK
Content-Type : text/html
Content-Encoding : gzip
Cache-Control : private, max-age=0
<!doctype html> < html > ...
Packet Journey Back
Google (142.250.190.46:443)
→ Internet backbone
→ ISP
→ Your router (203.0.113.50)
→ NAT reverse translation
→ Your PC (192.168.1.10:52432)
Browser Renders Page
Parse HTML
Fetch CSS, JS, images (parallel connections)
Execute JavaScript
Render DOM
Display page
Packet at Each Layer
Application: GET / HTTP/2
Host: google.com
───────────────────────────
Transport: TCP Segment
Src Port: 52432
Dst Port: 443
Seq: 101, Ack: 301
───────────────────────────
Network: IP Packet
Src IP: 192.168.1.10 → (after NAT) 203.0.113.50
Dst IP: 142.250.190.46
TTL: 64
───────────────────────────
Data Link: Ethernet Frame
Src MAC: AA:BB:CC:DD:EE:FF (your PC)
Dst MAC: 11:22:33:44:55:66 (router)
───────────────────────────
Physical: Electrical signals / Radio waves
Scenario 2: Two Offices with Same Private IPs Accessing the Internet
The Question
“If Company A uses 192.168.1.0/24 and Company B also uses 192.168.1.0/24, how do they both access the same website?”
The Setup
Company A: Company B:
┌────────────────────────┐ ┌────────────────────────┐
│ 192.168.1.0/24 │ │ 192.168.1.0/24 │
│ │ │ │
│ PC: 192.168.1.5 │ │ PC: 192.168.1.5 │
│ (same IP!) │ │ (same IP!) │
│ │ │ │
│ NAT Gateway │ │ NAT Gateway │
│ Public: 203.0.113.10 │ │ Public: 198.51.100.20 │
└───────────┬────────────┘ └───────────┬────────────┘
│ │
└───────────────┬───────────────────┘
│
┌────┴────┐
│ Internet │
└────┬────┘
│
┌────┴────┐
│ Server │
│ 8.8.8.8 │
└─────────┘
How It Works
Step 1: Company A’s PC sends request
Original packet (inside Company A's network):
Src IP: 192.168.1.5
Dst IP: 8.8.8.8
After NAT (on the internet):
Src IP: 203.0.113.10 ← Company A's public IP
Src Port: 10001 ← Assigned by NAT
Dst IP: 8.8.8.8
Step 2: Company B’s PC sends request (at same time)
Original packet (inside Company B's network):
Src IP: 192.168.1.5 ← Same private IP!
Dst IP: 8.8.8.8
After NAT (on the internet):
Src IP: 198.51.100.20 ← Company B's public IP (different!)
Src Port: 20001 ← Assigned by NAT
Dst IP: 8.8.8.8
Step 3: Server sees two different sources
From the server's perspective:
Request 1: From 203.0.113.10:10001 (Company A)
Request 2: From 198.51.100.20:20001 (Company B)
These are completely different - no conflict!
Step 4: Responses route correctly
Response to 203.0.113.10:10001
→ Company A's NAT gateway
→ Lookup: port 10001 → 192.168.1.5:original_port
→ Delivered to Company A's PC
Response to 198.51.100.20:20001
→ Company B's NAT gateway
→ Lookup: port 20001 → 192.168.1.5:original_port
→ Delivered to Company B's PC
The Key Insight
Private IPs are only significant within their own network. Once packets leave through NAT, the private IP is replaced with the unique public IP. The internet never sees 192.168.1.5 - it only sees the public IPs.This is why millions of home networks can all use 192.168.1.0/24 without any conflict!
Scenario 3: Private Subnet Accessing the Internet (AWS)
The Setup
┌─────────────────────────────────────────────────────────────┐
│ AWS VPC │
│ 10.0.0.0/16 │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Public Subnet │ │
│ │ 10.0.1.0/24 │ │
│ │ │ │
│ │ ┌────────────────────┐ │ │
│ │ │ NAT Gateway │ │ │
│ │ │ 10.0.1.100 │ │ │
│ │ │ EIP: 54.x.x.x │ │ │
│ │ └─────────┬──────────┘ │ │
│ │ │ │ │
│ └──────────────┼──────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────┼──────────────────────────────────────────┐ │
│ │ │ Private Subnet │ │
│ │ │ 10.0.2.0/24 │ │
│ │ │ │ │
│ │ ┌─────────┴────────────────┐ │ │
│ │ │ App Server │ │ │
│ │ │ 10.0.2.50 │ │ │
│ │ │ (No public IP) │ │ │
│ │ └──────────────────────────┘ │ │
│ │ │ │
│ │ Route Table: │ │
│ │ 10.0.0.0/16 → local │ │
│ │ 0.0.0.0/0 → nat-xxx │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Internet Gateway │ │
│ └────────┬─────────┘ │
│ │ │
└─────────────┼────────────────────────────────────────────────┘
│
Internet
The Flow: App Server Updating Packages
Step 1: App server needs to download update
App Server (10.0.2.50) → apt-get update → needs packages.ubuntu.com
Step 2: Route table lookup
Destination: 91.189.88.152 (packages.ubuntu.com)
Route table check:
10.0.0.0/16 → local? No match
0.0.0.0/0 → nat-xxx ← Match! Send to NAT Gateway
Step 3: Packet sent to NAT Gateway
Packet arrives at NAT Gateway (10.0.1.100):
Src: 10.0.2.50:54321
Dst: 91.189.88.152:443
Step 4: NAT Gateway translates
NAT Gateway rewrites source:
Src: 54.x.x.x:10001 ← Elastic IP
Dst: 91.189.88.152:443
NAT table entry:
10.0.2.50:54321 → 54.x.x.x:10001 → 91.189.88.152:443
Step 5: Packet goes to Internet Gateway → Internet
Step 6: Ubuntu server responds
Response:
Src: 91.189.88.152:443
Dst: 54.x.x.x:10001
Step 7: NAT Gateway reverse translates
Lookup port 10001 → 10.0.2.50:54321
Rewrite:
Src: 91.189.88.152:443
Dst: 10.0.2.50:54321
Step 8: App server receives response
Why Can’t Internet Reach App Server?
Random internet user → 10.0.2.50?
Problem 1: 10.0.2.50 is not routable on internet
Problem 2: No NAT mapping exists for inbound
Problem 3: Security groups would block anyway
The private subnet is truly private!
Scenario 4: Microservice Calling Another Microservice
The Setup (Kubernetes-style)
┌─────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Service A │ │
│ │ │ │
│ │ Pod: user-service-abc123 │ │
│ │ IP: 10.244.1.5 │ │
│ │ │ │
│ │ Code: response = http.get("http://order-service") │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ order-service (Service) │ │
│ │ ClusterIP: 10.96.50.100 │ │
│ │ Port: 80 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ order-pod-1 │ │ order-pod-2 │ │ order-pod-3 │ │
│ │ 10.244.2.10 │ │ 10.244.2.11 │ │ 10.244.2.12 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
The Flow
Step 1: DNS Resolution (CoreDNS)
user-service code: http.get("http://order-service")
DNS query: order-service.default.svc.cluster.local
Response: 10.96.50.100 (ClusterIP)
Step 2: Request to ClusterIP
user-service (10.244.1.5:45678) → 10.96.50.100:80
iptables/IPVS intercepts this:
ClusterIP 10.96.50.100:80 → one of:
- 10.244.2.10:8080
- 10.244.2.11:8080
- 10.244.2.12:8080
DNAT applied: Dest changed to 10.244.2.11:8080 (randomly selected)
Step 3: Pod-to-Pod Networking
Packet:
Src: 10.244.1.5:45678
Dst: 10.244.2.11:8080
Pod network (CNI) routes between nodes if needed
Step 4: Response
order-pod-2 (10.244.2.11:8080) → user-service (10.244.1.5:45678)
Connection tracking ensures response goes to original requester
Scenario 5: SSH Through a Bastion Host
The Setup
┌─────────────────────────────────────────────────────────────┐
│ Your VPC │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Public Subnet │ │
│ │ │ │
│ │ ┌────────────────────────────┐ │ │
│ │ │ Bastion Host │ │ │
│ │ │ 10.0.1.50 │ │ │
│ │ │ Public: 54.1.2.3 │ │ │
│ │ │ Port 22 open │ │ │
│ │ └─────────────┬──────────────┘ │ │
│ │ │ │ │
│ └──────────────────┼───────────────────────────────────┘ │
│ │ │
│ ┌──────────────────┼───────────────────────────────────┐ │
│ │ │ Private Subnet │ │
│ │ │ │ │
│ │ ┌─────────────▼──────────────┐ │ │
│ │ │ Database Server │ │ │
│ │ │ 10.0.2.100 │ │ │
│ │ │ No public IP │ │ │
│ │ │ Port 22 (from bastion)│ │ │
│ │ └────────────────────────────┘ │ │
│ │ │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
You: Laptop at home (203.0.113.100)
Method 1: Two-Step SSH
Method 2: SSH ProxyJump (Recommended)
Method 3: SSH Config File
# ~/.ssh/config
Host bastion
HostName 54.1.2.3
User ec2-user
IdentityFile ~/.ssh/key.pem
Host private-db
HostName 10.0.2.100
User ec2-user
IdentityFile ~/.ssh/key.pem
ProxyJump bastion
# Now just run:
ssh private-db
The Network Flow
Your Laptop (203.0.113.100)
│
│ SSH (port 22) over internet
▼
Bastion (54.1.2.3 / 10.0.1.50)
│
│ SSH (port 22) over private network
▼
Database Server (10.0.2.100)
Your SSH session is end-to-end encrypted.
Bastion acts as a secure gateway.
Security Group Rules
Bastion Security Group:
Inbound: TCP 22 from YOUR_IP/32 only
Database Security Group:
Inbound: TCP 22 from bastion-sg only (not public!)
Scenario 6: HTTPS Request Through CloudFlare CDN
The Setup
┌────────────────────────────────────────────────────────────────┐
│ │
│ User in Tokyo CloudFlare Edge Origin │
│ ┌──────────┐ (Tokyo POP) (US-East)│
│ │ Browser │ ┌──────────┐ ┌──────────┐│
│ │ │──────────►│ CDN │─────────────►│ Server ││
│ │ │◄──────────│ Edge │◄─────────────│ ││
│ └──────────┘ └──────────┘ └──────────┘│
│ │ │ │ │
│ 1ms 150ms │
│ (to edge) (to origin) │
│ │
└────────────────────────────────────────────────────────────────┘
DNS Setup
example.com DNS:
A record → CloudFlare Anycast IP (104.16.x.x)
(not your actual origin IP)
The Flow: First Request (Cache Miss)
Step 1: User → CloudFlare Edge
User's browser → DNS lookup → 104.16.123.45 (CloudFlare Tokyo)
User → CloudFlare Tokyo POP (1ms latency - nearby!)
Step 2: CloudFlare checks cache
Cache lookup: /static/logo.png
Result: MISS (not cached yet)
Step 3: CloudFlare → Origin
CloudFlare Tokyo → Your origin server in US-East
(150ms latency for this hop)
Step 4: Origin responds
Origin → CloudFlare: 200 OK + logo.png
CloudFlare caches the response (if cacheable)
CloudFlare → User: 200 OK + logo.png
Total time: ~1ms + 150ms + 150ms = ~300ms
The Flow: Second Request (Cache Hit)
User (or another user in Tokyo) → /static/logo.png
CloudFlare cache lookup: HIT!
CloudFlare → User: 200 OK + logo.png (from cache)
Total time: ~1ms (no origin involved!)
What CloudFlare Adds
User Request: What Origin Sees:
──────────────── ──────────────────────
From: User's IP From: CloudFlare IP
CF-Connecting-IP: User's IP
CF-IPCountry: JP
CF-Ray: abc123-NRT
Response Headers:
CF-Cache-Status: HIT/MISS/DYNAMIC
CF-Ray: abc123-NRT
Key Takeaways
NAT Enables Internet Scale Millions can share private IP ranges because NAT makes them unique at the public IP level.
Every Hop Adds Latency Each router, NAT, proxy adds processing time. Minimize hops for performance.
Layers Build On Each Other Application relies on Transport relies on Network relies on Data Link.
Security at Every Layer Firewalls, Security Groups, NACLs, TLS - defense in depth.
What’s Next?
Module 17: IPv6 Deep Dive Understand the future of IP addressing with IPv6 in detail.