# Module 1: Wireshark Fundamentals

**Nav:** [Course Home](../README.md) | Module 1 | [Module 2 →](02-dhcp-message-flow.md)

---

## Overview

Wireshark is the most widely used network protocol analyzer in the world. It lets you capture packets off a live network interface and inspect them at every layer of the OSI model — from raw Ethernet frames up through application-layer payloads. Whether you are troubleshooting a DHCP failure, diagnosing slow application performance, or investigating a security incident, Wireshark gives you ground truth. Logs can lie, dashboards can mislead, but the packet capture tells you exactly what happened on the wire.

In a production environment, the ability to read a packet capture separates the engineers who guess from the engineers who know. When a client reports "the network is slow," you can fire up Wireshark, capture traffic, and pinpoint whether the problem is DNS resolution delay, TCP retransmissions, TLS negotiation overhead, or something else entirely. This skill is not optional for any serious network or systems engineer.

This module walks you through the Wireshark interface, teaches you how to start and stop captures, apply filters to isolate the traffic you care about, and read the decoded packet fields. By the end, you will have deployed the full lab topology in CML and completed your first captures — ICMP and DNS — which lay the foundation for the DHCP deep-dives in Modules 2 through 4.

---

## Key Concepts

### What Is Wireshark?
Wireshark is a free, open-source packet analyzer. It captures raw network frames from an interface (physical NIC, virtual NIC, or SPAN port) and decodes them into human-readable protocol fields. It supports over 3,000 protocols and can read/write `.pcap` and `.pcapng` file formats.

### Capture vs. Display Filters
These are two fundamentally different filter systems and confusing them is a common beginner mistake.

| Aspect | Capture Filter | Display Filter |
|---|---|---|
| **When applied** | Before packets are written to the buffer | After packets are already captured |
| **Syntax** | BPF (Berkeley Packet Filter) syntax | Wireshark display filter syntax |
| **Example** | `host 10.10.10.1 and port 67` | `ip.addr == 10.10.10.1 && udp.port == 67` |
| **Effect** | Packets not matching are **discarded permanently** | Packets not matching are **hidden but still in the capture** |
| **Use case** | High-traffic environments where you must limit capture size | Post-capture analysis, iterative investigation |
| **Where set** | Capture Options dialog, before starting | Filter toolbar, anytime |

**Rule of thumb:** Use capture filters only when you know exactly what you need and cannot afford to capture everything (high-speed links, long-duration captures). Use display filters for everything else — they are non-destructive and let you change your mind.

### SPAN (Switched Port Analyzer)
Modern switches do not flood traffic to all ports the way hubs did. To capture traffic that is not destined for your Wireshark machine, you must either use a network tap or configure a SPAN session on the switch. SPAN copies traffic from one or more source ports/VLANs to a destination port where your analyzer sits.

### The Three Panes
1. **Packet List Pane** (top) — One row per packet. Columns: No., Time, Source, Destination, Protocol, Length, Info.
2. **Packet Details Pane** (middle) — Expandable protocol tree for the selected packet. Each layer (Frame, Ethernet II, IPv4, UDP, DHCP, etc.) can be expanded to see every field.
3. **Packet Bytes Pane** (bottom) — Raw hex dump and ASCII representation. When you click a field in the details pane, the corresponding bytes highlight here.

### Common Display Filters

| Filter | What It Does |
|---|---|
| `ip.addr == 10.10.10.1` | Any packet with this IP as source OR destination |
| `ip.src == 10.10.10.1` | Source IP only |
| `ip.dst == 10.10.10.1` | Destination IP only |
| `tcp.port == 443` | TCP source or destination port 443 |
| `udp.port == 53` | UDP source or destination port 53 (DNS) |
| `eth.addr == aa:bb:cc:dd:ee:ff` | Ethernet source or destination MAC |
| `icmp` | All ICMP traffic |
| `dns` | All DNS traffic |
| `dhcp` | All DHCP traffic (Wireshark uses "dhcp" not "bootp" in modern versions) |
| `tcp.flags.syn == 1 && tcp.flags.ack == 0` | TCP SYN packets only (connection initiations) |
| `frame.len > 1400` | Packets larger than 1400 bytes |
| `ip.addr == 10.10.10.0/24` | Any IP in the 10.10.10.0/24 subnet |
| `!(arp or dns)` | Exclude ARP and DNS (reduce noise) |

