OS Lab 8 - Transport and Security

De la WikiLabs
Jump to navigationJump to search

Objectives

Upon completion of this lab, you will be able to:

  • Explain the fundamental differences between Connectionless (UDP) and Connection-Oriented (TCP) transport protocols and their appropriate use cases.
  • Understand the TCP state machine and the lifecycle of connections (LISTEN, SYN_SENT, ESTABLISHED, TIME_WAIT, etc.).
  • Inspect active socket states and statistics using the ss (socket statistics) utility to diagnose connection issues.
  • Perform network service discovery using nmap for port scanning.
  • Implement a complete Public Key Infrastructure (PKI) by generating Certificate Authorities (CAs), private keys, and signed certificates using openssl.
  • Secure network communications using TLS (Transport Layer Security) to provide confidentiality and authenticity.
  • Verify encryption effectiveness by inspecting packets with tcpdump to demonstrate the difference between plaintext and encrypted traffic.
  • Understand the trust model of PKI and certificate chains used in modern HTTPS and secure communications.
  • Understand the role of DNS (Domain Name System) and hostname resolution in network communication and certificate validation.

Introduction

In Lab 7, we built the foundational "plumbing" of computer networks: network interfaces, IP addresses, routing tables, and bridges. These components solve the problem of connectivity: they allow one machine to find and reach another machine on a network or across the internet. We demonstrated how the kernel routes packets from source to destination based on IP addresses.

However, there's a critical distinction we haven't addressed: machines don't really communicate with machines. More precisely, processes communicate with processes. When you browse a website, it's not just your computer talking to a server; it's your browser process talking to a web server process. When you send an email, your mail client talks to a mail server process. The question becomes: how does a packet arriving at a destination machine know which process should receive it?

This is where the Transport Layer comes into play. The transport layer solves several fundamental problems:

  1. Process Addressing: It introduces the concept of ports to identify specific applications or services (e.g., HTTP servers typically listen on port 80, SSH on port 22, DNS on port 53).
  2. Data Transfer Semantics: It defines how data should be transferred: reliably with error checking and retransmission (TCP) or quickly with minimal overhead (UDP).
  3. Flow Control and Congestion Management: It prevents fast senders from overwhelming slow receivers and manages network congestion to prevent collapse.

But there's another critical problem lurking beneath the surface: security. The internet is fundamentally an untrusted network. Your packets traverse dozens of routers, switches, and network devices controlled by various organizations and potentially malicious actors. Any intermediate device can inspect, copy, or even modify your traffic. This is especially concerning when you're transmitting sensitive data like passwords, credit card numbers, or private communications.

In this lab, we move beyond basic connectivity to explore:

  • How processes establish communication channels using ports and sockets
  • The trade-offs between UDP's speed and TCP's reliability
  • How operating systems manage connection state
  • Network reconnaissance techniques (port scanning) used by both administrators and attackers
  • Cryptographic foundations of secure communications (public key infrastructure)
  • How TLS (Transport Layer Security) protects data in transit, forming the foundation of modern secure internet protocols like HTTPS

We'll not only establish connections between our virtual machines (Red and Blue namespaces) but also implement complete TLS encryption to prevent eavesdropping. By using tcpdump to inspect packets "on the wire," we'll see firsthand the difference between plaintext and encrypted communications, demonstrating why TLS has become the universal standard for web traffic.

Additionally, we'll introduce a crucial component of internet infrastructure: hostname resolution. While machines communicate using IP addresses, humans prefer memorable names like "google.com" or "github.com". More importantly, security on the internet is built on these names, not IP addresses. When you visit a website with HTTPS, the server proves it controls a specific domain name (like "bank.com"), not just an IP address. In this lab, we'll use simple hostname-to-IP mappings to understand this concept before diving deeper into DNS (Domain Name System) in the next lab.


Prerequisites

System Requirements

A running instance of a Linux virtual machine with root privileges (via sudo). You will need terminal access, either via SSH or directly through the VM console. Multiple terminal windows will be helpful for running servers, clients, and monitoring tools simultaneously.

Required Packages

The following packages must be installed:

sudo apt update
sudo apt install -y nmap openssl tcpdump iproute2
  • nmap: Network exploration tool and security scanner. Includes ncat, an implementation of cat over sockets with SSL/TLS support.
  • openssl: Cryptographic toolkit for SSL/TLS, certificate generation, and various cryptographic operations.
  • tcpdump: Command-line packet analyzer for network traffic inspection.
  • iproute2: Modern Linux networking utilities (provides ip, ss commands).

Knowledge Prerequisites

You should be familiar with:

  • Network interfaces, IP addresses, and routing from Lab 7
  • Bash scripting from Lab 5 (variables, loops, functions)
  • Process concepts from Lab 3 (PIDs, process execution)

You should also understand:

  • What an IP address is and how packets are routed
  • The concept of clients and servers
  • Basic command-line text manipulation (grep, awk, cut)

Theoretical Background

The Transport Layer: Bridging Machines and Processes

The Problem: Port Numbers and Multiplexing

Imagine your computer receives a packet from the internet. The IP header tells the kernel which machine the packet is for (destination IP), but once it arrives, how does the kernel know which of the potentially hundreds of running processes should receive this packet?

The solution is port numbers. A port is a 16-bit unsigned integer (range 0-65535) that identifies a specific communication endpoint on a machine. When combined with an IP address, a port creates a unique socket address (IP:PORT) that identifies a specific process on a specific machine.

Port numbers are divided into three ranges:

  • Well-Known Ports (0-1023): Reserved for standard services (HTTP=80, HTTPS=443, SSH=22, DNS=53, SMTP=25). On Linux systems, binding to these ports typically requires root privileges.
  • Registered Ports (1024-49151): Can be registered for specific services but are less rigidly controlled.
  • Dynamic/Private Ports (49152-65535): Used for ephemeral (temporary) client-side ports when making outbound connections.

When a web browser connects to a web server, it might create a socket with local address 192.168.1.50:54321 (client's IP and a random ephemeral port) connecting to remote address 203.0.113.10:443 (server's IP and HTTPS port). The combination of (source IP, source port, destination IP, destination port, protocol) uniquely identifies a connection.

The transport layer performs multiplexing (combining multiple data streams into one network connection on the sending side) and demultiplexing (separating the combined stream back into individual streams on the receiving side based on port numbers).

UDP: User Datagram Protocol

UDP is the simpler of the two main transport protocols. Its philosophy is "fire and forget."

Characteristics:

  • Connectionless: No handshake or connection establishment. Just send packets (called "datagrams").
  • Unreliable: No delivery guarantees. Packets may arrive out of order, be duplicated, or be lost entirely.
  • No State: The kernel doesn't maintain connection state. Each datagram is independent.
  • Low Overhead: Minimal header (8 bytes) compared to TCP's 20+ bytes.
  • Fast: No waiting for acknowledgments or retransmissions.

UDP Header:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Length             |           Checksum            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             Data                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Just four fields: source port, destination port, length, and an optional checksum. Compare this to TCP's much more complex header.

When UDP is Used:

  • DNS Queries: Fast lookups where a lost query can simply be retried.
  • Real-time Streaming: Video/audio where old data is useless (better to skip than wait).
  • Gaming: Low-latency updates where occasional packet loss is acceptable.
  • IoT Sensors: Simple periodic data updates where reliability is handled at application level.
  • Broadcast/Multicast: Sending to multiple recipients simultaneously.

When UDP is NOT Used:

  • File transfers
  • Financial transactions
  • Remote terminal sessions
  • Email delivery

UDP pushes reliability concerns to the application layer. Applications must implement their own acknowledgment, retransmission, and ordering mechanisms if needed.

TCP: Transmission Control Protocol

TCP is the workhorse of the internet. Most traffic you generate (web browsing, email, file transfers, SSH) uses TCP.

Characteristics:

  • Connection-Oriented: Requires explicit connection establishment (handshake) and termination.
  • Reliable: Guarantees that data arrives correctly and in order, using acknowledgments and retransmissions.
  • Stateful: The kernel maintains extensive state for each connection (sequence numbers, window sizes, timers).
  • Stream-Oriented: Presents data as a continuous byte stream, not individual packets. Application-level message boundaries are not preserved.
  • Flow Control: Prevents fast senders from overwhelming slow receivers using sliding windows.
  • Congestion Control: Detects network congestion and adjusts transmission rates to prevent network collapse.

TCP Connection Lifecycle: The State Machine

