Diferență între revizuiri ale paginii „OS Lab 8 - Transport and Security”
| (Nu s-a afișat o versiune intermediară efectuată de același utilizator) | |||
| Linia 656: | Linia 656: | ||
<syntaxhighlight lang="bash">sudo ip netns exec red ping -c 2 10.0.0.3</syntaxhighlight> | <syntaxhighlight lang="bash">sudo ip netns exec red ping -c 2 10.0.0.3</syntaxhighlight> | ||
| + | Not test connectivity using hostnames | ||
| + | |||
| + | <syntaxhighlight lang="bash">sudo ip netns exec red ping -c 2 blue.lab</syntaxhighlight> | ||
Test internet access from Red: | Test internet access from Red: | ||
| Linia 1.385: | Linia 1.388: | ||
'''Step 3: Start the Secure Client''' | '''Step 3: Start the Secure Client''' | ||
| − | In Terminal 3, connect from Red with TLS enabled: | + | In Terminal 3, attempt connect from Red with TLS enabled: |
| − | <syntaxhighlight lang="bash">sudo ip netns exec red ncat --ssl --ssl-verify --ssl-trustfile pki/ca.crt | + | <syntaxhighlight lang="bash">sudo ip netns exec red ncat --ssl --ssl-verify --ssl-trustfile pki/ca.crt blue.lab 8443</syntaxhighlight> |
Command breakdown: | Command breakdown: | ||
| Linia 1.393: | Linia 1.396: | ||
* <code>--ssl-verify</code>: Verify server certificate (don't accept self-signed or invalid certificates) | * <code>--ssl-verify</code>: Verify server certificate (don't accept self-signed or invalid certificates) | ||
* <code>--ssl-trustfile pki/ca.crt</code>: Trust anchor (our CA certificate) | * <code>--ssl-trustfile pki/ca.crt</code>: Trust anchor (our CA certificate) | ||
| − | * <code> | + | * <code>blue.lab 8443</code>: Connect to Blue on port 8443 |
| − | |||
| − | |||
| − | + | You should see the connection succeed. If you were to attempt to connect to 10.0.0.3 instead of blue.lab, it would FAIL because of hostname mismatch. | |
| − | |||
| − | |||
'''Step 4: Observe the TLS Handshake''' | '''Step 4: Observe the TLS Handshake''' | ||
| Linia 1.464: | Linia 1.463: | ||
<span id="understanding-what-happened"></span> | <span id="understanding-what-happened"></span> | ||
| + | |||
==== Understanding What Happened ==== | ==== Understanding What Happened ==== | ||
Versiunea curentă din 28 noiembrie 2025 14:49
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
nmapfor 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
tcpdumpto 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:
- 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).
- Data Transfer Semantics: It defines how data should be transferred: reliably with error checking and retransmission (TCP) or quickly with minimal overhead (UDP).
- 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. Includesncat, an implementation ofcatover 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 (providesip,sscommands).
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:
- CLOSED: No connection exists. This is the starting and ending state.
- LISTEN: Server is waiting for incoming connection requests. Socket is bound to a port.
- SYN_SENT: Client has sent a SYN (synchronize) packet and is waiting for a response. This occurs immediately after calling
connect(). - SYN_RCVD: Server has received a SYN and sent back SYN-ACK, waiting for the final ACK. Short-lived state.
- ESTABLISHED: Connection is fully established and data can flow in both directions. This is where most time is spent.
- FIN_WAIT_1: Active close initiated. Application called
close(), sent FIN, waiting for ACK. - FIN_WAIT_2: Received ACK for our FIN, waiting for peer's FIN.
- CLOSE_WAIT: Received FIN from peer, waiting for application to call
close(). - LAST_ACK: Sent our FIN, waiting for final ACK.
- 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":
- Client → Server: SYN
- Client sends a segment with SYN flag set and an initial sequence number (ISN)
- Client enters SYN_SENT state
- 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
- 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:
- Active Closer → Passive Closer: FIN
- Passive Closer → Active Closer: ACK (acknowledges FIN)
- Passive Closer → Active Closer: FIN (when application closes)
- 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:
- Eavesdrop: Read all plaintext data (passwords, messages, documents)
- Modify: Alter data in transit (change bank account numbers, inject malware)
- 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:
- Confidentiality: Data is encrypted so eavesdroppers see only gibberish
- Integrity: Data cannot be modified without detection
- 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:
- Negotiation: Agree on TLS version and cipher suite
- Authentication: Server presents certificate (sometimes client does too)
- Key Exchange: Establish shared encryption keys using asymmetric crypto
- 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:
- 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.
- 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)
- Private Key: Kept secret by the certificate owner. Used to prove ownership and establish secure connections.
- 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:
- Server sends its certificate
- Your browser checks: Is this certificate signed by a CA I trust?
- Browser walks the chain: End-entity ← Intermediate ← Root
- If Root CA is in browser's trust store, certificate is trusted
- Browser verifies certificate is for the correct domain (example.com)
- Browser verifies certificate hasn't expired
- 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:
- 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.
- 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.
- 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:
- Clean up any existing namespaces and bridges from previous labs
- Create a Linux bridge (
br-lab) acting as a virtual switch - Create two network namespaces (
redandblue) - Create veth pairs connecting each namespace to the bridge
- Assign IP addresses and routes
- Enable NAT for internet access
- 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 existip route get 8.8.8.8: A way to determine which interface routes to the internetgrep -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
|| trueto 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
Not test connectivity using hostnames
sudo ip netns exec red ping -c 2 blue.lab
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:
- Terminal 1 (Host): The "wiretapper" watching traffic on the bridge
- Terminal 2 (Blue): The UDP server listening for messages
- 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 ASCIIudp 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 namespacencat: 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:
- Red's
ncatprocess wrote "Hello UDP World\n" to a UDP socket - Red's kernel wrapped this in a UDP datagram (8-byte UDP header + data)
- Red's kernel wrapped the UDP datagram in an IP packet (20-byte IP header + UDP datagram)
- Red's kernel wrapped the IP packet in an Ethernet frame (14-byte Ethernet header + IP packet)
- Frame sent out veth-red interface
- Frame traversed veth pair to bridge
- Bridge forwarded frame to veth-blue-br
- Frame arrived at Blue's veth-blue interface
- Blue's kernel unwrapped layers and delivered payload to
ncatprocess listening on port 9000 - Blue's
ncatwrote payload to stdout
All of this happened in microseconds, with no connection setup or teardown.
Deliverable A
Provide the following:
- 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:
- Start a TCP server in Blue
- Use
nmapto discover the open port (simulating reconnaissance) - Capture the three-way handshake with
tcpdump - Establish a connection from Red
- Inspect the kernel's socket state table to see the ESTABLISHED connection
- 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 808010.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:
- The original LISTEN socket (still waiting for additional connections)
- 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:
- LISTEN → Waiting for incoming connections
- SYN_SENT → (We didn't see this as client because transition was fast)
- ESTABLISHED → Active connection, data transfer phase
- FIN_WAIT_1 → (Brief state during close)
- FIN_WAIT_2 → (Brief state during close)
- 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:
- ss Output: The output of
sudo ip netns exec blue ss -tnashowing both the LISTEN socket and the ESTABLISHED connection. Clearly label which line is which. - 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:
- Red wants to connect to Blue
- Attacker intercepts the connection
- Attacker establishes two connections: Attacker↔Red and Attacker↔Blue
- Attacker decrypts messages from Red, reads them, re-encrypts, and forwards to Blue
- 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:
- Certificates: Digital documents binding a public key to an identity (domain name, organization)
- Digital Signatures: Certificates are signed by a trusted Certificate Authority (CA)
- Trust Anchors: Your system comes with a pre-installed list of trusted root CAs
When Red connects to Blue:
- Blue sends its certificate
- Red checks: Is this certificate signed by a CA I trust?
- Red verifies the certificate is for the correct domain/identity
- Red verifies the certificate hasn't expired
- 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/ProvinceL=Lab: LocalityO=MyCA: OrganizationCN=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 file2048: 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:
- File Listing: Output of
ls -lh pkishowing all six files with their sizes. - Certificate Inspection: Output of
openssl x509 -in blue.crt -text -nooutshowing 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:
- TCP Handshake: Establish connection (SYN, SYN-ACK, ACK)
- 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
- 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, attempt connect from Red with TLS enabled:
sudo ip netns exec red ncat --ssl --ssl-verify --ssl-trustfile pki/ca.crt blue.lab 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)blue.lab 8443: Connect to Blue on port 8443
You should see the connection succeed. If you were to attempt to connect to 10.0.0.3 instead of blue.lab, it would FAIL because of hostname mismatch.
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):
- Red sends "ClientHello" with supported cipher suites
- Blue sends "ServerHello" with chosen cipher suite + blue.crt certificate
- Red verifies blue.crt is signed by ca.crt (from
--ssl-trustfile) - Red verifies certificate CN, validity dates, etc.
- Red generates a pre-master secret, encrypts it with Blue's public key (from blue.crt), sends it
- Both sides derive the same symmetric encryption keys from the pre-master secret
- Both sides send "Finished" messages encrypted with the new keys
- 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:
- 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)
- 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_SHA384TLS_CHACHA20_POLY1305_SHA256TLS_AES_128_GCM_SHA256
Legacy cipher suites (TLS 1.2):
ECDHE-RSA-AES256-GCM-SHA384ECDHE-RSA-AES128-GCM-SHA256DHE-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:
- TCP/IP Illustrated by W. Richard Stevens - Classic networking book
- High Performance Browser Networking - Free online book by Ilya Grigorik
- TLS 1.3 RFC 8446
- QUIC RFC 9000
- Let's Encrypt Documentation - Free CA for real certificates
- SSL Labs - Test TLS configuration of real websites
- Wireshark Documentation
- Nmap Documentation