### Common Capture Filters (BPF Syntax)

| Filter | What It Does |
|---|---|
| `host 10.10.10.1` | Traffic to/from this IP |
| `port 67 or port 68` | DHCP traffic |
| `net 10.10.10.0/24` | Traffic in this subnet |
| `ether host aa:bb:cc:dd:ee:ff` | Traffic to/from this MAC |
| `not port 22` | Exclude SSH (useful when capturing over SSH) |

### File Formats
- **`.pcap`** — Legacy format (libpcap). Universally supported. Single interface only.
- **`.pcapng`** — Next-generation format. Supports multiple interfaces, comments, name resolution blocks, and richer metadata. Wireshark default since version 1.8.

---

## Lab 1.1: Deploy the CML Topology

### Objective
Build the full lab topology in Cisco Modeling Labs (CML). This topology will be used for all modules in this course.

### Topology Diagram

```
                    ┌──────────────────┐
                    │   RTR1 (CSR1000v)│
                    │   Gi0/1 (trunk)  │
                    └────────┬─────────┘
                             │ 802.1Q Trunk
                             │ VLANs 10, 20, 30
                    ┌────────┴─────────┐
                    │  SW1 (IOSv-L2)   │
                    │  Gi0/0 - Trunk   │
                    │  Gi0/1 - VLAN 10 │
                    │  Gi0/2 - VLAN 20 │
                    │  Gi0/3 - VLAN 30 │
                    │  Gi1/0 - SPAN dst│
                    └──┬───┬───┬───┬───┘
                       │   │   │   │
                  ┌────┘   │   │   └────┐
                  │        │   │        │
           ┌──────┴──┐ ┌──┴───┴──┐ ┌───┴─────────┐
           │ Client1  │ │ Client2 │ │  DHCP-SVR   │
           │ Ubuntu   │ │ Ubuntu  │ │ Ubuntu 22.04│
           │ VLAN 10  │ │ VLAN 20 │ │ VLAN 30     │
           │          │ │         │ │ 10.10.30.10 │
           └──────────┘ └─────────┘ └─────────────┘

                  ┌───────────────┐
                  │ Wireshark-PC  │
                  │ Ubuntu Desktop│
                  │ SPAN dest     │
                  │ (Gi1/0 on SW1)│
                  └───────────────┘
```

### SW1 Configuration (IOSv-L2)

```
! === SW1 Full Configuration ===

hostname SW1

! --- Create VLANs ---
vlan 10
 name DATA
vlan 20
 name VOICE
vlan 30
 name SERVERS

! --- Trunk to RTR1 ---
interface GigabitEthernet0/0
 description TRUNK_TO_RTR1
 switchport trunk encapsulation dot1q
 switchport mode trunk
 switchport trunk allowed vlan 10,20,30
 no shutdown

! --- Access port for Client1 (VLAN 10) ---
interface GigabitEthernet0/1
 description CLIENT1_VLAN10
 switchport mode access
 switchport access vlan 10
 spanning-tree portfast
 no shutdown

! --- Access port for Client2 (VLAN 20) ---
interface GigabitEthernet0/2
 description CLIENT2_VLAN20
 switchport mode access
 switchport access vlan 20
 spanning-tree portfast
 no shutdown

! --- Access port for DHCP-SVR (VLAN 30) ---
interface GigabitEthernet0/3
 description DHCP_SERVER_VLAN30
 switchport mode access
 switchport access vlan 30
 spanning-tree portfast
 no shutdown

! --- SPAN Destination Port for Wireshark-PC ---
interface GigabitEthernet1/0
 description SPAN_DESTINATION_WIRESHARK
 no shutdown

! --- SPAN Session: Mirror ALL VLANs to Wireshark-PC ---
! Source = VLANs 10, 20, 30 (both directions)
! Destination = Gi1/0
monitor session 1 source vlan 10,20,30 both
monitor session 1 destination interface GigabitEthernet1/0

! --- Verify SPAN ---
! show monitor session 1
```