TCP connections go through a well-defined series of states. Understanding these states is crucial for troubleshooting network issues.

Client Side:                          Server Side:

CLOSED                                CLOSED
  |                                      |
  |                                   (bind + listen)
  |                                      |
  |                                   LISTEN
  |                                      |
(connect)                                |
  |                                      |
SYN_SENT -------- SYN ----------------> |
  |                                   SYN_RCVD
  | <-------- SYN-ACK ----------------- |
  |                                      |
ESTABLISHED ------ ACK ---------------> ESTABLISHED
  |                                      |
  |                                      |
(data transfer happens here)            |
  |                                      |
  |                                      |
(close)                                  |
  |                                      |
FIN_WAIT_1 ------- FIN ---------------> |
  |                                   CLOSE_WAIT
  | <-------- ACK -------------------- |
  |                                      |
FIN_WAIT_2                            (close)
  |                                      |
  | <-------- FIN -------------------- LAST_ACK
  |                                      |
TIME_WAIT ------- ACK ---------------> CLOSED
  |
  | (wait 2*MSL)
  |
CLOSED

Key States Explained:

  1. CLOSED: No connection exists. This is the starting and ending state.
  2. LISTEN: Server is waiting for incoming connection requests. Socket is bound to a port.
  3. SYN_SENT: Client has sent a SYN (synchronize) packet and is waiting for a response. This occurs immediately after calling connect().
  4. SYN_RCVD: Server has received a SYN and sent back SYN-ACK, waiting for the final ACK. Short-lived state.
  5. ESTABLISHED: Connection is fully established and data can flow in both directions. This is where most time is spent.
  6. FIN_WAIT_1: Active close initiated. Application called close(), sent FIN, waiting for ACK.
  7. FIN_WAIT_2: Received ACK for our FIN, waiting for peer's FIN.
  8. CLOSE_WAIT: Received FIN from peer, waiting for application to call close().
  9. LAST_ACK: Sent our FIN, waiting for final ACK.
  10. TIME_WAIT: Both sides have closed, but socket remains in this state for 2*MSL (Maximum Segment Lifetime, typically 2-4 minutes) to ensure all packets have cleared the network. This prevents old duplicate packets from being interpreted as part of a new connection using the same port numbers.

The Three-Way Handshake:

Connection establishment (SYN → SYN-ACK → ACK) is called the "three-way handshake":

  1. Client → Server: SYN
    • Client sends a segment with SYN flag set and an initial sequence number (ISN)
    • Client enters SYN_SENT state
  2. Server → Client: SYN-ACK
    • Server responds with SYN and ACK flags set
    • Server sends its own ISN and acknowledges client's ISN+1
    • Server enters SYN_RCVD state
  3. Client → Server: ACK
    • Client acknowledges server's ISN+1
    • Both sides enter ESTABLISHED state
    • Data transfer can begin

This handshake synchronizes sequence numbers on both sides, allowing reliable, ordered delivery.

Why Three-Way? Why Not Two?

A two-way handshake would be susceptible to old duplicate SYN packets causing false connections. The three-way handshake ensures both sides agree on current sequence numbers before data transmission begins.

Connection Termination (Four-Way Handshake):

Either side can initiate closure:

  1. Active Closer → Passive Closer: FIN
  2. Passive Closer → Active Closer: ACK (acknowledges FIN)
  3. Passive Closer → Active Closer: FIN (when application closes)
  4. Active Closer → Passive Closer: ACK (final acknowledgment)

Sometimes steps 2 and 3 are combined (FIN+ACK in one packet) for a three-segment close.

TCP Segment Header:

TCP headers are much more complex than UDP:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Acknowledgment Number                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Data |           |U|A|P|R|S|F|                               |
| Offset| Reserved  |R|C|S|S|Y|I|            Window             |
|       |           |G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Checksum            |         Urgent Pointer        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             Data                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Key fields:

  • Sequence Number: Position of this segment's first byte in the stream
  • Acknowledgment Number: Next expected byte from peer
  • Flags: SYN, ACK, FIN, RST, PSH, URG control connection state
  • Window: Available receive buffer space (flow control)
  • Checksum: Error detection

Socket Statistics with ss

The ss (socket statistics) command is the modern replacement for the legacy netstat command. It's faster and more feature-rich.

Common usage:

ss -tuna  # TCP, UDP, numeric, all states
ss -tln   # TCP listening sockets with numeric ports
ss -tapn  # TCP all states, show process names

Options:

  • -t: TCP sockets
  • -u: UDP sockets
  • -l: Listening sockets only
  • -a: All states (listening and non-listening)
  • -n: Don't resolve service names (show port numbers)
  • -p: Show process using socket
  • -e: Extended information
  • -m: Memory usage

Example output:

State      Recv-Q Send-Q Local Address:Port    Peer Address:Port
LISTEN     0      128    0.0.0.0:22            0.0.0.0:*
ESTAB      0      0      10.0.0.2:45678        10.0.0.3:8080
TIME-WAIT  0      0      10.0.0.2:45680        10.0.0.3:8080

Understanding the fields:

  • State: Current TCP state
  • Recv-Q: Bytes in receive queue (not yet read by application)
  • Send-Q: Bytes in send queue (not yet acknowledged by peer)
  • Local Address:Port: This machine's socket address
  • Peer Address:Port: Remote machine's socket address

Non-zero Recv-Q might indicate the application is slow to read data. Non-zero Send-Q might indicate network congestion or a slow receiver.

Network Security Fundamentals

The Threat Model: Man-in-the-Middle (MITM)

Consider the network topology from Lab 7:

[Red NS] ←→ [Bridge] ←→ [Blue NS]
              ↑
           [Host]

The host has interfaces connected to the bridge and can see all traffic between Red and Blue. In a real network, this "middle position" might be occupied by:

  • Your ISP's routers
  • Corporate proxy servers
  • Public WiFi access points
  • Government surveillance equipment
  • Malicious actors who've compromised network infrastructure

A Man-in-the-Middle attacker can:

  1. Eavesdrop: Read all plaintext data (passwords, messages, documents)
  2. Modify: Alter data in transit (change bank account numbers, inject malware)
  3. Impersonate: Pretend to be one side of the communication

This is why encryption is essential for any sensitive communication.

Cryptography Basics

Modern secure communications rely on a combination of symmetric and asymmetric cryptography.

Symmetric Encryption (Secret Key Cryptography):

  • Same key used for encryption and decryption
  • Fast and efficient
  • Problem: How do you securely share the key?
  • Examples: AES, ChaCha20

Asymmetric Encryption (Public Key Cryptography):

  • Key pair: public key (can be shared) and private key (must be kept secret)
  • Data encrypted with public key can only be decrypted with private key
  • Slow compared to symmetric encryption
  • Solves key distribution problem
  • Examples: RSA, Elliptic Curve (ECDSA, Ed25519)

Digital Signatures:

  • Used to verify authenticity and integrity
  • Sender creates a signature using their private key
  • Receiver verifies using sender's public key
  • Proves the sender owns the private key and data hasn't been tampered with

Hash Functions:

  • One-way functions that produce fixed-size output (digest) from arbitrary input
  • Same input always produces same output
  • Computationally infeasible to find two inputs with same output (collision resistance)
  • Examples: SHA-256, SHA-3

TLS: Transport Layer Security

TLS (formerly SSL) is the protocol that secures most internet traffic today. It provides:

  1. Confidentiality: Data is encrypted so eavesdroppers see only gibberish
  2. Integrity: Data cannot be modified without detection
  3. Authentication: Verify you're talking to the correct server (via certificates)

TLS Handshake (Simplified):

Client                                               Server

