When examining your configuration, the core issue stems from OpenVPN's default behavior of redirecting all traffic through the VPN tunnel (0.0.0.0/1 and 128.0.0.0/1 routes). This creates a routing loop when attempting to SSH into your original public IP (104.167.102.77). Let's break down what happens:
1. SSH connection attempts reach ens33 (104.167.102.77) 2. Return traffic gets routed through tun0 (10.172.1.5) 3. Connection breaks because response can't route back properly
We'll modify the OpenVPN configuration to exclude your SSH traffic from the VPN tunnel while maintaining other traffic routing. Add these directives to your config.ovpn:
route-nopull route 104.167.102.77 255.255.255.255 net_gateway route 0.0.0.0 128.0.0.0 vpn_gateway route 128.0.0.0 128.0.0.0 vpn_gateway
To ensure SSH traffic remains on the physical interface, we'll add iptables rules:
# Preserve existing connections iptables -A INPUT -i ens33 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Allow new SSH connections on physical interface iptables -A INPUT -i ens33 -p tcp --dport 22 -j ACCEPT # Block SSH attempts coming through VPN iptables -A INPUT -i tun0 -p tcp --dport 22 -j DROP
For CentOS 7, make these changes permanent:
# Save iptables rules service iptables save systemctl enable iptables # Modify OpenVPN service to wait for network systemctl edit openvpn@client.service [Service] ExecStartPre=/bin/sleep 5
After implementation, verify with these commands:
# Check routing table ip route show table all # Test SSH connectivity while VPN is active ssh -v user@104.167.102.77 # Verify outbound traffic routing curl --interface tun0 ifconfig.co curl --interface ens33 ifconfig.co
If you encounter problems:
# Check for MTU mismatches ping -M do -s 1500 104.167.102.1 # Examine OpenVPN logs journalctl -u openvpn@client -f # Test raw connectivity nc -zv 104.167.102.77 22
For more advanced setups, consider policy routing:
# Create custom routing table echo "200 vpnbypass" >> /etc/iproute2/rt_tables # Add rule for SSH traffic ip rule add from 104.167.102.77 table vpnbypass # Set default route in custom table ip route add default via 104.167.102.1 dev ens33 table vpnbypass
When you activate OpenVPN with default configurations on a Linux VPS, it typically modifies your routing table to send ALL traffic through the VPN tunnel. This creates our core problem:
# Before OpenVPN $ ip route default via 104.167.102.1 dev ens33 # After OpenVPN $ ip route 0.0.0.0/1 via 10.172.1.5 dev tun0 default via 104.167.102.1 dev ens33 128.0.0.0/1 via 10.172.1.5 dev tun0
We'll use Linux's advanced routing capabilities to create separate routing tables:
# Create custom routing table (ID 100) echo "100 vpnbypass" >> /etc/iproute2/rt_tables # Add rules to use this table for SSH traffic ip rule add from 104.167.102.77 table vpnbypass ip rule add fwmark 1 table vpnbypass # Populate the custom table ip route add default via 104.167.102.1 dev ens33 table vpnbypass ip route add 104.167.102.0/24 dev ens33 src 104.167.102.77 table vpnbypass
Modify your PIA OpenVPN configuration (config.ovpn):
client dev tun proto udp remote nl.privateinternetaccess.com 1194 resolv-retry infinite nobind persist-key persist-tun ca ca.crt tls-client remote-cert-tls server auth-user-pass comp-lzo verb 1 reneg-sec 0 crl-verify crl.pem # Add these critical directives: route-nopull route 0.0.0.0 0.0.0.0 vpn_gateway script-security 2 up /etc/openvpn/update-resolv-conf down /etc/openvpn/update-resolv-conf
Create these iptables rules to mark SSH traffic:
iptables -t mangle -A OUTPUT -p tcp --sport 22 -j MARK --set-mark 1 iptables -t mangle -A OUTPUT -p tcp --dport 22 -j MARK --set-mark 1
For CentOS 7, create /etc/rc.local to make rules persistent:
#!/bin/bash ip rule add from 104.167.102.77 table vpnbypass ip rule add fwmark 1 table vpnbypass ip route add default via 104.167.102.1 dev ens33 table vpnbypass iptables -t mangle -A OUTPUT -p tcp --sport 22 -j MARK --set-mark 1 exit 0
Then make it executable:
chmod +x /etc/rc.local systemctl enable rc-local
After implementation:
# Confirm SSH remains accessible $ telnet 104.167.102.77 22 Trying 104.167.102.77... Connected to 104.167.102.77. # Verify internet traffic uses VPN $ curl ifconfig.me 109.201.154.177 # Should show PIA exit IP # Check routing tables $ ip route show table vpnbypass default via 104.167.102.1 dev ens33