Configuring OpenVPN Client on Amazon EC2 to Route All Traffic While Preserving SSH Access


2 views

When running openvpn --config client.ovpn on an EC2 instance, the immediate SSH connection drop occurs because:

  • The VPN client routes all traffic through the tunnel by default
  • EC2's SSH access relies on the original network interface
  • Security Group rules become ineffective for the new VPN tunnel

For EC2 instances in a VPC, we need a two-pronged approach:

# 1. Modify OpenVPN client configuration
client
dev tun
proto udp
remote vpn.server.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
verb 3
# Critical routing modifications:
route-nopull
route 169.254.169.254 255.255.255.255 net_gateway
script-security 2
up "/etc/openvpn/update-resolv-conf"
down "/etc/openvpn/update-resolv-conf"

Create a custom routing script (/etc/openvpn/ec2-routes.sh):

#!/bin/bash
# Preserve EC2 metadata service access
ip route add 169.254.169.254 via $(ip route show | grep default | awk '{print $3}')

# Add your SSH source IPs (replace with your actual IPs)
ip route add YOUR_SSH_IP/32 via $(ip route show | grep default | awk '{print $3}')

# Route all other traffic through VPN
ip route add 0.0.0.0/1 via $route_vpn_gateway
ip route add 128.0.0.0/1 via $route_vpn_gateway

Modify your systemd service unit (/etc/systemd/system/openvpn-client@.service):

[Unit]
Description=OpenVPN Client
After=network.target

[Service]
Type=simple
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/%i.conf --route-up /etc/openvpn/ec2-routes.sh
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target

After implementation:

  1. Start the service: sudo systemctl start openvpn-client@client
  2. Verify routes: ip route show
  3. Check tunnel IP: curl ifconfig.me
  4. Test metadata access: curl http://169.254.169.254/latest/meta-data/

For persistent connections, consider using autossh with a monitoring port:

autossh -M 20000 -N -f -L 2222:localhost:22 ec2-user@your-ec2-instance

When configuring an OpenVPN client on EC2 instances, the immediate SSH connection drop occurs because all traffic (including SSH) gets routed through the VPN tunnel by default. This creates a catch-22 situation where you need SSH access to fix the routing but lose it precisely when the VPN connects.

Before launching OpenVPN, verify your VPC security groups allow both:

  • Inbound SSH (TCP 22) from your management IP
  • Outbound UDP 1194 (or your VPN port) to the VPN server
# Sample AWS CLI command to update security groups
aws ec2 authorize-security-group-ingress \
  --group-id sg-0123456789 \
  --protocol tcp \
  --port 22 \
  --cidr 203.0.113.1/32

Modify the OpenVPN client configuration to maintain SSH access through these approaches:

# Method 1: Exclude SSH traffic in client.ovpn
route-nopull
route 203.0.113.1 255.255.255.255 net_gateway
route 10.0.0.0 255.0.0.0 vpn_gateway

# Method 2: Use routing policy scripts
script-security 2
route-up "/etc/openvpn/route-up.sh"

Create /etc/openvpn/route-up.sh:

#!/bin/bash
# Preserve SSH access to management IP
ip route add 203.0.113.1/32 via $(ip route show default | awk '{print $3}')
# Add other exceptions if needed
ip route add 169.254.169.254/32 via $(ip route show default | awk '{print $3}')

# Verify metadata service remains accessible
curl http://169.254.169.254/latest/meta-data/instance-id

For systemd-based instances, create a custom service:

[Unit]
Description=OpenVPN Client with SSH Preservation
After=network.target

[Service]
Type=forking
ExecStart=/usr/sbin/openvpn --daemon --config /etc/openvpn/client/client.ovpn --route-up /etc/openvpn/route-up.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target

When connection drops occur:

  1. Check instance console logs via AWS web console
  2. Review OpenVPN logs in /var/log/syslog
  3. Test routing tables with ip route show table all

After successful connection:

# Confirm traffic routing
curl ifconfig.me  # Should show VPN IP
dig +short myip.opendns.com @resolver1.opendns.com

# Verify SSH pathway remains
traceroute 203.0.113.1