> **Note:** The SPAN destination port is removed from all VLANs and STP automatically. It becomes a dedicated mirror port. The Wireshark-PC connected to it will see copies of all frames on VLANs 10, 20, and 30.

### RTR1 Configuration (CSR1000v)

```
! === RTR1 Full Configuration ===

hostname RTR1

! --- Physical interface (trunk side) ---
interface GigabitEthernet0/1
 description TRUNK_TO_SW1
 no ip address
 no shutdown

! --- Subinterface for VLAN 10 (DATA) ---
interface GigabitEthernet0/1.10
 description GATEWAY_VLAN10_DATA
 encapsulation dot1Q 10
 ip address 10.10.10.1 255.255.255.0

! --- Subinterface for VLAN 20 (VOICE) ---
interface GigabitEthernet0/1.20
 description GATEWAY_VLAN20_VOICE
 encapsulation dot1Q 20
 ip address 10.10.20.1 255.255.255.0

! --- Subinterface for VLAN 30 (SERVERS) ---
interface GigabitEthernet0/1.30
 description GATEWAY_VLAN30_SERVERS
 encapsulation dot1Q 30
 ip address 10.10.30.1 255.255.255.0
```

### DHCP-SVR Basic Network Configuration (Ubuntu 22.04)

```bash
# /etc/netplan/00-installer-config.yaml
network:
  version: 2
  ethernets:
    ens3:
      addresses:
        - 10.10.30.10/24
      routes:
        - to: 10.10.10.0/24
          via: 10.10.30.1
        - to: 10.10.20.0/24
          via: 10.10.30.1
      nameservers:
        addresses:
          - 8.8.8.8
          - 8.8.4.4
```

```bash
# Apply the netplan configuration
sudo netplan apply

# Verify
ip addr show ens3
ip route show
ping 10.10.30.1    # Should reach RTR1
```

### Installing Wireshark on Wireshark-PC (Ubuntu Desktop)

```bash
# Update package lists
sudo apt update

# Install Wireshark (select "Yes" when asked about non-superuser capture)
sudo apt install -y wireshark

# Add your user to the wireshark group (required for non-root captures)
sudo usermod -aG wireshark $USER

# Log out and back in for the group change to take effect
# Or use newgrp for the current session:
newgrp wireshark

# Verify you can see interfaces
wireshark --version
dumpcap -D
```

> **Important:** If you skipped the "allow non-superusers" dialog during install, reconfigure it:
> ```bash
> sudo dpkg-reconfigure wireshark-common
> ```
> Select "Yes", then re-add your user to the wireshark group.

### Verification

Run these commands to confirm the topology is working:

| Device | Command | Expected Result |
|---|---|---|
| SW1 | `show vlan brief` | VLANs 10, 20, 30 present with correct ports |
| SW1 | `show interfaces trunk` | Gi0/0 trunking, VLANs 10,20,30 allowed |
| SW1 | `show monitor session 1` | Source VLANs 10,20,30 → Dest Gi1/0 |
| RTR1 | `show ip interface brief` | Subinterfaces up/up with correct IPs |
| RTR1 | `ping 10.10.30.10` | Successful ping to DHCP-SVR |
| DHCP-SVR | `ip addr show ens3` | 10.10.30.10/24 |
| DHCP-SVR | `ping 10.10.30.1` | Successful ping to RTR1 |
| Wireshark-PC | `dumpcap -D` | Lists available capture interfaces |

---

## Lab 1.2: First Capture — ICMP Ping

### Objective
Capture ICMP echo request/reply packets between two devices and dissect them field by field in Wireshark.

### Steps

**Step 1: Start Wireshark on Wireshark-PC**
```
1. Open Wireshark (Activities → Wireshark, or run `wireshark` from terminal)
2. In the interface list, double-click on your capture interface (ens3 — connected to SPAN port)
3. The capture starts immediately — you will see packets flowing if there is any traffic on VLANs 10/20/30
```

