> ## Documentation Index
> Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Real-World Networking Scenarios

> Complete end-to-end networking scenarios explaining how requests flow from client to server and back

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

The best way to truly understand networking is to follow a packet end-to-end. Each scenario below is like watching a letter travel through the postal system -- from the moment you drop it in the mailbox, through every sorting facility and delivery truck, until it arrives at its destination. But unlike a letter, a network packet passes through multiple "translation desks" (NAT, firewalls, load balancers) that rewrite its headers at each stop.

<Frame>
  <img src="https://mintcdn.com/devweeekends/X0Fp4X8lMl-ZftoO/images/courses/networking-mastery/request-journey.svg?fit=max&auto=format&n=X0Fp4X8lMl-ZftoO&q=85&s=d663286425427d076fd8383a3ca21e90" alt="Complete Request Journey" width="1080" height="1080" data-path="images/courses/networking-mastery/request-journey.svg" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/devweeekends/X0Fp4X8lMl-ZftoO/images/courses/networking-mastery/aws-nat-gateway.svg?fit=max&auto=format&n=X0Fp4X8lMl-ZftoO&q=85&s=609c0028665486a24c531c4d9d46a62e" alt="AWS NAT Gateway Flow" width="1080" height="1080" data-path="images/courses/networking-mastery/aws-nat-gateway.svg" />
</Frame>

<Info>
  **Estimated Time**: 4-5 hours\
  **Difficulty**: Intermediate to Advanced\
  **Prerequisites**: All previous modules
</Info>

***

## Quick Reference: IP Addressing Fundamentals

Before diving into scenarios, let's refresh the key concepts you'll see throughout.

### Private vs Public IP Addresses

<CardGroup cols={2}>
  <Card title="Private IPs (RFC 1918)" icon="house">
    **Not routable on the internet** - used inside your network only.

    | Range                             | CIDR           | Typical Use             |
    | --------------------------------- | -------------- | ----------------------- |
    | `10.0.0.0` - `10.255.255.255`     | 10.0.0.0/8     | Cloud VPCs, enterprises |
    | `172.16.0.0` - `172.31.255.255`   | 172.16.0.0/12  | Medium organizations    |
    | `192.168.0.0` - `192.168.255.255` | 192.168.0.0/16 | Home networks           |

    **Key insight**: Millions of networks can use `192.168.1.1` simultaneously - they're isolated!
  </Card>

  <Card title="Public IPs" icon="globe">
    **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)
  </Card>
</CardGroup>

### 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 |

<Note>
  **Why -2?** First address = Network ID (`192.168.1.0`), Last address = Broadcast (`192.168.1.255`). Neither can be assigned to a host.
</Note>

### Special Addresses You'll See

| Address           | Meaning                       |
| ----------------- | ----------------------------- |
| `0.0.0.0`         | "Any address" / default route |
| `127.0.0.1`       | Localhost (loopback)          |
| `255.255.255.255` | Broadcast to entire network   |
| `169.254.x.x`     | Link-local (DHCP failed)      |
| `224.0.0.0/4`     | Multicast 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

<Steps>
  <Step title="Browser Parses URL">
    ```
    https://google.com

    Protocol: HTTPS (port 443)
    Host: google.com
    Path: / (root)
    ```
  </Step>

  <Step title="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)
    ```
  </Step>

  <Step title="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
    ```
  </Step>

  <Step title="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     │
    ```
  </Step>

  <Step title="HTTP Request">
    Inside the encrypted TLS tunnel:

    ```http theme={null}
    GET / HTTP/2
    Host: google.com
    User-Agent: Chrome/120.0
    Accept: text/html
    Accept-Encoding: gzip, br
    Cookie: NID=123...
    ```
  </Step>

  <Step title="Google's Infrastructure">
    ```
    Internet → Google's Edge (Anycast)
                    │
                    ▼
             Load Balancer
                    │
            ┌───────┼───────┐
            ▼       ▼       ▼
         Server   Server  Server
         (generates response)
    ```
  </Step>

  <Step title="HTTP Response">
    ```http theme={null}
    HTTP/2 200 OK
    Content-Type: text/html
    Content-Encoding: gzip
    Cache-Control: private, max-age=0

    <!doctype html><html>...
    ```
  </Step>

  <Step title="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)
    ```
  </Step>

  <Step title="Browser Renders Page">
    * Parse HTML
    * Fetch CSS, JS, images (parallel connections)
    * Execute JavaScript
    * Render DOM
    * Display page
  </Step>
</Steps>

### 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

<Note>
  **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!
</Note>

***

## 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

This scenario is the modern equivalent of Scenario 1, but inside a cluster instead of across the internet. Think of Kubernetes networking like an office building's internal phone system. Each desk (pod) has an extension (IP). The directory service (CoreDNS) translates team names ("order-service") to the right extension. The PBX system (kube-proxy/iptables) handles call routing and load balancing across team members.

### 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

```bash theme={null}
# Step 1: SSH to bastion
ssh -i key.pem ec2-user@54.1.2.3

# Step 2: From bastion, SSH to private server
ssh -i key.pem ec2-user@10.0.2.100
```

### Method 2: SSH ProxyJump (Recommended)

```bash theme={null}
# Single command - tunnels through bastion
ssh -J ec2-user@54.1.2.3 ec2-user@10.0.2.100
```

### Method 3: SSH Config File

```bash theme={null}
# ~/.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

<CardGroup cols={2}>
  <Card title="NAT Enables Internet Scale" icon="expand">
    Millions can share private IP ranges because NAT makes them unique at the public IP level.
  </Card>

  <Card title="Every Hop Adds Latency" icon="clock">
    Each router, NAT, proxy adds processing time. Minimize hops for performance.
  </Card>

  <Card title="Layers Build On Each Other" icon="layer-group">
    Application relies on Transport relies on Network relies on Data Link.
  </Card>

  <Card title="Security at Every Layer" icon="shield">
    Firewalls, Security Groups, NACLs, TLS - defense in depth.
  </Card>
</CardGroup>

***

## What's Next?

<Card title="Module 17: IPv6 Deep Dive" icon="arrow-right" href="/courses/networking-mastery/17-ipv6">
  Understand the future of IP addressing with IPv6 in detail.
</Card>
