A comprehensive simulation environment for understanding QUIC connection migration. This project demonstrates how QUIC maintains connections even when network paths change (IP addresses, ports, or interfaces).
Unlike TCP which identifies connections by the 4-tuple (source IP, source port, destination IP, destination port), QUIC uses Connection IDs. This allows connections to survive network changes such as:
- WiFi to cellular handoffs
- NAT rebinding (port changes)
- IP address changes
- Network interface switches
Short answer: No, Docker is not required.
You can run this simulation directly on your local machine. However, Docker can be useful if you want to:
- Simulate network conditions (latency, packet loss)
- Test with network namespaces (true IP isolation)
- Avoid dependency conflicts with your system Python
This is the simplest approach and perfect for understanding QUIC migration:
# Install dependencies
pip install -r requirements.txt
# Generate certificates
python generate_certs.py
# Terminal 1: Start server
python quic_server.py
# Terminal 2: Run client
python quic_client.py
# Or explore interactively
python migration_demo.pyIf you want network isolation or advanced testing:
# Build image
docker build -t quic-migration .
# Run server
docker run -p 4433:4433/udp quic-migration python quic_server.py
# Run client (in another terminal)
docker run --network host quic-migration python quic_client.pyquic/
├── requirements.txt # Python dependencies
├── generate_certs.py # Generate self-signed certificates
├── quic_server.py # QUIC server with migration tracking
├── quic_client.py # QUIC client with migration simulation
├── migration_demo.py # Interactive learning tool
├── README.md # This file
└── Dockerfile # Optional Docker setup
pip install -r requirements.txtThe main dependency is aioquic, a Python implementation of QUIC.
QUIC requires TLS, so we need certificates:
python generate_certs.pyThis creates cert.pem and key.pem for testing.
Start with the interactive demo to understand concepts:
python migration_demo.pyThis provides:
- Explanations of QUIC migration concepts
- Step-by-step scenarios
- Benefits and use cases
Terminal 1 - Start the server:
python quic_server.pyYou should see:
🚀 Starting QUIC server on 127.0.0.1:4433
📋 Server supports connection migration
Terminal 2 - Run the client:
python quic_client.pyWatch both terminals to see:
- Connection establishment
- Data exchange
- Simulated migration events
- Migration tracking
Key components:
- MigrationTracker (line 37): Tracks and logs migration events
- QuicServerProtocol (line 61): Handles QUIC events and detects migrations
- Migration Detection (line 85): Compares client addresses to detect changes
The server automatically:
- Detects when client address/port changes
- Validates new paths
- Continues serving without interruption
- Tracks migration count
Key components:
- QuicClientProtocol (line 34): Handles client-side QUIC events
- simulate_migration() (line 66): Simulates different migration types
- send_message() (line 51): Sends data and waits for response
The client can simulate:
- NAT_REBINDING: Source port changes
- NETWORK_SWITCH: Interface changes (WiFi → Cellular)
- IP_CHANGE: Full IP address change
An educational tool that explains:
- QUIC migration concepts
- Real-world scenarios
- Step-by-step migration processes
- Benefits and use cases
What happens:
- Client behind NAT, source port changes
- Server receives packets from same IP but different port
QUIC handles it:
- Connection ID remains same
- Server validates new path
- Connection continues seamlessly
What happens:
- Mobile device switches from WiFi to cellular
- Completely new IP address
QUIC handles it:
- Connection ID identifies the connection
- Path validation with CHALLENGE/RESPONSE
- Zero application-level interruption
What happens:
- DHCP lease renewal gives new IP
- Or connection reset by ISP
QUIC handles it:
- Connection state preserved
- Automatic path validation
- Transparent to application
What happens:
- Server advertises better route
- Client can migrate to preferred address
QUIC handles it:
- Server sends PREFERRED_ADDRESS
- Client validates and migrates
- Better routing or load balancing
- Unlike TCP's 4-tuple, QUIC uses Connection IDs
- Allows network path to change
- Can be rotated for privacy
- PATH_CHALLENGE frame to new address
- PATH_RESPONSE proves ownership
- Prevents address spoofing
- After initial validation, subsequent migrations are fast
- No handshake overhead
- Minimal latency impact
- Client can migrate (most common)
- Server can suggest preferred address
- Both validate new paths
- Seamless Mobility: Switch networks without disconnection
- Better User Experience: No interruptions in video, downloads, or games
- Reduced Latency: No connection re-establishment overhead
- Privacy: Rotate Connection IDs to prevent tracking
- Resilience: Survive NAT rebindings and network changes
- Mobile Apps: Maintain connections when switching WiFi/cellular
- Video Conferencing: Continue calls during network transitions
- Downloads: Large downloads survive network changes
- Gaming: Uninterrupted gameplay on mobile
- IoT Devices: Resilient connections for embedded systems
If you see "Address already in use":
# Find process using port 4433
lsof -i :4433
# Kill it or change port in server/client codeIf you see certificate errors:
# Regenerate certificates
python generate_certs.pyIf you see import errors:
# Ensure aioquic is installed
pip install --upgrade aioquicThe current simulation uses localhost loopback, which limits true network path changes. To see real migrations:
-
Use multiple network interfaces:
- Bind client to WiFi interface
- Switch to ethernet interface
- Observe migration in logs
-
Use network namespaces (Linux):
# Create namespace with different routing sudo ip netns add test
-
Use Docker with custom networks:
- More realistic network simulation
- Control network conditions
To properly test migration, you need actual network path changes:
# Bind to specific interface
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('192.168.1.100', 0)) # Bind to WiFi IP
# Then switch to cellular IPUse tc (traffic control) on Linux:
# Add 10% packet loss
sudo tc qdisc add dev eth0 root netem loss 10%
# Add latency
sudo tc qdisc add dev eth0 root netem delay 100msWhile not in base spec, you can explore multi-path extensions:
- Use multiple paths simultaneously
- Aggregate bandwidth
- Failover redundancy
- QUIC RFC 9000 - Official QUIC spec
- Connection Migration (RFC 9000 Section 9)
- aioquic Documentation
- Cloudflare QUIC Blog
- Run the interactive demo:
python migration_demo.py - Study the scenarios: Understand each migration type
- Run live simulation: See migrations in action
- Modify the code: Add your own scenarios
- Experiment: Try different network conditions
This is an educational project for learning QUIC connection migration.