**Step 2: Generate ICMP Traffic**

On the DHCP-SVR (10.10.30.10), ping RTR1:
```bash
ping -c 5 10.10.30.1
```

**Step 3: Stop the Capture**
```
1. Click the red square (Stop) button in Wireshark
2. You now have a buffer of captured packets
```

**Step 4: Apply a Display Filter**

In the display filter toolbar, type:
```
icmp
```
Press Enter. Only ICMP packets will be shown.

**Step 5: Examine an Echo Request Packet**

Click on an "Echo (ping) request" packet. In the Packet Details pane, expand each layer:

| Layer | Key Fields | What You See |
|---|---|---|
| **Frame** | Frame Number, Frame Length, Capture Timestamp | Metadata about the capture itself — not part of the actual packet |
| **Ethernet II** | Src MAC, Dst MAC, Type (0x0800 = IPv4) | Layer 2 header — 14 bytes. The MACs tell you the next-hop, not the final destination |
| **Internet Protocol Version 4** | Src IP (10.10.30.10), Dst IP (10.10.30.1), TTL, Protocol (1 = ICMP), Header Length, Total Length | Layer 3 header — 20 bytes minimum. TTL decrements at each hop |
| **Internet Control Message Protocol** | Type (8 = Echo Request), Code (0), Checksum, Identifier, Sequence Number | ICMP payload — Type 8 = request, Type 0 = reply. The ID and Seq# tie requests to replies |

**Step 6: Compare Request and Reply**

| Field | Echo Request | Echo Reply |
|---|---|---|
| Source IP | 10.10.30.10 | 10.10.30.1 |
| Destination IP | 10.10.30.1 | 10.10.30.10 |
| ICMP Type | 8 (Echo Request) | 0 (Echo Reply) |
| ICMP Code | 0 | 0 |
| Identifier | Same value in both | Same value in both |
| Sequence | Increments per ping | Matches the request |

### What You Should See in Wireshark
- Alternating request/reply pairs (you sent 5 pings, so 10 ICMP packets)
- Source and destination swap between request and reply
- The packet bytes pane shows the raw hex — click on "Type: 8" in the details and see `08` highlighted in the hex dump

---

## Lab 1.3: Capture DNS Traffic

### Objective
Capture DNS queries and responses to understand how name resolution works at the packet level.

### Steps

**Step 1: Start a new capture on Wireshark-PC**
```
1. File → Close (discard the previous capture or save it)
2. Double-click your capture interface to start a new capture
```

**Step 2: Generate DNS Traffic from DHCP-SVR**
```bash
# Resolve a hostname
nslookup google.com
# Or use dig for more detail
dig google.com
```

**Step 3: Stop the capture and filter**

Display filter:
```
dns
```

**Step 4: Examine the DNS Query**

Click on the DNS query packet (Info column shows "Standard query A google.com"):

| Layer | Key Fields |
|---|---|
| **UDP** | Src Port: random high port, Dst Port: 53 |
| **Domain Name System (query)** | Transaction ID, Flags (Standard query, recursion desired), Questions: 1, Answer RRs: 0 |
| **Queries → google.com: type A, class IN** | The actual question — "What is the A record for google.com?" |

**Step 5: Examine the DNS Response**

Click the response packet (Info shows "Standard query response A google.com A x.x.x.x"):

| Layer | Key Fields |
|---|---|
| **UDP** | Src Port: 53, Dst Port: original high port |
| **Domain Name System (response)** | Same Transaction ID, Flags (response, recursion available), Answer RRs: 1+ |
| **Answers → google.com: type A, class IN, addr x.x.x.x** | The answer — the resolved IP address(es) |

**Step 6: Save the Capture**
```
1. File → Save As
2. Choose a location and filename (e.g., dns_capture.pcapng)
3. Format: pcapng (default)
```

### What You Should See in Wireshark
- Query and response paired by Transaction ID
- The query goes to UDP port 53, the response comes from UDP port 53
- If `dig` was used, you may also see an AAAA query (IPv6) alongside the A query
- Response contains one or more answer records with TTL values