ClientHello ----------------------------------------→
(supported ciphers, TLS versions, random nonce)

                                 ←---------------------- ServerHello
                                                         (chosen cipher, TLS version, random nonce)
                                                         Certificate
                                                         (server's public key + CA signature)
                                                         ServerKeyExchange
                                                         ServerHelloDone

ClientKeyExchange ------------------------------------→
(pre-master secret encrypted with server's public key)
ChangeCipherSpec
Finished

                                 ←--------------- ChangeCipherSpec
                                                  Finished

[Encrypted Application Data] ←----------------→ [Encrypted Application Data]

Key steps:

  1. Negotiation: Agree on TLS version and cipher suite
  2. Authentication: Server presents certificate (sometimes client does too)
  3. Key Exchange: Establish shared encryption keys using asymmetric crypto
  4. Encryption: Switch to symmetric encryption for data transfer

In order to minimize overhead, the asymmetric crypto is only used to establish a session key. Then fast symmetric encryption is used for the actual data.

Why Both?

  • Asymmetric encryption solves the key distribution problem
  • Symmetric encryption provides fast data encryption
  • Together they provide security and performance

Public Key Infrastructure (PKI)

PKI is the system of trust that underlies secure internet communications.

Components:

  1. Certificate Authority (CA): A trusted third party that signs certificates. Major CAs include Let's Encrypt, DigiCert, GlobalSign. Your operating system and browser come with a pre-installed list of trusted root CAs.
  2. Certificate: A document binding a public key to an identity (domain name, organization). Contains:
    • Subject (who the certificate is for)
    • Issuer (which CA signed it)
    • Public key
    • Validity period (not before / not after dates)
    • Digital signature (from CA)
  3. Private Key: Kept secret by the certificate owner. Used to prove ownership and establish secure connections.
  4. Certificate Signing Request (CSR): A request to a CA saying "Please sign a certificate for my public key and domain."

Trust Chain:

Root CA (self-signed, in browser's trust store)
   ↓ signs
Intermediate CA (signed by Root CA)
   ↓ signs
End-Entity Certificate (your server, signed by Intermediate CA)

When you connect to https://example.com:

  1. Server sends its certificate
  2. Your browser checks: Is this certificate signed by a CA I trust?
  3. Browser walks the chain: End-entity ← Intermediate ← Root
  4. If Root CA is in browser's trust store, certificate is trusted
  5. Browser verifies certificate is for the correct domain (example.com)
  6. Browser verifies certificate hasn't expired
  7. If all checks pass, secure connection established

Self-Signed Certificates:

In this lab, we create self-signed certificates (the CA signs its own certificate). This is fine for testing, but browsers will show warnings in production because the CA isn't in their trust store. Real websites use certificates from trusted CAs.

Port Scanning and Network Reconnaissance

Port scanning is the process of probing a target system to discover which ports are open (have services listening). This is used by:

  • System administrators for inventory and auditing
  • Security researchers for vulnerability assessment
  • Attackers for reconnaissance (first step in many attacks)

nmap Basics:

nmap -p 22 10.0.0.3          # Scan port 22 on specific IP
nmap -p 1-1000 10.0.0.3      # Scan ports 1-1000
nmap -p- 10.0.0.3            # Scan all 65535 ports
nmap 10.0.0.0/24             # Scan all hosts in subnet
nmap -sV 10.0.0.3            # Service version detection
nmap -O 10.0.0.3             # OS fingerprinting

Scan Types:

  • TCP Connect Scan (-sT): Completes full three-way handshake. Most reliable but also most detectable.
  • SYN Scan (-sS, default for root): Sends SYN, waits for SYN-ACK, then sends RST instead of ACK. "Half-open" scan, stealthier.
  • UDP Scan (-sU): Slower, less reliable, but necessary for UDP services.

Port States:

  • Open: Service actively accepting connections
  • Closed: No service, but port is reachable (responds with RST)
  • Filtered: Firewall or filter blocking access (no response or ICMP unreachable)

Only scan systems you own or have explicit permission to scan. Unauthorized scanning may violate computer crime laws.

The Future: QUIC and HTTP/3

TCP has served the internet well since the 1970s, but it has limitations that become apparent in modern, high-latency networks.

TCP's Problems:

  1. Head-of-Line Blocking: TCP provides a single ordered byte stream. If one packet is lost, all subsequent packets (even for unrelated data) must wait for retransmission. In HTTP/2, a single lost packet blocks all simultaneous downloads.
  2. Handshake Latency: TCP three-way handshake + TLS handshake requires 2-3 round trips before data transfer begins. On high-latency connections (satellite, mobile), this adds seconds of delay.
  3. Ossification: TCP is implemented in operating system kernels. Deploying new features (like improved congestion control) requires OS updates on billions of devices—essentially impossible.

QUIC (Quick UDP Internet Connections):

QUIC is a new transport protocol developed by Google, now standardized as RFC 9000. It's the foundation of HTTP/3.

Key innovations:

  • Built on UDP: Implemented in userspace, not kernel. Fast iteration and deployment.
  • Integrated TLS 1.3: Encryption is mandatory and built-in, not layered on top.
  • Multiple Streams: Supports many independent streams in one connection. Loss in one stream doesn't block others.
  • 0-RTT Connection Resumption: Returning clients can send data in the first packet (zero round trips).
  • Connection Migration: Connection survives IP address changes (e.g., switching from WiFi to cellular).

QUIC implements reliability, congestion control, and flow control in userspace, giving the protocol designers much more flexibility than kernel-based TCP.

Adoption:

As of 2024, QUIC/HTTP/3 is used by:

  • Google services (Search, YouTube, Gmail)
  • Facebook/Meta
  • Cloudflare
  • Major CDNs

Most modern browsers support HTTP/3. It's particularly beneficial for mobile users and high-latency scenarios.

Environment Setup

We need the topology from Lab 7 (Red, Blue, and a Bridge connecting them). To ensure a clean, consistent environment, we'll use a setup script.

Understanding the Setup Script

The script creates the following topology:

         [Host: 10.0.0.1]
               |
               | (br-lab bridge)
               |
       +-------+-------+
       |               |
  [Red: 10.0.0.2] [Blue: 10.0.0.3]

Key operations:

  1. Clean up any existing namespaces and bridges from previous labs
  2. Create a Linux bridge (br-lab) acting as a virtual switch
  3. Create two network namespaces (red and blue)
  4. Create veth pairs connecting each namespace to the bridge
  5. Assign IP addresses and routes
  6. Enable NAT for internet access
  7. Each machine has both an IP address (10.0.0.x) and a hostname (x.lab). This mirrors how real internet servers work—they have IP addresses for routing, but we refer to them by domain names.

Step 1: Create the Setup Script

Create lab8_setup.sh with the following content:

#!/bin/bash
set -euo pipefail

if [ "$EUID" -ne 0 ]; then 
    echo "Please run as root (use sudo)"
    exit 1
fi

echo "[*] Cleaning up old environment..."
ip netns delete red 2>/dev/null || true
ip netns delete blue 2>/dev/null || true
ip link delete br-lab 2>/dev/null || true

echo "[*] Creating Bridge..."
ip link add br-lab type bridge
ip link set br-lab up
ip addr add 10.0.0.1/24 dev br-lab

echo "[*] Creating Namespaces..."
ip netns add red
ip netns add blue

echo "[*] Wiring Red..."
ip link add veth-red type veth peer name veth-red-br
ip link set veth-red-br master br-lab
ip link set veth-red-br up
ip link set veth-red netns red
ip netns exec red ip addr add 10.0.0.2/24 dev veth-red
ip netns exec red ip link set veth-red up
ip netns exec red ip link set lo up
ip netns exec red ip route add default via 10.0.0.1

echo "[*] Wiring Blue..."
ip link add veth-blue type veth peer name veth-blue-br
ip link set veth-blue-br master br-lab
ip link set veth-blue-br up
ip link set veth-blue netns blue
ip netns exec blue ip addr add 10.0.0.3/24 dev veth-blue
ip netns exec blue ip link set veth-blue up
ip netns exec blue ip link set lo up
ip netns exec blue ip route add default via 10.0.0.1

echo "[*] Enabling NAT on Host..."
sysctl -w net.ipv4.ip_forward=1 > /dev/null

# Determine internet-facing interface
IFACE=$(ip route get 8.8.8.8 | grep -oP 'dev \K\S+')
echo "[*] Detected internet interface: $IFACE"

# Configure NAT (idempotent - won't fail if already exists)
nft add table ip nat 2>/dev/null || true
nft add chain ip nat postrouting { type nat hook postrouting priority srcnat \; } 2>/dev/null || true
nft add rule ip nat postrouting ip saddr 10.0.0.0/24 oifname "$IFACE" masquerade 2>/dev/null || true

# Configure host names
if ! grep -q "# Lab8 Configuration" /etc/hosts; then
    echo "" >> /etc/hosts
    echo "# Lab8 Configuration" >> /etc/hosts
    echo "10.0.0.1        host.lab" >> /etc/hosts
    echo "10.0.0.2        red.lab" >> /etc/hosts
    echo "10.0.0.3        blue.lab" >> /etc/hosts
fi

echo ">>> Setup Complete"
echo "    Red:  10.0.0.2"
echo "    Blue: 10.0.0.3"
echo "    Host: 10.0.0.1"

Script Explanation:

  • set -euo pipefail: Exit immediately if any command fails
  • [ "$EUID" -ne 0 ]: Check if running as root (EUID = Effective User ID)
  • 2>/dev/null || true: Suppress error messages and don't fail if cleanup targets don't exist
  • ip route get 8.8.8.8: A way to determine which interface routes to the internet
  • grep -oP 'dev \K\S+': Extract just the interface name
  • Hostname entries map red.lab → 10.0.0.2, blue.lab → 10.0.0.3
  • NAT commands use || true to be idempotent (can run multiple times safely)

Step 2: Make the Script Executable and Run It

chmod +x lab8_setup.sh
sudo ./lab8_setup.sh

Expected output:

[*] Cleaning up old environment...
[*] Creating Bridge...
[*] Creating Namespaces...
[*] Wiring Red...
[*] Wiring Blue...
[*] Enabling NAT on Host...
[*] Detected internet interface: eth0
[✓] Setup Complete
    Red:  10.0.0.2
    Blue: 10.0.0.3
    Host: 10.0.0.1

Step 3: Verify the Setup

Test connectivity between Red and Blue:

sudo ip netns exec red ping -c 2 10.0.0.3

Test internet access from Red:

sudo ip netns exec red ping -c 2 8.8.8.8

Both should succeed. If they fail:

  • Check that the setup script completed without errors
  • Verify interfaces are UP: ip link show br-lab, sudo ip netns exec red ip link
  • Verify routes: sudo ip netns exec red ip route show
  • Verify NAT rules: sudo nft list ruleset

You're now ready to begin the hands-on exercises!

Hands-on Exercises

These exercises build progressively, demonstrating the differences between UDP and TCP, socket state management, and finally securing communications with TLS encryption.

Exercise A: UDP Communication (The Connectionless Message)

Theory: UDP's Simplicity

UDP is the "postcards" of the internet. You write a message, put on an address, and drop it in the mailbox. You hope it arrives, but you don't get confirmation. There's no handshake, no connection establishment—just send data and hope for the best.

This simplicity has advantages:

  • Low latency: No handshake delay
  • No connection state: Server can handle many clients with minimal resources
  • Multicast/broadcast capable: Can send to multiple recipients simultaneously

For this exercise, we'll send a message from Red to Blue using UDP and observe the traffic with tcpdump. Because UDP is connectionless, you'll see the data appear immediately on the wire without any preceding handshake packets.

Practice: Sending UDP Messages

We'll use three terminal windows:

  1. Terminal 1 (Host): The "wiretapper" watching traffic on the bridge
  2. Terminal 2 (Blue): The UDP server listening for messages
  3. Terminal 3 (Red): The UDP client sending messages

Step 1: Start the Wiretapper

In Terminal 1 on the host, start capturing UDP traffic on port 9000:

sudo tcpdump -i br-lab -X udp port 9000

Let's break down this command:

  • -i br-lab: Capture on the bridge interface (where we can see traffic between Red and Blue)
  • -X: Display packet contents in both hex and ASCII
  • udp port 9000: BPF (Berkeley Packet Filter) expression matching UDP packets with source or destination port 9000

You should see:

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-lab, link-type EN10MB (Ethernet), capture size 262144 bytes

Leave this running. It's now waiting to capture packets.

Step 2: Start the UDP Server

In Terminal 2, start a UDP listener in the Blue namespace:

sudo ip netns exec blue ncat -u -l -p 9000

Command breakdown:

  • ip netns exec blue: Run command in Blue's namespace
  • ncat: Network cat implementation (from nmap package)
  • -u: Use UDP instead of TCP
  • -l: Listen mode (act as server)
  • -p 9000: Listen on port 9000

The command appears to hang: this is correct. It's waiting for incoming datagrams.

Step 3: Start the UDP Client

In Terminal 3, connect to the Blue server from Red:

sudo ip netns exec red ncat -u 10.0.0.3 9000

Command breakdown:

  • ncat -u 10.0.0.3 9000: Connect to 10.0.0.3 on port 9000 using UDP

The terminal is now ready for input. You can type messages.

Step 4: Send a Message

In Terminal 3 (Red client), type:

Hello UDP World

Press Enter.

Step 5: Observe the Results

  • Terminal 2 (Blue server): Should display "Hello UDP World"
  • Terminal 1 (tcpdump): Should show the captured packet

The tcpdump output will look something like this:

15:42:18.123456 IP 10.0.0.2.45678 > 10.0.0.3.9000: UDP, length 16
    0x0000:  4500 002c 1234 4000 4011 abcd 0a00 0002  E..,..@.@.......
    0x0010:  0a00 0003 b26e 2328 0018 5678 4865 6c6c  .....n#(..VxHell
    0x0020:  6f20 5544 5020 576f 726c 640a            o.UDP.World.

Key observations:

  • Source: 10.0.0.2.45678 (Red, ephemeral port)
  • Destination: 10.0.0.3.9000 (Blue, our server port)
  • Protocol: UDP
  • You can see "Hello UDP World" in the ASCII column on the right

Step 6: Critical Analysis

Look carefully at the tcpdump output. Count the packets:

  • You should see exactly ONE packet—the data packet
  • There were NO packets before the message (no handshake)
  • There were NO acknowledgment packets after the message

Try sending more messages in Terminal 3:

Message two
Third message

Each appears immediately in Terminal 2 and Terminal 1 as a separate UDP datagram.

Step 7: Cleanup

Press Ctrl+C in all three terminals to stop the processes.

Understanding What Happened

When you pressed Enter in Terminal 3:

  1. Red's ncat process wrote "Hello UDP World\n" to a UDP socket
  2. Red's kernel wrapped this in a UDP datagram (8-byte UDP header + data)
  3. Red's kernel wrapped the UDP datagram in an IP packet (20-byte IP header + UDP datagram)
  4. Red's kernel wrapped the IP packet in an Ethernet frame (14-byte Ethernet header + IP packet)
  5. Frame sent out veth-red interface
  6. Frame traversed veth pair to bridge
  7. Bridge forwarded frame to veth-blue-br
  8. Frame arrived at Blue's veth-blue interface
  9. Blue's kernel unwrapped layers and delivered payload to ncat process listening on port 9000
  10. Blue's ncat wrote payload to stdout

All of this happened in microseconds, with no connection setup or teardown.

Deliverable A

Provide the following:

  1. tcpdump Output: Screenshot of the tcpdump output showing at least one UDP packet. The output must clearly show:
    • Source IP and port (Red, ephemeral)
    • Destination IP and port (Blue, 9000)
    • The plaintext message in the hex/ASCII dump

Exercise B: TCP Communication and Socket State Inspection

Theory: TCP's Statefulness

Unlike UDP, TCP maintains connection state. Before any data flows, both sides must agree to communicate (handshake). The kernel tracks this state throughout the connection's lifetime.

In this exercise, we'll:

  1. Start a TCP server in Blue
  2. Use nmap to discover the open port (simulating reconnaissance)
  3. Capture the three-way handshake with tcpdump
  4. Establish a connection from Red
  5. Inspect the kernel's socket state table to see the ESTABLISHED connection
  6. Observe the four-way handshake when closing

This demonstrates TCP's stateful nature and introduces important diagnostic tools.

Practice: TCP Connection Lifecycle

Step 1: Start the TCP Server

In Terminal 1, start a TCP listener in Blue on port 8080:

sudo ip netns exec blue ncat -l -p 8080

Note the absence of -u flag—this defaults to TCP mode.

The command waits for connections. In TCP, the server must be listening before clients can connect (unlike UDP where you can send to a port that isn't listening).

Step 2: Verify Server is Listening

In Terminal 2, check Blue's listening sockets:

sudo ip netns exec blue ss -tln

Command breakdown:

  • ss: Socket statistics utility
  • -t: Show TCP sockets
  • -l: Show listening sockets only
  • -n: Numeric output (don't resolve port names)

Expected output:

State   Recv-Q  Send-Q  Local Address:Port   Peer Address:Port
LISTEN  0       128     0.0.0.0:8080         0.0.0.0:*

This shows:

  • State: LISTEN (waiting for connections)
  • Recv-Q: 0 (no data in receive queue)
  • Send-Q: 128 (this is actually the backlog—max pending connections)
  • Local Address:Port: 0.0.0.0:8080 (listening on all interfaces)
  • Peer Address:Port: 0.0.0.0:* (no peer yet, not connected)

The 0.0.0.0 address means "any interface"—the server will accept connections on any IP address belonging to this machine.

Step 3: Port Reconnaissance with nmap

In Terminal 2, scan Blue from Red to discover open ports:

sudo ip netns exec red nmap -p 8080 10.0.0.3

Command breakdown:

  • nmap: Network exploration tool
  • -p 8080: Scan only port 8080
  • 10.0.0.3: Target IP (Blue)

Expected output:

Starting Nmap 7.93 ( https://nmap.org )
Nmap scan report for 10.0.0.3
Host is up (0.000050s latency).

PORT     STATE SERVICE
8080/tcp open  http-proxy

Nmap done: 1 IP address (1 host up) scanned in 0.10 seconds

Key information:

  • Port 8080 is open (accepting connections)
  • Nmap identified it as potentially being "http-proxy" based on common port conventions (though it's actually just our ncat listener)
  • Latency is very low (microseconds) because everything is local

How did nmap determine the port is open? nmap sent a SYN packet. Blue responded with SYN-ACK (indicating willingness to connect). nmap then sent RST to abort the connection. This "SYN scan" is less noisy than completing the full handshake.

Step 4: Capture the Three-Way Handshake

In Terminal 3, start capturing TCP control packets (SYN, FIN, RST) on the bridge:

sudo tcpdump -i br-lab "tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0"

This is a complex BPF filter. Let's decode it:

  • tcp[tcpflags]: Access the TCP flags byte in the header
  • & (tcp-syn|tcp-fin|tcp-rst): Bitwise AND with mask for SYN, FIN, or RST flags
  • != 0: Match if any of these flags are set

This captures connection establishment (SYN) and termination (FIN, RST) packets, filtering out normal data packets.

Leave this running.

Step 5: Establish a Connection

In Terminal 2, connect from Red to Blue:

sudo ip netns exec red ncat 10.0.0.3 8080

This time we're not using -l (this is the client side) and not using -u (defaulting to TCP).

Step 6: Observe the Handshake

In Terminal 3 (tcpdump), you should see three packets:

16:15:32.123456 IP 10.0.0.2.45678 > 10.0.0.3.8080: Flags [S], seq 1234567890, win 65535
16:15:32.123467 IP 10.0.0.3.8080 > 10.0.0.2.45678: Flags [S.], seq 9876543210, ack 1234567891, win 65535
16:15:32.123478 IP 10.0.0.2.45678 > 10.0.0.3.8080: Flags [.], ack 9876543211, win 65535

Let's analyze each packet:

Packet 1: SYN

  • Source: Red (10.0.0.2, ephemeral port 45678)
  • Destination: Blue (10.0.0.3, port 8080)
  • Flags: [S] (SYN only)
  • Sequence number: Red's initial sequence number (ISN)
  • This is Red saying: "I want to establish a connection. My starting sequence number is 1234567890."

Packet 2: SYN-ACK

  • Source: Blue (10.0.0.3, port 8080)
  • Destination: Red (10.0.0.2, port 45678)
  • Flags: [S.] (SYN + ACK)
  • Sequence number: Blue's ISN
  • Acknowledgment: Red's ISN + 1
  • This is Blue saying: "I accept the connection. My starting sequence number is 9876543210, and I'm ready to receive byte 1234567891 from you."

Packet 3: ACK

  • Source: Red
  • Destination: Blue
  • Flags: [.] (ACK only, represented as a dot)
  • Acknowledgment: Blue's ISN + 1
  • This is Red saying: "Acknowledged. I'm ready to receive byte 9876543211 from you."

The connection is now ESTABLISHED on both sides.

Step 7: Inspect Socket State

In Terminal 4 (new terminal), check Blue's socket table:

sudo ip netns exec blue ss -tna

Adding the -a flag shows all states (not just listening).

Expected output:

State       Recv-Q  Send-Q  Local Address:Port   Peer Address:Port
LISTEN      0       128     0.0.0.0:8080         0.0.0.0:*
ESTAB       0       0       10.0.0.3:8080        10.0.0.2:45678

Now we see two entries:

  1. The original LISTEN socket (still waiting for additional connections)
  2. A new ESTAB (ESTABLISHED) socket representing the connected client

The ESTABLISHED socket shows the full four-tuple:

  • Local: 10.0.0.3:8080 (Blue's IP and the server port)
  • Peer: 10.0.0.2:45678 (Red's IP and Red's ephemeral port)

Also check from Red's perspective:

sudo ip netns exec red ss -tna

Expected output:

State       Recv-Q  Send-Q  Local Address:Port   Peer Address:Port
ESTAB       0       0       10.0.0.2:45678       10.0.0.3:8080

Red sees one ESTABLISHED connection. Notice the local and peer addresses are swapped from Blue's perspective—same connection, different viewpoint.

Step 8: Data Transfer

The connection is established. Type a message in Terminal 2 (Red client):

Testing TCP Connection

Press Enter. The message should appear in Terminal 1 (Blue server).

Now type a response in Terminal 1:

Message received

Press Enter. It should appear in Terminal 2.

TCP provides bidirectional communication over a single connection.

Step 9: Connection Termination

Press Ctrl+D (EOF, end of file) in Terminal 2 (Red client). This closes Red's side of the connection.

In Terminal 3 (tcpdump), you should see the four-way handshake:

16:20:15.123456 IP 10.0.0.2.45678 > 10.0.0.3.8080: Flags [F.], seq ..., ack ...
16:20:15.123467 IP 10.0.0.3.8080 > 10.0.0.2.45678: Flags [.], ack ...
16:20:15.123478 IP 10.0.0.3.8080 > 10.0.0.2.45678: Flags [F.], seq ..., ack ...
16:20:15.123489 IP 10.0.0.2.45678 > 10.0.0.3.8080: Flags [.], ack ...

Packet 1: FIN from Red

  • Red says: "I'm done sending data. I'm closing my side of the connection."

Packet 2: ACK from Blue

  • Blue acknowledges Red's FIN: "I received your close notification."

Packet 3: FIN from Blue

  • Blue says: "I'm also done. I'm closing my side."

Packet 4: ACK from Red

  • Red acknowledges Blue's FIN: "Confirmed. Connection fully closed."

Immediately after this, check the socket state:

sudo ip netns exec red ss -tna

You might see:

State       Recv-Q  Send-Q  Local Address:Port   Peer Address:Port
TIME-WAIT   0       0       10.0.0.2:45678       10.0.0.3:8080

The connection enters TIME-WAIT state for typically 60 seconds to ensure all packets have cleared the network. This prevents old duplicate packets from being misinterpreted as part of a new connection using the same port numbers.

After the timeout, the connection disappears entirely from the socket table.

Step 10: Compare with UDP

Think about the differences:

  • UDP: No handshake, no state, no acknowledgments, just send data
  • TCP: Three-way handshake to establish, state tracking during connection, four-way handshake to terminate

TCP's complexity provides reliability at the cost of overhead and latency.

Understanding TCP State Transitions

The states we observed:

  1. LISTEN → Waiting for incoming connections
  2. SYN_SENT → (We didn't see this as client because transition was fast)
  3. ESTABLISHED → Active connection, data transfer phase
  4. FIN_WAIT_1 → (Brief state during close)
  5. FIN_WAIT_2 → (Brief state during close)
  6. TIME_WAIT → Ensuring clean shutdown

In production environments, you might see:

  • Many TIME_WAIT connections after a load spike (normal)
  • Connections stuck in SYN_SENT (peer not responding)
  • Many CLOSE_WAIT (application not properly closing connections—potential resource leak)

Deliverable B

Provide the following:

  1. ss Output: The output of sudo ip netns exec blue ss -tna showing both the LISTEN socket and the ESTABLISHED connection. Clearly label which line is which.
  2. tcpdump Output: The captured three-way handshake showing:
    • Packet 1: SYN (Flags [S])
    • Packet 2: SYN-ACK (Flags [S.])
    • Packet 3: ACK (Flags [.])

Exercise C: Public Key Infrastructure (Creating a Certificate Authority)

Theory: The Trust Problem

Encryption solves the confidentiality problem. But it creates a new problem: authentication. How do you know you're talking to the real Blue server and not an attacker pretending to be Blue?

Consider this attack scenario:

  1. Red wants to connect to Blue
  2. Attacker intercepts the connection
  3. Attacker establishes two connections: Attacker↔Red and Attacker↔Blue
  4. Attacker decrypts messages from Red, reads them, re-encrypts, and forwards to Blue
  5. Neither Red nor Blue realizes they're talking through a middleman

This is a classic Man-in-the-Middle (MITM) attack. Encryption alone doesn't prevent it.

PKI solves this with:

  1. Certificates: Digital documents binding a public key to an identity (domain name, organization)
  2. Digital Signatures: Certificates are signed by a trusted Certificate Authority (CA)
  3. Trust Anchors: Your system comes with a pre-installed list of trusted root CAs

When Red connects to Blue:

  1. Blue sends its certificate
  2. Red checks: Is this certificate signed by a CA I trust?
  3. Red verifies the certificate is for the correct domain/identity
  4. Red verifies the certificate hasn't expired
  5. If all checks pass, Red uses the public key from the certificate to establish encryption

The attacker can't forge a certificate signed by a trusted CA (they don't have the CA's private key).

Certificate Components:

A certificate contains:

  • Subject: Who the certificate is for (e.g., CN=blue.lab, Common Name)
  • Issuer: Who signed it (e.g., CN=root-ca)
  • Public Key: The subject's public key
  • Validity Period: Not Before and Not After dates
  • Signature: CA's digital signature over all the above

X.509 Standard:

Certificates use the X.509 format, an ITU-T standard. The format is binary (DER encoding) but often converted to text (PEM encoding) for easier handling. PEM format looks like:

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKL0h...
(many lines of Base64-encoded data)
-----END CERTIFICATE-----

Practice: Building Your Own PKI

In production, you'd obtain certificates from a public CA like Let's Encrypt, DigiCert, or GlobalSign. For this lab, we'll create our own CA and sign our own certificates. This gives insight into how PKI works internally.

Step 1: Create a Working Directory

mkdir -p pki
cd pki

This directory will contain all our keys and certificates. In production, private keys would be stored with strict access controls (chmod 600).

Step 2: Generate the Certificate Authority

First, we create the root of our trust hierarchy—the CA itself.

openssl req -new -x509 -days 365 -nodes \
  -subj "/C=RO/ST=Bucharest/L=Lab/O=MyCA/CN=root-ca" \
  -keyout ca.key -out ca.crt

Let's break down this complex command:

  • openssl req: Certificate request utility
  • -new: Generate a new certificate request
  • -x509: Output a self-signed certificate instead of a CSR
  • -days 365: Certificate valid for 365 days
  • -nodes: Don't encrypt the private key (no DES, "nodes" = no DES). In production, you'd protect the CA key with a passphrase.
  • -subj: Certificate subject (identity):
    • C=RO: Country (Romania)
    • ST=Bucharest: State/Province
    • L=Lab: Locality
    • O=MyCA: Organization
    • CN=root-ca: Common Name (identifies this CA)
  • -keyout ca.key: Write private key to this file
  • -out ca.crt: Write certificate to this file

This creates two files:

  • ca.key: The CA's private key. KEEP THIS SECRET. Anyone with this key can sign certificates that your system will trust.
  • ca.crt: The CA's self-signed certificate. This is the "trust anchor" that clients will use to verify other certificates.

Step 3: Inspect the CA Certificate

Let's see what we created:

openssl x509 -in ca.crt -text -noout

Command breakdown:

  • openssl x509: Certificate utility
  • -in ca.crt: Input file
  • -text: Output human-readable text
  • -noout: Don't output the certificate itself (just the decoded text)

Expected output (abbreviated):

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 12345678901234567890
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=RO, ST=Bucharest, L=Lab, O=MyCA, CN=root-ca
        Validity
            Not Before: Nov  1 10:00:00 2024 GMT
            Not After : Nov  1 10:00:00 2025 GMT
        Subject: C=RO, ST=Bucharest, L=Lab, O=MyCA, CN=root-ca
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:d4:7a:...
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: ...
            X509v3 Authority Key Identifier: ...
            X509v3 Basic Constraints: critical
                CA:TRUE

Key observations:

  • Issuer == Subject: This is self-signed (the CA signed its own certificate)
  • Validity: 365 days from creation
  • Public Key: 2048-bit RSA key
  • CA:TRUE: This certificate can sign other certificates

Step 4: Generate the Server's Private Key

Now we create a private key for the Blue server:

openssl genrsa -out blue.key 2048

Command breakdown:

  • openssl genrsa: Generate RSA private key
  • -out blue.key: Output file
  • 2048: Key size in bits (2048 is standard; 4096 for higher security)

This generates blue.key, a 2048-bit RSA private key. This file must be kept secret. Anyone with this key can impersonate the Blue server.

Step 5: Generate a Certificate Signing Request (CSR)

The server creates a CSR to ask the CA to sign a certificate:

openssl req -new -key blue.key \
  -subj "/C=RO/ST=Bucharest/L=Lab/O=BlueServer/CN=blue.lab" \
  -out blue.csr

Command breakdown:

  • openssl req -new: Create a new certificate request
  • -key blue.key: Use this private key
  • -subj: Certificate subject:
    • CN=blue.lab: Common Name (this should match the domain name clients use to connect)
  • -out blue.csr: Output CSR file

The CSR contains:

  • The server's public key (derived from blue.key)
  • The desired subject (identity)
  • A signature proving the requester possesses the private key

Why a CSR? In production, you'd send the CSR to a public CA. The CA verifies your identity (sometimes requiring domain ownership verification, sometimes requiring extensive documentation). Once satisfied, the CA signs your CSR, creating a certificate. You never share your private key with the CA.

Step 6: Sign the Certificate (Act as CA)

Now we act as the CA and sign Blue's CSR:

openssl x509 -req -in blue.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out blue.crt -days 365

Command breakdown:

  • openssl x509 -req: Sign a certificate request
  • -in blue.csr: Input CSR
  • -CA ca.crt: CA's certificate
  • -CAkey ca.key: CA's private key (this is why we keep it secret)
  • -CAcreateserial: Create a serial number file (ca.srl) to track issued certificates
  • -out blue.crt: Output signed certificate
  • -days 365: Certificate valid for 365 days

This creates blue.crt, signed by our CA. The signature proves the CA vouches for the binding between the public key and the identity "blue.lab."

Step 7: Inspect the Server Certificate

openssl x509 -in blue.crt -text -noout

Key observations:

  • Issuer: CN=root-ca (signed by our CA)
  • Subject: CN=blue.lab (the server's identity)
  • Issuer ≠ Subject: This is NOT self-signed; it's signed by the CA
  • Signature: Contains the CA's cryptographic signature

Step 8: Verify the Certificate Chain

Clients will verify that blue.crt is signed by ca.crt:

openssl verify -CAfile ca.crt blue.crt

Expected output:

blue.crt: OK

This confirms the certificate chain is valid. If we modified blue.crt or used a different CA, verification would fail.

Step 9: File Inventory

List the files we created:

ls -lh pki

Expected output:

-rw-r--r-- 1 user user 1.3K Nov  1 10:00 ca.crt
-rw------- 1 user user 1.7K Nov  1 10:00 ca.key
-rw-r--r-- 1 user user   17 Nov  1 10:00 ca.srl
-rw-r--r-- 1 user user 1.1K Nov  1 10:00 blue.crt
-rw-r--r-- 1 user user  920 Nov  1 10:00 blue.csr
-rw------- 1 user user 1.7K Nov  1 10:00 blue.key

Files explained:

  • ca.crt: CA certificate (public, distribute to clients)
  • ca.key: CA private key (KEEP SECRET)
  • ca.srl: Serial number tracker (internal bookkeeping)
  • blue.crt: Blue's signed certificate (public)
  • blue.csr: Certificate signing request (can be deleted after signing)
  • blue.key: Blue's private key (KEEP SECRET)

Understanding the Trust Model

In our lab:

  • Clients trust ca.crt (we'll explicitly provide it)
  • blue.crt is signed by ca.crt
  • Therefore, clients trust blue.crt

In the real world:

  • Your browser/OS ships with ~150 pre-trusted root CAs
  • When you visit https://example.com, the server sends its certificate
  • Browser verifies the certificate chain: example.com cert → Intermediate CA → Root CA (in trust store)
  • If chain is valid and domain name matches, connection is trusted

This is why certificate authorities are critical infrastructure. Compromise of a CA's private key would allow attackers to create trusted certificates for any domain.

Deliverable C: Provide the following:

  1. File Listing: Output of ls -lh pki showing all six files with their sizes.
  2. Certificate Inspection: Output of openssl x509 -in blue.crt -text -noout showing the certificate details. Circle or highlight:
    • The Issuer (should be root-ca)
    • The Subject (should be blue.lab)
    • The Validity dates

Exercise D: Secured Transport with TLS Encryption

Theory: Encryption in Action

Now we put everything together: TCP for reliable transport + TLS for encryption using our PKI.

When Red connects to Blue with TLS:

  1. TCP Handshake: Establish connection (SYN, SYN-ACK, ACK)
  2. TLS Handshake:
    • Negotiate cipher suite and TLS version
    • Blue sends its certificate (blue.crt)
    • Red verifies the certificate is signed by ca.crt (which we'll provide)
    • Exchange keys using public key cryptography
    • Derive shared symmetric encryption keys
  3. Encrypted Data Transfer: All application data encrypted with the shared keys

After the handshake, all data is encrypted with fast symmetric encryption (typically AES), but the keys were securely exchanged using asymmetric encryption.

We'll use tcpdump to show that eavesdroppers (our host acting as "man in the middle") can't read the encrypted traffic.

Practice: TLS-Secured Connection

Step 1: Start the Secure Server

In Terminal 1, start ncat in SSL/TLS mode in Blue:

sudo ip netns exec blue ncat --ssl --ssl-cert pki/blue.crt --ssl-key pki/blue.key -l -p 8443

Command breakdown:

  • --ssl: Enable SSL/TLS
  • --ssl-cert pki/blue.crt: Server certificate
  • --ssl-key pki/blue.key: Server private key
  • -l -p 8443: Listen on port 8443 (can choose any port)

The server is now ready to accept TLS connections.

Step 2: Start the Wiretapper

In Terminal 2 on the host, capture traffic on port 8443:

sudo tcpdump -i br-lab -X -s 0 port 8443

Command breakdown:

  • -X: Show hex/ASCII payload
  • -s 0: Capture full packets (no truncation)
  • port 8443: Match source or destination port 8443

This is our "attacker" position, intercepting traffic between Red and Blue.

Step 3: Start the Secure Client

In Terminal 3, connect from Red with TLS enabled:

sudo ip netns exec red ncat --ssl --ssl-verify --ssl-trustfile pki/ca.crt 10.0.0.3 8443

Command breakdown:

  • --ssl: Enable SSL/TLS
  • --ssl-verify: Verify server certificate (don't accept self-signed or invalid certificates)
  • --ssl-trustfile pki/ca.crt: Trust anchor (our CA certificate)
  • 10.0.0.3 8443: Connect to Blue on port 8443

You should see the connection succeed. If you see an error like "certificate verification failed," check:

  • blue.crt Common Name matches the IP/hostname you're connecting to (we used blue.lab in the cert but are connecting to 10.0.0.3—this mismatch is OK for this lab since we're using --ssl-trustfile)
  • ca.crt is the correct CA certificate
  • blue.crt is signed by ca.crt

Step 4: Observe the TLS Handshake

In Terminal 2 (tcpdump), you should see several packets immediately after connection. These are the TLS handshake:

16:30:45.123456 IP 10.0.0.2.45678 > 10.0.0.3.8443: Flags [P.], seq 1:517, ack 1, length 516
    0x0000:  4500 0234 1234 4000 4006 abcd 0a00 0002  E..4.4@.@.......
    0x0010:  0a00 0003 b26e 20fb 1234 5678 1234 5678  .....n...4Vx.4Vx
    0x0020:  5018 ffff abcd 0000 1603 0301 ff01 0001  P...............
    0x0030:  fb03 0356 4e12 3456 789a bcde f012 3456  ...VN.4Vx.....4V
    0x0040:  789a bcde f012 3456 789a bcde f012 3456  x...4Vx.....4V
    ...

Notice:

  • The payload starts with 0x16 0x03 0x03 (TLS Handshake, TLS 1.2)
  • The data looks random (it contains encrypted pre-master secrets, cipher suites, etc.)
  • You can't read any meaningful content

Step 5: Send a Secret Message

In Terminal 3 (Red client), type:

This is a Secret Password: MyP@ssw0rd123

Press Enter.

The message should appear in Terminal 1 (Blue server) in plaintext—the TLS layer decrypts it automatically before delivering to the application.

Step 6: Inspect the Encrypted Traffic

Look at Terminal 2 (tcpdump). You should see packets containing the encrypted message:

16:31:02.234567 IP 10.0.0.2.45678 > 10.0.0.3.8443: Flags [P.], seq 517:572, length 55
    0x0000:  4500 005f 1235 4000 4006 abc2 0a00 0002  E.._.5@.@.......
    0x0010:  0a00 0003 b26e 20fb 1234 5890 1234 5890  .....n...4X..4X.
    0x0020:  5018 ffff abcd 0000 1703 0300 32a4 f7b3  P.........2.....
    0x0030:  8c44 e291 bc73 4fa8 d612 e8f3 9a45 b7c9  .D...sO......E..
    0x0040:  1f22 d847 b3a5 c7e9 2d48 f6a4 b812 d7c4  .".G....-H......
    0x0050:  3a95 e8f6 b2d1 c847 a5e3 9f                :......G...

Critical observation: Can you read "This is a Secret Password" in the hex dump?

No! You see random-looking bytes. The actual payload is:

  • Encrypted with AES or ChaCha20 (symmetric encryption)
  • Authenticated with HMAC or AEAD
  • Completely unreadable without the encryption keys

Compare this to Exercise A (UDP) where you could clearly read "Hello UDP World" in the packet capture.

Step 7: Send More Data

Try sending additional messages:

Credit Card: 4532-1234-5678-9012
SSN: 123-45-6789
API Key: sk_live_1234567890abcdefghijklmnopqrstuvwxyz

Each appears in plaintext on the server (Terminal 1) but as encrypted gibberish in the packet capture (Terminal 2).

This is exactly how HTTPS protects your sensitive data when you browse websites. Between your browser and the web server, your data is encrypted. Even if someone intercepts the packets (your ISP, a coffee shop WiFi operator, a government agency), they see only encrypted data.

Step 8: Cleanup

Press Ctrl+C in all terminals to stop the processes.

Understanding What Happened

The TLS handshake (simplified):

  1. Red sends "ClientHello" with supported cipher suites
  2. Blue sends "ServerHello" with chosen cipher suite + blue.crt certificate
  3. Red verifies blue.crt is signed by ca.crt (from --ssl-trustfile)
  4. Red verifies certificate CN, validity dates, etc.
  5. Red generates a pre-master secret, encrypts it with Blue's public key (from blue.crt), sends it
  6. Both sides derive the same symmetric encryption keys from the pre-master secret
  7. Both sides send "Finished" messages encrypted with the new keys
  8. All subsequent data is encrypted with the symmetric keys

The symmetric keys are never transmitted—both sides independently compute them from the shared pre-master secret.

Real-World Context

This is how HTTPS works:

  • Your browser has ~150 trusted root CAs built in
  • You visit https://example.com
  • Server sends its certificate, signed by a trusted CA
  • Browser verifies the chain: example.com cert → Intermediate CA → Root CA
  • If valid, browser shows padlock icon
  • All data encrypted with TLS

Without TLS, someone could:

  • Read your passwords
  • Steal your session cookies
  • Intercept your credit card numbers
  • Modify downloads to inject malware

This is why the web has largely moved to HTTPS-by-default.

Deliverable D: Provide the following:

  1. tcpdump Output: Screenshot of the packet capture showing encrypted data. The output must clearly show:
    • Source and destination (Red to Blue on port 8443)
    • The hex dump of the payload
    • The payload looks like random bytes (NOT readable text)
  2. Comparison: Side-by-side comparison (can be text description or screenshot):
    • Exercise A UDP packet capture (plaintext visible)
    • Exercise D TLS packet capture (encrypted)

Reference: Command Quick Guide

This section provides a quick reference for commands introduced in this lab.

Network Communication Tools

# UDP Server
ncat -u -l -p <port>

# UDP Client
ncat -u <ip> <port>

# TCP Server
ncat -l -p <port>

# TCP Client
ncat <ip> <port>

# TCP Server with TLS
ncat --ssl --ssl-cert <cert> --ssl-key <key> -l -p <port>

# TCP Client with TLS (verify certificate)
ncat --ssl --ssl-verify --ssl-trustfile <ca_cert> <ip> <port>

# TCP Client with TLS (no verification - insecure)
ncat --ssl <ip> <port>

Socket Inspection

# Show all TCP sockets
ss -ta

# Show all TCP sockets, numeric, all states
ss -tna

# Show listening TCP sockets
ss -tln

# Show TCP sockets with process info (requires root)
ss -tnap

# Show UDP sockets
ss -una

# Show socket memory usage
ss -tm

# Show extended socket information
ss -tei

# Filter by state
ss -t state established
ss -t state time-wait

# Filter by port
ss -tn sport = :8080
ss -tn dport = :443

Port Scanning (nmap)

# Scan specific port
nmap -p 22 <ip>

# Scan port range
nmap -p 1-1000 <ip>

# Scan all ports (slow)
nmap -p- <ip>

# Scan common ports (faster)
nmap --top-ports 100 <ip>

# TCP SYN scan (stealthy, requires root)
sudo nmap -sS <ip>

# TCP Connect scan (no root required)
nmap -sT <ip>

# UDP scan (slow)
sudo nmap -sU <ip>

# Service version detection
nmap -sV <ip>

# OS detection
sudo nmap -O <ip>

# Aggressive scan (OS, version, scripts)
sudo nmap -A <ip>

# Scan subnet
nmap 10.0.0.0/24

# Fast scan (no DNS resolution, no ping)
nmap -n -Pn <ip>

Packet Capture (tcpdump)

# Capture on interface
sudo tcpdump -i <interface>

# Show hex and ASCII
sudo tcpdump -i <interface> -X

# Capture specific port
sudo tcpdump -i <interface> port 8080

# Capture specific protocol
sudo tcpdump -i <interface> tcp
sudo tcpdump -i <interface> udp

# Capture TCP SYN packets
sudo tcpdump -i <interface> "tcp[tcpflags] & tcp-syn != 0"

# Capture TCP handshakes (SYN, FIN, RST)
sudo tcpdump -i <interface> "tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0"

# Save to file
sudo tcpdump -i <interface> -w capture.pcap

# Read from file
tcpdump -r capture.pcap

# Capture full packets (no truncation)
sudo tcpdump -i <interface> -s 0

# Show absolute sequence numbers
sudo tcpdump -i <interface> -S

# Don't resolve hostnames (faster)
sudo tcpdump -i <interface> -n

# Capture only N packets
sudo tcpdump -i <interface> -c 10

Certificate Management (openssl)

# Generate self-signed CA
openssl req -new -x509 -days 365 -nodes \
  -subj "/C=XX/ST=State/L=City/O=Org/CN=CA" \
  -keyout ca.key -out ca.crt

# Generate private key
openssl genrsa -out server.key 2048
openssl genrsa -out server.key 4096  # More secure

# Generate CSR
openssl req -new -key server.key \
  -subj "/C=XX/ST=State/L=City/O=Org/CN=domain.com" \
  -out server.csr

# Sign CSR with CA
openssl x509 -req -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out server.crt -days 365

# View certificate (human-readable)
openssl x509 -in cert.crt -text -noout

# View CSR
openssl req -in cert.csr -text -noout

# View private key
openssl rsa -in key.key -text -noout

# Extract specific fields
openssl x509 -in cert.crt -noout -subject
openssl x509 -in cert.crt -noout -issuer
openssl x509 -in cert.crt -noout -dates
openssl x509 -in cert.crt -noout -serial
openssl x509 -in cert.crt -noout -fingerprint

# Verify certificate chain
openssl verify -CAfile ca.crt cert.crt

# Check certificate and key match
openssl x509 -noout -modulus -in cert.crt | openssl md5
openssl rsa -noout -modulus -in key.key | openssl md5
# If MD5 hashes match, certificate and key are paired

# Convert formats
openssl x509 -in cert.pem -out cert.der -outform DER  # PEM to DER
openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM  # DER to PEM

# Test TLS connection
openssl s_client -connect domain.com:443 -CAfile ca.crt

Common Port Numbers Reference

Port Service Protocol Description
20 FTP-DATA TCP FTP data transfer
21 FTP TCP FTP control
22 SSH TCP Secure Shell
23 Telnet TCP Unencrypted remote access
25 SMTP TCP Email sending
53 DNS UDP/TCP Domain Name System
67/68 DHCP UDP Dynamic IP configuration
80 HTTP TCP Web traffic (unencrypted)
110 POP3 TCP Email retrieval
143 IMAP TCP Email retrieval
443 HTTPS TCP Web traffic (encrypted)
465 SMTPS TCP SMTP over TLS
587 SMTP TCP SMTP (submission)
993 IMAPS TCP IMAP over TLS
995 POP3S TCP POP3 over TLS
3306 MySQL TCP MySQL database
3389 RDP TCP Remote Desktop Protocol
5432 PostgreSQL TCP PostgreSQL database
6379 Redis TCP Redis cache
8080 HTTP-Alt TCP Alternative HTTP port
8443 HTTPS-Alt TCP Alternative HTTPS port

TCP State Reference

State Description Typical Duration
CLOSED No connection N/A
LISTEN Server waiting for connections Indefinite
SYN_SENT Client sent SYN, waiting for SYN-ACK Milliseconds
SYN_RCVD Server received SYN, sent SYN-ACK Milliseconds
ESTABLISHED Connection active, data transfer Seconds to hours
FIN_WAIT_1 Active close, sent FIN Milliseconds
FIN_WAIT_2 Active close, received ACK for FIN Seconds
CLOSE_WAIT Passive close, received FIN Variable (app-dependent)
CLOSING Both sides closing simultaneously Milliseconds
LAST_ACK Passive close, sent FIN Milliseconds
TIME_WAIT Final state after close 60-240 seconds

Cipher Suite Examples

Modern cipher suites (TLS 1.3):

  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256
  • TLS_AES_128_GCM_SHA256

Legacy cipher suites (TLS 1.2):

  • ECDHE-RSA-AES256-GCM-SHA384
  • ECDHE-RSA-AES128-GCM-SHA256
  • DHE-RSA-AES256-GCM-SHA384

Cipher suite components:

  • Key exchange: ECDHE, DHE, RSA
  • Authentication: RSA, ECDSA, Ed25519
  • Encryption: AES-256-GCM, AES-128-GCM, ChaCha20-Poly1305
  • Hash: SHA256, SHA384

Deliverables and Assessment

Submit a single PDF document containing all Exercise Deliverables (A-D).

Additional Resources

This lab introduced the transport layer (UDP, TCP) and applied cryptography (PKI, TLS) to secure communications. These concepts are foundational to understanding modern networked systems and security.

For Further Study:

Transport Protocols:

  • TCP congestion control algorithms (Reno, Cubic, BBR)
  • TCP fast open (TFO) for reduced latency
  • QUIC/HTTP/3 for modern applications
  • SCTP (Stream Control Transmission Protocol)
  • Multipath TCP (MPTCP) for using multiple interfaces simultaneously

Security and Cryptography:

  • TLS 1.3 improvements over TLS 1.2
  • Certificate pinning for enhanced security
  • Elliptic curve cryptography (ECDSA, Ed25519)
  • Perfect forward secrecy (PFS)
  • HSTS (HTTP Strict Transport Security)
  • Certificate Transparency logs

Network Monitoring and Debugging:

  • Wireshark for advanced packet analysis
  • tshark for command-line packet analysis
  • iptraf-ng for real-time network monitoring
  • netstat and ss advanced features
  • strace for tracing system calls related to networking

Secure Communication Tools:

  • WireGuard VPN
  • OpenVPN
  • SSH tunneling and port forwarding
  • mTLS (mutual TLS) for client authentication
  • SOCKS proxies

Network Security:

  • Firewall configuration (nftables, iptables)
  • IDS/IPS systems (Snort, Suricata)
  • Network segmentation and VLANs
  • DDoS mitigation techniques
  • Zero-trust networking

Performance Optimization:

  • TCP tuning (window size, buffer sizes)
  • Nagle's algorithm and TCP_NODELAY
  • TCP keepalive configuration
  • Connection pooling
  • Load balancing techniques

Relevant Manual Pages:

man 7 tcp          # TCP protocol overview
man 7 udp          # UDP protocol overview
man 7 ip           # IP protocol overview
man 8 ss           # Socket statistics utility
man 8 nmap         # Network exploration tool
man 8 tcpdump      # Packet capture tool
man 1 openssl      # OpenSSL command-line tool
man 1 ncat         # Ncat (netcat) tool
man 5 nftables     # nftables firewall

Online Resources: