Skip to main content

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.
Complete Request Journey
AWS NAT Gateway Flow
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.
RangeCIDRTypical Use
10.0.0.0 - 10.255.255.25510.0.0.0/8Cloud VPCs, enterprises
172.16.0.0 - 172.31.255.255172.16.0.0/12Medium organizations
192.168.0.0 - 192.168.255.255192.168.0.0/16Home 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
CIDRSubnet MaskUsable HostsQuick Math
/8255.0.0.016,777,2142^24 - 2
/16255.255.0.065,5342^16 - 2
/24255.255.255.02542^8 - 2
/28255.255.255.240142^4 - 2
/32255.255.255.2551Single 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

AddressMeaning
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

1

Browser Parses URL

https://google.com

Protocol: HTTPS (port 443)
Host: google.com
Path: / (root)
2

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)
3

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
4

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     │
5

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...
6

Google's Infrastructure

Internet → Google's Edge (Anycast)


         Load Balancer

        ┌───────┼───────┐
        ▼       ▼       ▼
     Server   Server  Server
     (generates response)
7

HTTP Response

HTTP/2 200 OK
Content-Type: text/html
Content-Encoding: gzip
Cache-Control: private, max-age=0

<!doctype html><html>...
8

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)
9

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

# Step 1: SSH to bastion
ssh -i key.pem [email protected]

# Step 2: From bastion, SSH to private server
ssh -i key.pem [email protected]
# Single command - tunnels through bastion
ssh -J [email protected] [email protected]

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.