Back to Technology

Complete Protocols Master Part 14: VPN & Tunneling Protocols

January 31, 2026 Wasil Zafar 40 min read

Master secure tunneling: IPsec for site-to-site, WireGuard for modern simplicity, OpenVPN for flexibility, and SSH tunnels for quick secure access.

Table of Contents

  1. Introduction
  2. IPsec
  3. WireGuard
  4. OpenVPN
  5. SSH Tunnels
  6. GRE Tunnels
  7. Comparison
  8. Summary

Introduction: VPN & Tunneling Concepts

VPNs create encrypted "tunnels" through untrusted networks. Whether connecting offices, enabling remote work, or bypassing censorship—the goal is secure, private communication over public infrastructure.

Series Context: This is Part 14 of 20 in the Complete Protocols Master series. VPN protocols operate across multiple OSI layers—IPsec at Layer 3, SSL VPNs at Layer 4/7.
Concepts

VPN Fundamentals

VPN Core Concepts:

1. TUNNEL
   Original packet encapsulated inside another
   Encrypted and authenticated
   Appears as single connection to outsiders

2. ENCRYPTION
   Prevents eavesdropping
   Common: AES-256-GCM, ChaCha20-Poly1305

3. AUTHENTICATION
   Proves identity of both ends
   Pre-shared keys, certificates, or passwords

4. INTEGRITY
   Detects tampering
   HMAC, Poly1305

VPN Types:
• Site-to-Site: Connect entire networks
• Remote Access: Individual users to network
• Point-to-Point: Direct server connection

Without VPN:
[You] → [ISP] → [Internet] → [Server]
       ↑ Can see everything

With VPN:
[You] → [Encrypted Tunnel] → [VPN Server] → [Server]
       ↑ ISP sees encrypted blob
Comparison

VPN Protocol Overview

ProtocolComplexitySpeedBest For
IPsecHighFastSite-to-site, enterprise
WireGuardLowFastestModern choice, mobile
OpenVPNMediumGoodFlexible, firewalls
SSH TunnelLowGoodQuick port forwarding
PPTPLowFast❌ Broken, don't use
L2TP/IPsecMediumGoodLegacy compatibility

IPsec: Internet Protocol Security

IPsec is the standard for site-to-site VPNs between offices. It operates at Layer 3, securing all IP traffic transparently. Complex but battle-tested.

Components

IPsec Architecture

IPsec Components:

1. IKE (Internet Key Exchange)
   • Phase 1: Establish secure channel for negotiation
   • Phase 2: Negotiate actual VPN parameters
   • Handles key exchange, authentication

2. ESP (Encapsulating Security Payload)
   • Encrypts packet payload
   • Provides authentication
   • Most common IPsec mode

3. AH (Authentication Header)
   • Authentication only, no encryption
   • Rarely used alone
   • Doesn't work with NAT

Modes:
• Tunnel Mode: Entire packet encrypted (site-to-site)
• Transport Mode: Only payload encrypted (host-to-host)

IKE Phases:
Phase 1 (IKE SA):
  • Authenticate peers
  • Establish secure channel
  • Negotiate algorithms

Phase 2 (IPsec SA):
  • Negotiate IPsec parameters
  • Create encryption keys
  • One per traffic pair
# IPsec packet structure (Tunnel Mode)

Original Packet:
+--------+--------+---------+
| IP Hdr | TCP/UDP | Payload |
+--------+--------+---------+

After ESP Encryption (Tunnel Mode):
+----------+----------+------------+----------+---------+-----------+
| New IP   | ESP      | Orig IP    | TCP/UDP  | Payload | ESP Auth  |
| Header   | Header   | Header     |          |         | Trailer   |
+----------+----------+------------+----------+---------+-----------+
           |←────────── ENCRYPTED ────────────→|

ESP Header:
• SPI (Security Parameter Index): Identifies the SA
• Sequence Number: Anti-replay protection

ESP Trailer:
• Padding
• Authentication Tag (ICV)
IKEv2

IKEv2 Advantages

IKEv2 vs IKEv1:

IKEv2 Improvements:
• Fewer messages (4 vs 6-9)
• Built-in NAT traversal
• MOBIKE: Seamless IP changes (mobile)
• Stronger crypto requirements
• Better DoS resistance

IKEv2 Exchange:

