A VPN (Virtual Private Network) creates a secure, encrypted tunnel through an untrusted network. It's essential for remote work, connecting datacenters, and protecting sensitive traffic. Understanding VPN protocols and tunneling is critical for modern infrastructure.
What is a VPN?
VPN (Virtual Private Network) creates a private network over a public network:
User in Coffee Shop
↓ (encrypted tunnel through internet)
[VPN Tunnel]
↓
Private Network (company, datacenter)
↑
Now appears as local user
Why VPNs matter:
- Security — Encrypt traffic from snooping
- Privacy — Hide real IP address
- Access Control — Connect remote sites securely
- Compliance — Meet data protection requirements
Types of VPNs
Client-to-Site (Remote Access):
Remote User's Device
↓
[Client VPN software]
↓ (encrypted)
[VPN Server]
↓
Internal Network
Result: Remote user connects to company network
Site-to-Site:
Office A Network
↓
[VPN Gateway]
↓ (encrypted through internet)
[VPN Gateway]
↓
Office B Network
Result: Two networks securely connected
VPN Tunneling Protocols
| Protocol | Type | Speed | Security | Setup | DevOps Use |
|---|---|---|---|---|---|
| OpenVPN | Software | Moderate | Excellent | Complex | Remote access |
| WireGuard | Kernel | Very Fast | Modern | Simple | VPN, site-to-site |
| IPSec | Kernel | Very Fast | Excellent | Complex | Site-to-site, datacenters |
| SSH Tunnel | Software | Moderate | Good | Very Simple | Quick tunneling |
| L2TP/IPSec | Kernel | Fast | Good | Moderate | Legacy remote access |
OpenVPN
Why OpenVPN:
- Open source, widely trusted
- Works over TCP or UDP
- Cross-platform (Linux, Windows, Mac, mobile)
- Very flexible configuration
- Popular with VPN providers
OpenVPN Architecture:
Client Server
↓ ↓
[OpenVPN Client] ←→ [OpenVPN Server]
↓ (encrypted) ↓
Internet connection Listens on port 1194
↑ ↑
Install OpenVPN:
# Ubuntu/Debian
sudo apt-get install openvpn openvpn-easy-rsa
# Generate certificates (Public Key Infrastructure)
make-cadir ~/openvpn-ca
cd ~/openvpn-ca
./easyrsa init-pki
./easyrsa build-ca
./easyrsa gen-req server nopass
./easyrsa sign-req server serverServer Configuration (/etc/openvpn/server.conf):
# Port and protocol
port 1194
proto udp
# Network settings
dev tun
server 10.8.0.0 255.255.255.0
# Certificates
ca ca.crt
cert server.crt
key server.key
dh dh.pem
# Encryption
cipher AES-256-CBC
auth SHA256
# Keep connection alive
keepalive 10 120
# Push settings to clients
push "route 192.168.1.0 255.255.255.0"
push "dhcp-option DNS 8.8.8.8"
# Enable port forwarding
port-share 0.0.0.0 443
Client Configuration (client.ovpn):
client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
ca ca.crt
cert client.crt
key client.key
cipher AES-256-CBC
auth SHA256
verb 3
Connect to VPN:
sudo openvpn --config client.ovpnWireGuard
Why WireGuard:
- Extremely simple (4,000 lines of code vs 100,000+ for OpenVPN)
- Lightning fast (kernel-space)
- Modern cryptography defaults
- Perfect for infrastructure
- Growing adoption
WireGuard Architecture:
Peer A →→ Encrypted Tunnel →→ Peer B
(WireGuard)
Install WireGuard:
# Ubuntu/Debian
sudo apt-get install wireguard wireguard-tools
# Generate keys
wg genkey | tee private.key | wg pubkey > public.keyServer Configuration (/etc/wireguard/wg0.conf):
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server-private-key>
# Client 1
[Peer]
PublicKey = <client1-public-key>
AllowedIPs = 10.0.0.2/32
# Client 2
[Peer]
PublicKey = <client2-public-key>
AllowedIPs = 10.0.0.3/32
Client Configuration (/etc/wireguard/wg0.conf):
[Interface]
Address = 10.0.0.2/24
PrivateKey = <client-private-key>
[Peer]
PublicKey = <server-public-key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Start WireGuard:
sudo ip link add dev wg0 type wireguard
sudo ip addr add 10.0.0.1/24 dev wg0
sudo ip link set wg0 up
sudo wg set wg0 listen-port 51820 private-key <(wg genkey)
# Or use wg-quick
sudo wg-quick up wg0IPSec (IP Security)
Why IPSec:
- Industry standard for site-to-site
- Works at network layer (all protocols)
- Very secure
- Native to most enterprise equipment
- Datacenter-to-datacenter standard
IPSec Components:
IKE (Internet Key Exchange)
↓ Negotiates encryption parameters
↓
AH (Authentication Header)
↓ Signs data integrity
↓
ESP (Encapsulating Security Payload)
↓ Encrypts data
↓
Socket layer - Protected traffic
IPSec Modes:
- Transport Mode: Encrypt payload only (host-to-host)
- Tunnel Mode: Encrypt entire IP packet (site-to-site)
Install IPSec (strongSwan):
sudo apt-get install strongswan strongswan-swanctl
# Generate keys
ipsec pki --gen --type rsa --size 4096 --outform pem > private.pemServer IPSec Configuration (/etc/ipsec.conf):
config setup
charondebug = "ike 2, knl 2"
conn office-to-datacenter
left = 203.0.113.1
leftsubnet = 192.168.1.0/24
right = 198.51.100.1
rightsubnet = 10.0.0.0/24
ike = aes256-sha256-modp2048!
esp = aes256-sha256!
keyingtries = 0
ikelifetime = 10h
lifetime = 1h
dpd_action = restart
auto = start
authby = secret
SSH Tunnels
Why SSH Tunnels:
- Simplest VPN-like solution
- SSH already installed everywhere
- Perfect for quick tunneling
- No additional software needed
- Great for emergency access
Local Port Forwarding (access remote service):
# Forward local port 8080 to remote server's MySQL
ssh -L 8080:database.example.com:3306 [email protected]
# Now: localhost:8080 → database.example.com:3306 (encrypted)
mysql -h localhost -P 8080Remote Port Forwarding (expose local service):
# Forward remote port 9000 to local service
ssh -R 9000:localhost:8080 [email protected]
# Now: server.example.com:9000 → localhost:8080Dynamic Port Forwarding (SOCKS proxy):
# Create SOCKS proxy
ssh -D 1080 [email protected]
# Configure app to use SOCKS proxy on localhost:1080
# All traffic goes through SSH tunnelPersistent SSH Tunnel (systemd):
[Unit]
Description=SSH Tunnel to Database
After=network.target
[Service]
Type=simple
User=app
ExecStart=/usr/bin/ssh -N -L 5432:db.internal:5432 [email protected]
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.targetVPN in Kubernetes
VPN into Kubernetes Network:
# Access pods from local machine
kubectl port-forward pod/my-pod 8080:8080
# Access service
kubectl port-forward svc/my-service 3306:3306
# Now any tool can connect:
mysql -h localhost -P 3306Site-to-Site VPN for Multi-Cloud:
apiVersion: v1
kind: ConfigMap
metadata:
name: wireguard-config
data:
wg0.conf: |
[Interface]
Address = 10.100.0.1/24
ListenPort = 51820
PrivateKey = {key}
[Peer]
PublicKey = <other-datacenter-key>
Endpoint = 198.51.100.1:51820
AllowedIPs = 10.200.0.0/24Deploy WireGuard as sidecar or DaemonSet for cluster-to-cluster connectivity.
Common VPN Issues
"Can't connect to VPN"
1. Check VPN server running
sudo systemctl status openvpn@server
2. Verify client certificate is valid
openssl x509 -in client.crt -text -noout
3. Check firewall allows port
sudo ufw status | grep 1194
sudo iptables -L | grep 1194
4. Test connectivity
telnet vpn.example.com 1194"VPN connects but no internet"
1. Check routing table
route -n
2. Verify gateway is set
ip route show
3. Check NAT/masquerading
sudo iptables -L -n -t nat | grep MASQUERADE
4. Enable IP forwarding on server
echo "1" | sudo tee /proc/sys/net/ipv4/ip_forward
# Make permanent
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p"VPN is slow"
1. Check packet loss
ping -c 100 vpn.example.com | grep "% packet loss"
2. Measure throughput
iperf3 -c vpn.example.com
3. Check encryption overhead
Check CPU usage: top
4. Switch to faster protocol
WireGuard faster than OpenVPN
UDP better than TCP"Can't reach specific hosts through VPN"
1. Verify routing on VPN client
route -n | grep -E "VPN|10\\."
2. Check firewall rules on destination network
Can destination ping VPN server?
3. Verify split tunneling not blocking traffic
Should route through VPN, not local
4. Test with traceroute
traceroute destination-hostVPN Best Practices
1. Use Modern Protocols
✓ WireGuard for new deployments
✓ OpenVPN for flexibility/compatibility
✗ L2TP/IPSec (legacy)
✗ PPTP (insecure, deprecated)
2. Strong Encryption
✓ AES-256 for data
✓ SHA-256 for authentication
✓ 2048-bit DH or elliptic curve
✗ Weaker ciphers
3. Certificate Rotation
# Regenerate certificates every 1-2 years
/etc/openvpn/easy-rsa/easyrsa gen-req server nopass
/etc/openvpn/easy-rsa/easyrsa sign-req server server
# Restart OpenVPN
sudo systemctl restart openvpn@server4. Monitor VPN Usage
# OpenVPN: check connection logs
tail -f /var/log/openvpn/status.log
# WireGuard: show peers
sudo wg show
# Monitor bandwidth
nethogs5. Network Isolation
✓ Place VPN servers in DMZ
✓ Firewall internal networks behind VPN server
✓ Don't expose internal services directly
✗ Don't put VPN server on same network as databases
6. Kill Switch
# If VPN drops, block internet
sudo iptables -A INPUT -i eth0 -j DROP
sudo iptables -A OUTPUT -o eth0 -j DROP
# Allow only VPN
sudo iptables -A INPUT -i tun0 -j ACCEPT
sudo iptables -A OUTPUT -o tun0 -j ACCEPTDevOps VPN Patterns
Bastion Host Access:
Local Dev Machine
↓
SSH to Bastion (VPN-like)
↓
SSH to Internal Servers
# Often combined with VPN for extra security
Multi-Datacenter Replication:
DC1 Database
↓ (VPN site-to-site)
DC2 Database
Replication encrypted end-to-end
Encrypted CI/CD Pipelines:
CI/CD Runner
↓ (VPN tunnel)
Private Docker Registry
Private Package Repository
Private Kubernetes Cluster
All communication encrypted
Key Concepts
- VPN = Virtual Private Network for secure tunneling
- Client-to-Site = Remote user accessing company network
- Site-to-Site = Two networks securely connected
- OpenVPN = Flexible, popular tunneling protocol
- WireGuard = Modern, fast, simple protocol
- IPSec = Industry standard, layer 3 encryption
- SSH Tunnel = Simplest tunnel option
- Encryption = Protects data in transit
- Authentication = Verifies packet source
- Always use VPN for sensitive traffic and remote access