In MacOS, how can I bypass a VPN for a specific site using its hostname?
The most simple way to create a static and persistent route to a host is creating a script addroute.sh (root:wheel 755) in /usr/local/bin. Replace the host name and the gateway though.

#!/bin/bash

sleep 10
route -n add -host $(dig +short example.com) 192.168.0.1


and load the script with a launch daemon usr.addroute.plist (root:wheel 644) in /Library/LaunchDaemon/:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
        &lt;key&gt;Label&lt;/key&gt;
        &lt;string&gt;usr.addroute&lt;/string&gt;
        &lt;key&gt;ProgramArguments&lt;/key&gt;
            &lt;array&gt;
                &lt;string&gt;/bin/sh&lt;/string&gt;
                &lt;string&gt;-c&lt;/string&gt;
                &lt;string&gt;/usr/local/bin/addroute.sh&lt;/string&gt;
            &lt;/array&gt;
        &lt;key&gt;RunAtLoad&lt;/key&gt;
        &lt;true/&gt;
        &lt;key&gt;StandardErrorPath&lt;/key&gt;
        &lt;string&gt;/tmp/usr.addroute.err&lt;/string&gt;
        &lt;key&gt;StandardOutPath&lt;/key&gt;
        &lt;string&gt;/tmp/usr.addroute.out&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;


Load it with: sudo launchctl load /Library/LaunchDaemon/usr.addroute.plist.

If everything works remove the Standard* keys/strings in the plist and the related files in /tmp.

The sleep 10 line is a sledgehammer approach - a route can only be added after a certain point in time: network has to be up for the specific interface - and may be replaced with something more elegant outlined in this answer here.



Depending on the VPN's or your default environment's DNS capabilities you may also have to add a route for a DNS server (e.g. Google's 8.8.8.8) and modify the dig command to dig @8.8.8.8 +short example.com.



If you reboot your host rarely and the remote hosts' IPs change often, use the following script (which can be improved probably):

#!/bin/bash

sleep 10

Hostname=hostname
GateWay=gateway_IP
IPHost=$(dig +short $Hostname)
RouteExist=$(netstat -nr -f inet | grep $IPHost | wc -l)
NewRoute=$(netstat -nr -f inet | grep $IPHost | awk '{print $1}')
OldHost=$(cat /usr/local/bin/addroute)

if [ $RouteExist -eq 0 ]
then
    route -n add -host $IPHost $GateWay
    RouteExist=1
    NewRoute=$(netstat -nr -f inet | grep $IPHost | awk '{print $1}')
    echo $NewRoute &gt; /usr/local/bin/addroute 
fi

if [ $IPHost != $OldHost ]

then
    route -n delete -host $OldHost $GateWay
    NewRoute=$(netstat -nr -f inet | grep $IPHost | awk '{print $1}')
    echo $NewRoute &gt; /usr/local/bin/addroute  
fi


and plist:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;usr.addroute&lt;/string&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;/bin/sh&lt;/string&gt;
        &lt;string&gt;-c&lt;/string&gt;
        &lt;string&gt;/usr/local/bin/addroute.sh&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;RunAtLoad&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;StandardErrorPath&lt;/key&gt;
    &lt;string&gt;/tmp/usr.addroute.err&lt;/string&gt;
    &lt;key&gt;StandardOutPath&lt;/key&gt;
    &lt;string&gt;/tmp/usr.addroute.out&lt;/string&gt;
    &lt;key&gt;StartInterval&lt;/key&gt;
    &lt;integer&gt;60&lt;/integer&gt;
&lt;/dict&gt;
&lt;/plist&gt;


An additional proxy file is needed:

sudo touch /usr/local/bin/addroute 


Please adjust the StartInterval (in seconds) in your plist as required and enter a proper host name and gateway IP in the shell script.

The first if routine adds a route to a remote host after booting your host and - later - a new route if the remote host's IP changes. The second if routine removes an outdated route.