Initiator                 Responder
    |                         |
    |--- IKE_SA_INIT -------->|
    |<-- IKE_SA_INIT ---------|
    |                         |
    |--- IKE_AUTH ----------->|
    |<-- IKE_AUTH ------------|
    |                         |
    [IPsec tunnel established]

Just 4 messages to establish VPN!
# strongSwan IPsec configuration example

# /etc/ipsec.conf
config setup
    charondebug="ike 2, knl 2, cfg 2"

conn site-to-site
    # Authentication
    authby=secret
    
    # Local side
    left=203.0.113.1
    leftsubnet=10.1.0.0/16
    leftid=@office-a
    
    # Remote side
    right=198.51.100.1
    rightsubnet=10.2.0.0/16
    rightid=@office-b
    
    # Encryption (IKE and ESP)
    ike=aes256-sha256-modp2048!
    esp=aes256-sha256!
    
    # Key exchange
    keyexchange=ikev2
    
    # Start automatically
    auto=start

# /etc/ipsec.secrets
@office-a @office-b : PSK "shared-secret-key-here"

# Commands
ipsec start
ipsec up site-to-site
ipsec statusall

WireGuard: Modern VPN

WireGuard is the modern choice—simpler, faster, and more secure by design. Only ~4,000 lines of code vs OpenVPN's 100,000+. Now included in the Linux kernel.

Why WireGuard? Opinionated cryptography (no algorithm negotiation), minimal attack surface, excellent performance. The future of VPN.
Design

WireGuard Principles

WireGuard Design Philosophy:

1. SIMPLICITY
   • ~4,000 lines of code (auditable)
   • Fixed cryptography (no negotiation)
   • Minimal configuration

2. CRYPTOGRAPHY (non-negotiable)
   • Key exchange: Curve25519
   • Encryption: ChaCha20-Poly1305
   • Hashing: BLAKE2s
   • KDF: HKDF

3. STEALTHY
   • UDP only
   • Silent to unauthenticated packets
   • No handshake response until valid

4. ROAMING
   • Client IP can change
   • Seamless reconnection
   • Perfect for mobile

Peer Model:
• No client/server distinction
• Each peer has public/private key pair
• AllowedIPs defines routing
# WireGuard setup

# 1. Generate keys (on each peer)
wg genkey | tee privatekey | wg pubkey > publickey

# 2. Server configuration (/etc/wireguard/wg0.conf)
[Interface]
PrivateKey = SERVER_PRIVATE_KEY
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# Client 1
PublicKey = CLIENT1_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32

[Peer]
# Client 2
PublicKey = CLIENT2_PUBLIC_KEY
AllowedIPs = 10.0.0.3/32

# 3. Client configuration
[Interface]
PrivateKey = CLIENT_PRIVATE_KEY
Address = 10.0.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0  # Route all traffic through VPN
PersistentKeepalive = 25

# 4. Start WireGuard
wg-quick up wg0
wg-quick down wg0

# 5. Check status
wg show
# WireGuard config generator

def generate_wireguard_config():
    """Generate WireGuard configurations"""
    
    print("WireGuard Configuration Generator")
    print("=" * 50)
    
    # In real use, generate with: wg genkey | wg pubkey
    print("""
    # Generate keys (run on each machine):
    wg genkey > privatekey
    cat privatekey | wg pubkey > publickey
    
    # Server config (wg0.conf):
    [Interface]
    PrivateKey = 
    Address = 10.0.0.1/24
    ListenPort = 51820
    
    [Peer]
    PublicKey = 
    AllowedIPs = 10.0.0.2/32
    
    # Client config:
    [Interface]
    PrivateKey = 
    Address = 10.0.0.2/24
    
    [Peer]
    PublicKey = 
    Endpoint = server-ip:51820
    AllowedIPs = 0.0.0.0/0
    PersistentKeepalive = 25
    """)
    
    print("\nAllowedIPs meanings:")
    print("• 0.0.0.0/0: Route ALL traffic (full tunnel)")
    print("• 10.0.0.0/24: Only VPN subnet (split tunnel)")
    print("• 10.0.0.2/32: Only this specific peer")

generate_wireguard_config()

OpenVPN: Flexible SSL VPN

OpenVPN is the most flexible VPN solution. Uses SSL/TLS, works over TCP or UDP, and can traverse firewalls that block other VPNs.

Features

OpenVPN Capabilities

OpenVPN Features:

