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>