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:
- Identify destination IPs that should use the VPN
- Implement proper routing rules
- 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:
- --route directives: Define specific IP ranges that should go through the VPN
- Policy-based routing: Using firewall marks and routing tables
- 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