1. TRANSPORT OPTIONS
   • UDP (default, faster)
   • TCP (firewall-friendly)
   • TCP 443 (looks like HTTPS)

2. AUTHENTICATION
   • Certificates (PKI)
   • Username/password
   • Two-factor (TOTP)
   • LDAP/RADIUS integration

3. MODES
   • TUN (Layer 3, routing)
   • TAP (Layer 2, bridging)

4. FLEXIBILITY
   • Push routes to clients
   • Client-specific configs
   • Split tunneling
   • Custom scripts

When to choose OpenVPN:
• Need TCP (blocked UDP)
• Complex authentication requirements
• Legacy system compatibility
• Need TAP mode (Layer 2)
# OpenVPN server configuration

# Server: /etc/openvpn/server.conf

# Network
port 1194
proto udp
dev tun

# Certificates
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
tls-auth ta.key 0

# Network settings
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"

# Security
cipher AES-256-GCM
auth SHA256

# Performance
keepalive 10 120
comp-lzo

# Privileges
user nobody
group nogroup
persist-key
persist-tun

# Logging
status /var/log/openvpn-status.log
verb 3
# OpenVPN client configuration

# Client: client.ovpn

client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind

persist-key
persist-tun

# Certificates (inline or file reference)
ca ca.crt
cert client.crt
key client.key
tls-auth ta.key 1

cipher AES-256-GCM
auth SHA256
verb 3

# Connect
# openvpn --config client.ovpn

SSH Tunnels

SSH tunnels aren't full VPNs, but they're incredibly useful for quick secure access. Forward specific ports or create a SOCKS proxy—all through SSH.

Tunnel Types

SSH Tunnel Options

SSH Tunnel Types:

1. LOCAL PORT FORWARDING (-L)
   Forward local port to remote service
   
   ssh -L 8080:internal-server:80 user@jump-host
   
   You → localhost:8080 → [SSH] → jump-host → internal-server:80
   
   Use: Access internal web server through jump host

2. REMOTE PORT FORWARDING (-R)
   Expose local service on remote server
   
   ssh -R 8080:localhost:3000 user@server
   
   server:8080 → [SSH] → You → localhost:3000
   
   Use: Expose local dev server publicly

3. DYNAMIC PORT FORWARDING (-D)
   Create SOCKS proxy
   
   ssh -D 1080 user@server
   
   Configure browser to use SOCKS5 localhost:1080
   All traffic goes through SSH tunnel
   
   Use: Browse as if from server's location
# SSH tunnel examples

# Local port forwarding
# Access remote database through jump host
ssh -L 5432:database.internal:5432 user@jump-host
# Now: psql -h localhost -p 5432

# Access internal web app
ssh -L 8080:intranet.company.local:80 user@vpn-server
# Now: http://localhost:8080

# Remote port forwarding
# Expose local dev server
ssh -R 80:localhost:3000 user@public-server
# Now: http://public-server/ shows your local app

# SOCKS proxy (browse through remote)
ssh -D 1080 user@server
# Configure browser: SOCKS5, localhost:1080

# Keep tunnel alive in background
ssh -f -N -L 8080:target:80 user@jump
# -f: Background
# -N: No command (tunnel only)

# Multiple tunnels
ssh -L 8080:web:80 -L 3306:db:3306 -L 6379:redis:6379 user@jump
# SSH tunnel with Python (sshtunnel library)

def ssh_tunnel_example():
    """Demonstrate SSH tunnel usage"""
    
    print("SSH Tunnel with Python")
    print("=" * 50)
    
    print("""
    from sshtunnel import SSHTunnelForwarder
    import pymysql
    
    # Create tunnel to access MySQL through SSH
    with SSHTunnelForwarder(
        ('jump-host.example.com', 22),
        ssh_username='user',
        ssh_pkey='/path/to/key',
        remote_bind_address=('database.internal', 3306),
        local_bind_address=('127.0.0.1', 3306)
    ) as tunnel:
        
        # Connect to database through tunnel
        conn = pymysql.connect(
            host='127.0.0.1',
            port=tunnel.local_bind_port,
            user='dbuser',
            password='dbpass',
            database='mydb'
        )
        
        cursor = conn.cursor()
        cursor.execute('SELECT * FROM users')
        print(cursor.fetchall())
    """)
    
    print("\nInstall: pip install sshtunnel")

ssh_tunnel_example()

GRE Tunnels

