How to Route Specific Traffic Through OpenVPN Based on Destination IP Filtering


2 views

When implementing OpenVPN, there are scenarios where you might want to route only specific traffic through the VPN tunnel while allowing other traffic to use the regular network interface. This is particularly useful for:

  • DNS queries for specific intranet sites
  • Geo-restricted services
  • Security-sensitive applications

The main technical challenge lies in configuring OpenVPN to:

  1. Identify destination IPs that should use the VPN
  2. Implement proper routing rules
  3. Handle DNS resolution appropriately

Here's how to implement selective routing:

1. IP-Based Routing Configuration

Add these directives to your OpenVPN client configuration:

route-nopull
route 192.168.1.0 255.255.255.0
route 10.8.0.0 255.255.255.0

2. Advanced Routing with Scripts

Create a route-up script (e.g., /etc/openvpn/update-routes.sh):

#!/bin/bash
# Allow only specific IP ranges through VPN
ip route add 192.168.100.0/24 dev tun0
ip route add 10.10.10.0/24 dev tun0

3. DNS-Specific Implementation

For DNS-specific routing, combine with dnsmasq:

# /etc/dnsmasq.conf
server=/intranet.example.com/10.8.0.1
server=/google.com/# # Use default DNS

Here's a complete client configuration example:

client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
cipher AES-256-CBC
verb 3
route-nopull
route-up /etc/openvpn/update-routes.sh
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf
script-security 2
  • Verify routes with ip route show
  • Check DNS resolution with dig +trace intranet.example.com
  • Monitor VPN traffic with tcpdump -i tun0

For more complex scenarios, consider:

  • Implementing policy-based routing with iptables
  • Using network namespaces for isolation
  • Containerized VPN solutions for application-specific routing

The fundamental requirement is to create an OpenVPN configuration that only routes specific traffic (like DNS queries for certain intranet sites) through the VPN tunnel while letting other traffic use the regular network connection. This differs from typical VPN setups where all traffic gets routed through the tunnel.

OpenVPN provides several mechanisms to achieve selective routing:

  1. --route directives: Define specific IP ranges that should go through the VPN
  2. Policy-based routing: Using firewall marks and routing tables
  3. Client-side scripting: With --up and --route-up scripts

Here's a sample OpenVPN client configuration file that implements IP-based filtering:

client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA256
cipher AES-256-CBC
verb 3

# Only route specific networks through VPN
route-nopull
route 192.168.1.0 255.255.255.0
route 10.0.0.0 255.0.0.0

# DNS handling
dhcp-option DNS 10.0.0.53
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

For more granular control, we can combine OpenVPN with iptables rules:

# Create a new routing table
echo "200 custom" >> /etc/iproute2/rt_tables

# Mark packets destined for specific IPs (e.g., your intranet DNS)
iptables -t mangle -A OUTPUT -d 192.168.1.53 -j MARK --set-mark 1

# Configure policy routing
ip rule add fwmark 1 table custom
ip route add default via $VPN_GATEWAY dev tun0 table custom

To specifically handle DNS traffic for certain domains:

# Create a named list of IPs that should go through VPN
ipset create vpn-dest hash:ip
ipset add vpn-dest 192.168.1.53
ipset add vpn-dest 10.0.0.10

# Mark packets destined for these IPs
iptables -t mangle -A OUTPUT -m set --match-set vpn-dest dst -j MARK --set-mark 1

# Configure routing (similar to above)
ip rule add fwmark 1 table custom
ip route add default via $VPN_GATEWAY dev tun0 table custom

To ensure only specific DNS queries go through the VPN while preventing leaks:

# Block all DNS except to our designated server
iptables -A OUTPUT -p udp --dport 53 -j DROP
iptables -A OUTPUT -p tcp --dport 53 -j DROP
iptables -A OUTPUT -p udp --dport 53 -d 192.168.1.53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -d 192.168.1.53 -j ACCEPT

Use these commands to verify your setup:

# Check routing for specific IPs
ip route get 192.168.1.53

# Verify DNS resolution
dig @192.168.1.53 intranet.example.com
dig google.com

# Check iptables counters
iptables -L -v -n -t mangle

When implementing selective routing, be aware of:

  • Increased complexity in troubleshooting
  • Potential latency for non-VPN traffic if not properly configured
  • DNS caching behavior on the client system
  • MTU issues when mixing VPN and non-VPN traffic