macOS 上的 OpenConnect:软件包、发布压缩包还是 git 克隆
Homebrew 安装的是二进制程序和网络脚本;源码树在你生成并运行它们之前两者都没有。先弄清你的连接用的是哪一种。
在 Mac 上获得 OpenConnect 客户端有三条路,它们在磁盘上留下的东西各不相同。Homebrew 配方会安装编译好的二进制程序和配置路由与 DNS 的网络脚本。发布压缩包给你带生成好的构建系统的源码。git 检出给你没有构建系统的源码。选错路,正是人们照着教程做了几分钟就遇到缺少 configure 的原因。
同一个名字下的两种不同机制
软件包这条路只有一条命令,对于工作是连接而不是开发的人来说,它就是正确的默认选择。
brew install openconnect
装了什么比命令本身更重要。你得到的不仅是客户端二进制文件,还有客户端调用来配置接口、路由和解析器的 vpnc-script。两者成对工作:二进制程序结束 TLS 会话,把产生的接口交给脚本,而脚本正是知道这个操作系统希望如何改动其网络的那部分。
这种分工解释了一整类令人困惑的报告。客户端连上了、报告成功,却把流量送错了路,通常不是隧道的问题而是脚本的问题;重装配方之所以有用,只是因为脚本也跟着重装了。在围绕这个配方做计划之前,先确认它目前对 macOS 与 CPU 架构的支持;一台把 shell 跑得很好的 Mac,也可能还没有为它构建的当前软件包。
源码这条路实际做了什么
发布压缩包自带生成好的构建系统,所以熟悉的 ./configure 一开始就存在。git 检出则没有,因为生成的文件是构建产物,而不是项目存档的东西。这就是为什么 ./autogen.sh 出现在针对检出的说明里,却不出现在发布压缩包里。
./autogen.sh
./configure
make
make install
每一行都做一件具体的事,知道哪一行失败能省下大量猜测。autogen 这一步运行 autotools 来生成 configure。configure 这一步检查客户端需要的编译器、库和头文件,然后写出反映检查结果的 makefile。make 这一步进行编译。install 这一步把结果复制到你路径上的某个位置。
恰恰是最后这一行,建议常常出错。安装并不能证明构建成功;把它放在任意下载文件夹里用高权限运行,只会让你以后想不起来那些文件放在哪。如果 configure 因为缺少某个库而失败,有用的输出是它打印的第一条错误,而不是日志最后二十行。
会话与网络配置是分开的
这个区分决定了连接是否真的承载流量。建立 TLS 会话只给你客户端一侧的接口。应用路由、地址和 DNS 解析器是通过网络脚本完成的第二步;一个只生成二进制程序却没带脚本的构建,只有半个客户端。
同样的分离也解释了为什么两台客户端相同的机器表现不同:脚本会查询系统的网络配置,而那个配置包含任何其他声称占用了某条路由的东西。当分离隧道把流量送到意料之外的地方时,隧道本身在正常工作,该检查的是路由决策。
所以调试时先问是哪一层失败了。连接始终建立不起来,是协议、证书或凭据问题。连接建立了却什么都不转发,是接口和脚本的问题。已安装的客户端在一个网络里能用、换一个就不能用,是可达性问题,再怎么重新构建也改变不了。
弄清你运行的是哪个二进制程序
手动安装的构建和打包的二进制程序可以和平共存,最终运行哪一个取决于你的路径,而不是你的意图。在把版本号告诉任何人之前,先把这件事弄清楚。
which -a openconnect
openconnect --version
brew list --versions openconnect
第一条命令按 shell 会尝试的顺序列出它能看到的所有副本。第二条告诉你哪一个回应了。如果这与你的预期不符,你运行的是旧实验留下的构建,任何配置改动都挪不动它。
安装客户端不等于网关批准
能运行的二进制程序并不能让部署变得兼容。网关的协议、认证流程以及任何受管设备要求,都要向拥有它的人确认,因为那是构建无法提供的策略与应用层事实。
项目的构建说明更详细地讲了 autotools 的顺序和对网络脚本的要求,应该以它为准,而不是早于你所用 macOS 版本的博客文章。如果目标只是连接,那就取软件包、保留脚本,把编译器放在一边。