GRE (Generic Routing Encapsulation) creates simple tunnels without encryption. Often combined with IPsec for secure site-to-site links.

GRE Basics

GRE Overview

GRE Characteristics:

WHAT IT DOES:
• Encapsulates any protocol in IP
• Creates virtual point-to-point link
• No encryption (add IPsec for security)

USE CASES:
• Carry non-IP protocols over IP network
• Connect routing domains
• Multicast over WAN
• Usually combined with IPsec

GRE Packet:
+----------+----------+----------+----------+
| Delivery | GRE      | Passenger| Passenger|
| Header   | Header   | Header   | Payload  |
+----------+----------+----------+----------+
(Outer IP)           (Inner packet)

GRE over IPsec:
+--------+---------+----------+----------+----------+
| IP Hdr | ESP Hdr | GRE Hdr  | Inner IP | Payload  |
+--------+---------+----------+----------+----------+
         |←────── Encrypted ──────────→|
# GRE tunnel configuration (Linux)

# Site A (192.168.1.0/24, public IP: 203.0.113.1)
ip tunnel add gre1 mode gre remote 198.51.100.1 local 203.0.113.1 ttl 255
ip link set gre1 up
ip addr add 10.0.0.1/30 dev gre1
ip route add 192.168.2.0/24 via 10.0.0.2

# Site B (192.168.2.0/24, public IP: 198.51.100.1)
ip tunnel add gre1 mode gre remote 203.0.113.1 local 198.51.100.1 ttl 255
ip link set gre1 up
ip addr add 10.0.0.2/30 dev gre1
ip route add 192.168.1.0/24 via 10.0.0.1

# Verify
ip tunnel show
ping 10.0.0.2  # Ping across tunnel

# Note: GRE alone is NOT encrypted
# Combine with IPsec for security

Protocol Comparison

Decision Guide

Choosing the Right VPN

ScenarioBest ChoiceReason
New deploymentWireGuardSimple, fast, modern
Enterprise site-to-siteIPsec IKEv2Standard, hardware support
Strict firewallOpenVPN (TCP 443)Looks like HTTPS
Quick port forwardSSH tunnelNo setup, instant
Mobile usersWireGuardSeamless roaming
Legacy integrationOpenVPNMost flexible auth
# VPN selection helper

def vpn_recommendation():
    """Recommend VPN based on requirements"""
    
    recommendations = {
        "greenfield": {
            "vpn": "WireGuard",
            "why": "Modern, simple, fastest performance",
            "config": "~15 lines of config"
        },
        "corporate_site_to_site": {
            "vpn": "IPsec IKEv2",
            "why": "Industry standard, hardware support",
            "config": "Complex, but well-documented"
        },
        "restricted_network": {
            "vpn": "OpenVPN over TCP 443",
            "why": "Mimics HTTPS, hard to block",
            "config": "Certificate management needed"
        },
        "quick_access": {
            "vpn": "SSH tunnel",
            "why": "No setup, use existing SSH",
            "config": "One command"
        },
        "mobile_workers": {
            "vpn": "WireGuard",
            "why": "Seamless IP changes, low battery",
            "config": "QR code import supported"
        }
    }
    
    print("VPN Recommendation Guide")
    print("=" * 50)
    
    for scenario, rec in recommendations.items():
        print(f"\n{scenario.replace('_', ' ').title()}:")
        print(f"  → {rec['vpn']}")
        print(f"     {rec['why']}")
        print(f"     Config: {rec['config']}")

vpn_recommendation()

Summary & Next Steps

Key Takeaways:
  • IPsec: Enterprise standard, site-to-site, complex
  • WireGuard: Modern, simple, fastest—the future
  • OpenVPN: Flexible, works through firewalls
  • SSH Tunnel: Quick port forwarding, no setup
  • GRE: Encapsulation without encryption (add IPsec)
Quiz

Test Your Knowledge

  1. IPsec IKEv2 vs IKEv1? (Fewer messages, NAT traversal)
  2. WireGuard advantage? (Simple, fast, minimal code)
  3. When OpenVPN over WireGuard? (TCP needed, complex auth)
  4. SSH -L vs -R? (Local forward vs remote forward)
  5. GRE limitation? (No encryption, needs IPsec)

Next in the Series

In Part 15: Authentication Protocols, we'll explore OAuth 2.0, SAML, Kerberos, and how identity verification works.