How to programmatically create a PPTP VPN connection on macOS Sierra/High Sierra?
Asked Answered
A

1

1

Apple removed high-level PPTP support in macOS Sierra from its network configuration system. However, the PPP internals are all still there, including /usr/sbin/pppd and /etc/ppp/.

How can I programmatically initiate a PPTP VPN connection on macOS Sierra / High Sierra using what's left?

Ambiversion answered 23/5, 2018 at 22:8 Comment(0)
A
2

Answer:

This method creates a PPTP connection that doesn't send all traffic and doesn't override other DNS providers, meaning it works with multiple simultaneous VPN connections each having different DNS search domains, and closes it in an orderly fashion.

Not sending all traffic requires you to know the VPN subnet beforehand. If you don't, you must send all traffic (see below), since vanilla PPP/LCP has no means to tell the client its subnet (although theoretically the ip-up and ip-down scripts could guess it from the received IP address).

Save this perl as /usr/local/bin/pptp:

#!/usr/bin/env perl
if (@ARGV) {
    my $name = $ARGV[0];
    if (length $name && -e "/etc/ppp/peers/$name") {
        my $pid;
        $SIG{"INT"} = "IGNORE";
        die "fork: $!" unless defined ($pid = fork);
        if ($pid) { # parent
            $SIG{"INT"} = sub {
                kill HUP => $pid;
            };
            wait;
            exit;
        } else { #child
            $SIG{"INT"} = "DEFAULT";
            exec "pppd", "call", $name;
            exit;
        }
    } else {
        print "Error: PPTP name: $name\n";
    }
} else {
    opendir my $d, "/etc/ppp/peers" or die "Cannot read /etc/ppp/peers";
    while (readdir $d) {
        print "$_\n" if !($_ eq "." || $_ eq "..");
    }
    closedir $d;
}

Run it as sudo pptp AcmeOffice, where AcmeOffice is the PPP connection name, and close it with a single Control-C/SIGINT.

In /etc/ppp/peers, create the PPP connection file, in this example /etc/ppp/peers/AcmeOffice:

plugin /System/Library/SystemConfiguration/PPPController.bundle/Contents/PlugIns/PPPDialogs.ppp
plugin PPTP.ppp
noauth
# debug 
redialcount 1
redialtimer 5
idle 1800
#mru 1320
mtu 1320
receive-all
novj 0:0
ipcp-accept-local
ipcp-accept-remote
refuse-pap
refuse-chap
#refuse-chap-md5
refuse-eap
hide-password
#noaskpassword
#mppe-stateless 
mppe-128 
mppe-stateful 
require-mppe 
passive 
looplocal 
nodetach
# defaultroute
#replacedefaultroute
# ms-dns 8.8.8.8
# usepeerdns
noipdefault
# logfile /tmp/ppp.AcmeOffice.log 
ipparam AcmeOffice
remoteaddress office.acme.com
user misteracme
password acme1234

The last 4 options are connection-specific. Note the password is stored cleartext. chown root:wheel and chmod 600 is recommended. nodetach, ipcp-accept-local, ipcp-accept-remote, noipdefault are critical.

Since we're not becoming/replacing the default route, you must manually change your routing table. Add an AcmeOffice entry to the /etc/ppp/ip-up script:

#!/bin/sh
#params: interface-name tty-device speed local-IP-address remote-IP-address ipparam

PATH=$PATH:/sbin:/usr/sbin

case "$6" in
    AcmeOffice)
        route -n add -net 192.168.1.0/24 -interface "$1"
        ;;
    AcmeLab)
        route -n add -net 192.168.2.0/24 -interface "$1"
        ;;
    AcmeOffshore)
        route -n add -net 192.168.3.0/24 -interface "$1"
        ;;
    VPNBook)
        ;;
    *)
        ;;
esac

and your /etc/ppp/ip-down script:

#!/bin/sh
#params: interface-name tty-device speed local-IP-address remote-IP-address ipparam

PATH=$PATH:/sbin:/usr/sbin

case "$6" in
    AcmeOffice)
        route -n delete -net 192.168.1.0/24 -interface "$1"
        ;;
    AcmeLab)
        route -n delete -net 192.168.2.0/24 -interface "$1"
        ;;
    AcmeOffshore)
        route -n delete -net 192.168.3.0/24 -interface "$1"
        ;;
    VPNBook)
        ;;
    *)
        ;;
esac

If the VPN has a DNS search domain (i.e. somehost.office.acme.com), create a file in /etc/resolver/ named after the DNS suffix, like /etc/resolver/office.acme.com, with contents like:

nameserver 192.168.1.1
domain office.acme.com

Note that this requires knowing the destination domain & nameserver beforehand. Theoretically ip-up & ip-down could create & delete this file on demand.

To send all traffic (& if you don't know the destination subnet), uncomment #defaultroute in the PPP connection file and leave the ip-up & ip-down entries blank (e.g. the VPNBook example). To override your DNS with the VPN's, uncomment usepeerdns.

Ambiversion answered 23/5, 2018 at 22:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.