-
-
Save p120ph37/7ac3f857886069e2bc4f to your computer and use it in GitHub Desktop.
#!/bin/sh | |
#################################################### | |
## ## | |
## PPP VPN split-network/split-DNS script for OSX ## | |
## by Aaron Meriwether ## | |
## ## | |
## installation: ## | |
## sudo cp thisfile /etc/ppp/ip-up ## | |
## sudo chmod 755 /etc/ppp/ip-up ## | |
## ## | |
#################################################### | |
################## | |
## begin config... | |
# Define per-VPN-server settings here... | |
SERVERS[0]="vpn.example.org" # must match the server name set in Network Preferences. | |
NETWORKS[0]="192.168.2.0/24 192.168.3.0/24" # only networks besides the VPN LAN itself! | |
DOMAINS[0]="example.org" # domains which should use the VPN's DNS resolver when connected. | |
SERVERS[1]="vpn.mit.edu" | |
NETWORKS[1]="" # an empty network list is acceptable if you are only interested in the DNS aspects | |
DOMAINS[1]="staff.mit.edu athena.mit.edu" | |
SERVERS[2]="vpn.rogers.com" | |
NETWORKS[2]="172.16.7.128/25 205.150.67.0/24" | |
DOMAINS[2]="" # likewise, an empty DNS list is acceptable if you are only interested in the network aspects | |
# set to /dev/null if you object to debugging output. | |
DEBUGFILE=/tmp/ip-up-debug.txt | |
## end config... | |
################# | |
# When the ppp link comes up, this script is called with the following | |
# parameters | |
# $1 the interface name used by pppd (e.g. ppp3) | |
# $2 the tty device name | |
# $3 the tty device speed | |
# $4 the local IP address for the interface | |
# $5 the remote IP address | |
# $6 the parameter specified by the 'ipparam' option to pppd | |
# (when used with a VPN configured via Network Preferences, | |
# $6 seems to contain the IP address of the gateway over | |
# which the VPN traffic passes. This might be useful in | |
# ip-up scripts which need to avoid breaking the route | |
# used by pppd itself.) | |
PATH=/usr/bin:/bin:/usr/sbin:/sbin | |
# Generic array operation. | |
# e.g.: indexOf "something" "${myArray[@]}" | |
# note the double quotes around the array and the use of [@] not [*] | |
indexOf() { | |
local s="$1"; shift; local a=( "$@" ) i | |
for (( i = 0; i < ${#@}; i++ )); do | |
if [ "${a[$i]}" == "$s" ]; then echo $i; return; fi | |
done | |
} | |
# Given an interface name, find the corresponding scutil service key. | |
if2service() { | |
local i | |
for i in $(echo "list State:/Network/Service/[^/]+/PPP" | scutil | cut -d/ -f4); do | |
if [ "$(echo show State:/Network/Service/$i/PPP | scutil | grep InterfaceName | cut -d' ' -f5)" == "$1" ]; then echo $i; return; fi | |
done | |
} | |
# Given a network service key (specifically a PPP service), get the server name (as set in Network Preferences). | |
getPppServerName() { | |
echo show Setup:/Network/Service/$1/PPP | scutil | grep CommRemoteAddress | cut -d' ' -f5 | |
} | |
echo "$(date +'%Y-%m-%d %T %Z') $0 1=$1 2=$2 3=$3 4=$4 5=$5 6=$6" >> $DEBUGFILE | |
SERVICE="$(if2service $1)" | |
echo "Service: $SERVICE" >> $DEBUGFILE | |
SERVER="$(getPppServerName $SERVICE)" | |
echo "Server Name: $SERVER" >> $DEBUGFILE | |
i=$(indexOf "$SERVER" "${SERVERS[@]}") | |
if [ -z "$i" ]; then | |
echo "No special configuration found for this VPN server." >> $DEBUGFILE | |
exit | |
fi | |
if [ -n "$(echo show State:/Network/Service/$SERVICE/IPv4 | scutil | grep OverridePrimary)" ]; then | |
echo "Clearing the 'Send all traffic over VPN connection' flag" >> $DEBUGFILE | |
scutil <<-END | |
get State:/Network/Service/$SERVICE/IPv4 | |
d.remove OverridePrimary | |
set State:/Network/Service/$SERVICE/IPv4 | |
END | |
fi | |
if [ -n "${NETWORKS[$i]}" ]; then | |
for n in ${NETWORKS[$i]}; do | |
echo "Adding route for network $n" >> $DEBUGFILE | |
route -n add -net $n $5 | |
done | |
fi | |
if [ -n "${DOMAINS[$i]}" ]; then | |
echo "Limiting DNS over the VPN to these domains: ${DOMAINS[$i]}" | |
scutil <<-END | |
get State:/Network/Service/$SERVICE/DNS | |
d.add SupplementalMatchDomains * ${DOMAINS[$i]} | |
set State:/Network/Service/$SERVICE/DNS | |
END | |
fi |
Nice script, only I have problem running it under El Capitan getting the split-dns to work. I can see the SupplementalMatchDomains
being set initially after the ipsec tunnel is up. But after a few seconds the PPP somehow seems to reset this change. From /var/log/ppp.log
:
Tue May 17 13:39:56 2016 : Received acsp/dhcp dictionaries
Tue May 17 13:39:56 2016 : Committed PPP store on install command
Have you found any way to work around this?
I have the same problem like @aequitas: its working directly after the ppp connection comes up, after 2 seconds the chage is reverted by the system. Any solution?
just as a workaround I added a "sleep 20" between line 103 and 104. With this its working. I think the problem is Mac OS related:
Fri Oct 13 12:18:00 2017 : l2tp_wait_input: Address added. previous interface setting (name: en4, address: 10.18.89.2), current interface setting (name: ppp0, family: PPP, address: 192.168.1.1, subnet: 255.255.255.0, destination: 10.255.255.0).
Fri Oct 13 12:18:00 2017 : Committed PPP store on install command
Fri Oct 13 12:18:00 2017 : L2TP port-mapping for en4, interfaceIndex: 0, Protocol: None, Private Port: 0, Public Address: 0, Public Port: 0, TTL: 0.
Fri Oct 13 12:18:00 2017 : L2TP port-mapping for en4 inconsistent. is Connected: 1, Previous interface: 6, Current interface 0
Fri Oct 13 12:18:03 2017 : sent [IP data <src addr 192.168.1.1> <dst addr 255.255.255.255> <BOOTP Request> <type INFORM> <client id 0x08000000010000> <parameters = 0x6 0x2c 0x2b 0x1 0xf9 0xf>]
Fri Oct 13 12:18:09 2017 : sent [IP data <src addr 192.168.1.1> <dst addr 255.255.255.255> <BOOTP Request> <type INFORM> <client id 0x08000000010000> <parameters = 0x6 0x2c 0x2b 0x1 0xf9 0xf>]
Fri Oct 13 12:18:12 2017 : sent [IP data <src addr 192.168.1.1> <dst addr 255.255.255.255> <BOOTP Request> <type INFORM> <client id 0x08000000010000> <parameters = 0x6 0x2c 0x2b 0x1 0xf9 0xf>]
Fri Oct 13 12:18:15 2017 : No DHCP server replied
It seems that the Mac OS links the ppp interface to the en4 interface with some inconsistencies, and that is generating a new DHCP BOOTP request.
In the end it resets the changes of the script here. So my workaround is just a delayed run of the setting by the script.
This is awesome stuff. Thank you for sharing! 😄