如何以编程方式在 macOS Sierra/High Sierra 上创建 PPTP VPN 连接?

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

Apple 从其网络配置系统中删除了 macOS Sierra 中的高级 PPTP 支持。但是,PPP 内部结构仍然存在,包括 /usr/sbin/pppd/etc/ppp/

如何使用剩下的内容以编程方式在 macOS Sierra / High Sierra 上启动 PPTP VPN 连接?

答案:

此方法创建的 PPTP 连接不会发送所有流量并且不会覆盖其他 DNS 提供商,这意味着它有效具有多个同时的 VPN 连接,每个连接都有不同的 DNS 搜索域,并以有序的方式关闭它。

不发送所有流量需要您事先知道 VPN 子网。如果你不这样做,你必须发送所有流量(见下文),因为 vanilla PPP/LCP 没有办法告诉客户端它的子网(尽管理论上 ip-upip-down 脚本可以猜测它来自收到的 IP 地址。

将此 perl 另存为 /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;
}

运行 为 sudo pptp AcmeOffice,其中 AcmeOffice 是 PPP 连接名称,并用单个 Control-C/SIGINT.

关闭它

/etc/ppp/peers中创建PPP连接文件,在本例中/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

最后 4 个选项是特定于连接的。请注意,密码以明文形式存储。建议使用 chown root:wheelchmod 600nodetachipcp-accept-localipcp-accept-remotenoipdefault 很关键。

由于我们不是 becoming/replacing 默认路由,您必须手动更改路由 table。将 AcmeOffice 条目添加到 /etc/ppp/ip-up 脚本:

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

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

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

和您的 /etc/ppp/ip-down 脚本:

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

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

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

如果 VPN 具有 DNS 搜索域(即 somehost.office.acme.com),请在 /etc/resolver/ 中创建一个以 DNS 后缀命名的文件,如 /etc/resolver/office.acme.com,内容如下:

nameserver 192.168.1.1
domain office.acme.com

请注意,这需要事先知道目标域和名称服务器。理论上 ip-up & ip-down 可以按需创建和删除此文件。

要发送所有流量(如果您不知道目标子网),请在 PPP 连接文件中取消注释 #defaultroute,并将 ip-upip-down 条目留空(例如 VPNBook 示例)。要用 VPN 覆盖您的 DNS,请取消注释 usepeerdns