---

## Understanding Check

1. **What is the difference between a capture filter and a display filter? When would you use each one?**
   A capture filter (BPF syntax) is applied before packets enter the buffer — unmatched packets are discarded and cannot be recovered. A display filter is applied after capture — all packets remain in the file and you can change filters at any time. Use capture filters on high-speed links or long captures where disk/memory is a concern. Use display filters for analysis and investigation.

2. **You are capturing on a switch and only see your own traffic. What are two possible solutions?**
   (a) Configure a SPAN session on the switch to mirror the source ports/VLANs to the port where your Wireshark machine is connected. (b) Use a physical network tap between the source device and the switch.

3. **In an ICMP echo request packet, what ICMP Type and Code values do you expect? What about the echo reply?**
   Echo Request: Type 8, Code 0. Echo Reply: Type 0, Code 0. The Identifier and Sequence Number fields tie requests to their corresponding replies.

4. **Write a display filter that shows only DNS traffic to or from the IP address 10.10.30.10.**
   `dns && ip.addr == 10.10.30.10`

---

## Related Modules

- [Course Home](../README.md)
- [Module 2: DHCP Message Flow (DORA)](02-dhcp-message-flow.md)
- [Module 3: DHCP Options Deep Dive](03-dhcp-options.md)
- [Module 4: DHCP Relay (ip helper-address)](04-dhcp-relay.md)

---

## Network Diagram

```mermaid
---
title: "Module 1: CML Lab Topology — Wireshark Fundamentals"
---
graph TD
    RTR1["<b>RTR1</b><br/>CSR1000v Router<br/>Gi0/1 — 802.1Q Trunk<br/>VLAN 10: 10.10.10.1/24<br/>VLAN 20: 10.10.20.1/24<br/>VLAN 30: 10.10.30.1/24"]

    SW1["<b>SW1</b><br/>IOSv-L2 Switch<br/>Gi0/0 — Trunk<br/>Gi0/1 — VLAN 10<br/>Gi0/2 — VLAN 20<br/>Gi0/3 — VLAN 30<br/>Gi1/0 — SPAN Dest"]

    CLIENT1["<b>Client1</b><br/>Ubuntu<br/>VLAN 10 — DATA<br/>DHCP Client"]

    CLIENT2["<b>Client2</b><br/>Ubuntu<br/>VLAN 20 — VOICE<br/>DHCP Client"]

    DHCPSVR["<b>DHCP-SVR</b><br/>Ubuntu 22.04<br/>VLAN 30 — SERVERS<br/>10.10.30.10/24"]

    WIRESHARK["<b>Wireshark-PC</b><br/>Ubuntu Desktop<br/>SPAN Destination<br/>Captures VLANs 10, 20, 30"]

    RTR1 <===>|"802.1Q Trunk<br/>Gi0/1 ↔ Gi0/0<br/>VLANs 10, 20, 30"| SW1

    SW1 --->|"Gi0/1<br/>VLAN 10 — DATA"| CLIENT1
    SW1 --->|"Gi0/2<br/>VLAN 20 — VOICE"| CLIENT2
    SW1 --->|"Gi0/3<br/>VLAN 30 — SERVERS"| DHCPSVR

    SW1 -.->|"Gi1/0 — SPAN Mirror<br/>VLANs 10, 20, 30"| WIRESHARK

    classDef router fill:#1a5276,stroke:#154360,color:#fff,stroke-width:2px
    classDef switch fill:#7d3c98,stroke:#6c3483,color:#fff,stroke-width:2px
    classDef client fill:#1e8449,stroke:#196f3d,color:#fff,stroke-width:2px
    classDef server fill:#b9770e,stroke:#9c640c,color:#fff,stroke-width:2px
    classDef wireshark fill:#c0392b,stroke:#a93226,color:#fff,stroke-width:2px

    class RTR1 router
    class SW1 switch
    class CLIENT1,CLIENT2 client
    class DHCPSVR server
    class WIRESHARK wireshark
```
