Resolving FortiClient VPN DNS Routing Issues in OSX El Capitan for Split-Tunnel Configurations


3 views

When using FortiClient VPN with split-tunnel configuration on OSX El Capitan, we encounter a critical networking issue where DNS queries are incorrectly routed through the primary interface instead of the VPN tunnel. This breaks the fundamental security premise of VPN connections by potentially leaking internal domain queries to public DNS servers.

OSX's network stack handles DNS resolution differently than other operating systems. The scutil --dns command reveals that El Capitan maintains a global resolver configuration that doesn't properly respect interface-specific DNS settings when using VPNs.

# Current DNS configuration example
$ scutil --dns
DNS Configuration

resolver #1
  search domain[0] : example.com
  nameserver[0] : 192.168.1.1  # Local network DNS
  if_index : 4 (en0)
  flags    : Request A records

We need to modify the system's DNS resolution behavior to ensure all queries for internal domains go through the VPN interface. Here's a comprehensive solution:

#!/bin/bash
# Script to fix DNS routing for FortiClient VPN

# 1. Identify your VPN interface (usually utunX)
VPN_IF=$(ifconfig | grep 'utun' | cut -d: -f1)

# 2. Get VPN DNS servers from scutil
VPN_DNS=$(scutil --dns | grep -A 3 "resolver #8" | grep nameserver | awk '{print $3}')

# 3. Create custom resolver for VPN domains
sudo mkdir -p /etc/resolver
sudo tee /etc/resolver/internal.example.com <<EOF
nameserver ${VPN_DNS}
EOF

# 4. Flush DNS cache
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

For more complex scenarios, we can implement dnsmasq as a local DNS forwarder:

# Install dnsmasq
brew install dnsmasq

# Configuration file
cat <<EOF > /usr/local/etc/dnsmasq.conf
# Listen only on VPN interface
listen-address=127.0.0.1,${VPN_IP}
# Forward internal domains to VPN DNS
server=/internal.example.com/${VPN_DNS}
EOF

# Start service
sudo brew services start dnsmasq

After implementing these changes, verify proper DNS routing with:

dig +short internal.example.com @${VPN_DNS}
tcpdump -i ${VPN_IF} -n port 53

For persistent monitoring, consider adding these checks to your network troubleshooting toolkit.


Since OSX El Capitan (10.11), many administrators have encountered a critical issue with FortiClient VPN's split tunneling feature where DNS queries bypass the VPN tunnel interface. This creates security vulnerabilities as requests are sent through the primary network interface instead of the encrypted VPN channel.

The root cause lies in how OSX El Capitan handles network interface priority and DNS resolution. The system's mDNSResponder service doesn't properly respect the VPN interface's DNS settings when split tunneling is enabled. Here's what happens at the system level:

# Typical incorrect DNS resolution path
User Process → mDNSResponder → Primary Interface DNS → Internet
# Expected path
User Process → mDNSResponder → VPN Interface DNS → Corporate Network

We'll implement a two-pronged approach to force DNS through the VPN tunnel:

Method 1: scutil Configuration

Modify the system configuration database:

sudo scutil
> get State:/Network/Service/com.fortinet.forticlient.vpn/DNS
> d.add ServerAddresses * 10.10.10.1 10.10.10.2
> set State:/Network/Service/com.fortinet.forticlient.vpn/DNS
> quit

Method 2: pfctl Firewall Rules

Create a packet filter rule to redirect DNS traffic:

echo "
block drop quick in proto udp from any to any port = 53
pass out quick proto udp from any to 192.168.1.1 port = 53
" | sudo pfctl -ef -

Verify your configuration with these diagnostic tools:

# Check active DNS servers
scutil --dns

# Monitor DNS queries
tcpdump -i ppp0 -n port 53

# Verify routing table
netstat -rn

For persistent configuration across reboots, modify /Library/Preferences/SystemConfiguration/preferences.plist:

<dict>
    <key>DNS</key>
    <dict>
        <key>ServerAddresses</key>
        <array>
            <string>10.10.10.1</string>
        </array>
    </dict>
</dict>