VPN to office without routing all internet traffic

Solution 1:

The general idea is to modify the routing table so only known office subnets (address blocks) get routed through your VPN interface (e.g. ppp0) and all other subnets get routed through your normal network interface (e.g. en0). When you connect to VPN Gnome network manager adds so-called default route to the VPN interface (ppp0). You need to remove this route but add new routing entries for known office subnets.

Firstly, you need to find what private subnets are used by your office network. The easiest way is just to ask your office network administrators. If this not an option, you can figure it yourself by resolving your office host names after you connected to VPN. For example:

$ nslookup service.company.office
Server:     127.0.0.53
Address:    127.0.0.53#53

Non-authoritative answer:
Name:   service.company.office
Address: 192.168.1.22

In this case the subnet you need to route through your VPN is 192.168.1.0/24 which means all addresses from 192.168.1.0 to 192.168.1.255. Your office may have more than one subnet you need to route.

Secondly, you need to modify routing table by using ip command. Print out the table by typing ip r and look for an entry that points to VPN device:

$ ip r
default dev ppp0 proto static scope link metric 50 
default via 192.168.20.1 dev eno1 proto dhcp metric 100 
...
192.168.20.0/24 dev eno1 proto kernel scope link src 192.168.20.126 metric 100
192.168.100.1 dev ppp0 proto kernel scope link src 192.168.100.89 metric 50 

So now you know that ppp0 is your VPN device. In my example there are two default routes but ppp0 has smaller metric so all traffic goes there. Now, add a separate route to your office network:

$ ip route add 192.168.1.0/24 dev ppp0 proto static scope link

Now you just need to remove the default route to ppp0 and you are good to go:

$ ip route delete default dev ppp0

You can automate this by the following script:

#!/bin/bash

# List your office networks
networks=(
                192.168.1.0/24 
                192.168.2.0/24 
)

# Execute it with sudo
if [ $(id -u) != "0" ]; then
        echo "You must be root to execute this script. Use sudo?"
        exit -1
fi

# Check if VPN is active. You can use ipsec status command 
# if your VPN is not L2TP
tunnel=$(ip l2tp show tunnel 2>&1)
if [ -z "$tunnel" ]; then
        echo "VPN is not active."
        exit -2
fi

# Add office private network routes
for net in ${networks[*]}; do
        ret=$(ip route add $net dev ppp0 proto static scope link 2>&1)
        if [[ $ret =~ "File exists" ]]; then
                echo "routes have been already added."
                exit -3
        fi
done

# Delete default routes so Internet is routed via local ISP
ip route delete default dev ppp0