OpenConnect

来自 ArchWiki

OpenConnect 是一款免费开源的客户端到站点 VPN 软件。它允许您连接到各种商业的所谓 SSL VPN 服务器/网关/集中器,即

  • Cisco AnyConnect anyconnect
  • Palo Alto Networks (PAN) GlobalProtect gp
  • Junos/Ivanti Pulse Secure pulse,另请参阅 Pulse Connect Secure
  • Juniper Network Connect nc
  • Fortinet fortinet
  • F5 f5
  • Array Networks array

安装

为了与 NetworkManager 集成,如果您使用像 GNOMEKDE 这样的 桌面环境,您可能需要 安装 networkmanager-openconnect 软件包。它将拉取 openconnect 软件包作为依赖项。如果您不需要集成,只需 安装 openconnect 软件包即可。

某些 VPN 被设置为拆分路由,因此也拆分 DNS。为了满足这一点,并且一般来说,建议使用 systemd-resolved 和 resolv.conf stub 模式。要验证是否是这种情况,请运行 resolvectl 并查找全局部分中 "resolv.conf mode: stub" 这一行。理解完整的输出可能非常有用,因此最好 研究 它。连接到 VPN 后,输出将大致如下所示

$ resolvectl
Global
       Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub

Link 2 (enp1s0)
    Current Scopes: DNS
         Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 192.168.0.1
       DNS Servers: 192.168.0.1
        DNS Domain: ~home.box

Link 3 (tun0)
    Current Scopes: DNS
         Protocols: -DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 10.10.10.10
       DNS Servers: 10.10.10.10
        DNS Domain: ~example.org ~int.example.net

用法

纯 OpenConnect

OpenConnect 有许多选项,请参阅 openconnect(8)。在最简单的情况下,您正在使用 Cisco AnyConnect VPN,因此您只需提供地址,然后在提示时输入您的用户名和密码。

$ sudo openconnect vpnserviceaddr

如果您使用 Cisco AnyConnect 以外的 VPN 类型,请添加 "--protocol" 选项,指定 ncgppulsef5fortinetarray 之一

$ sudo openconnect --protocol=vpntype vpnserviceaddr

也可以提供用户名

$ sudo openconnect --protocol=vpntype -u user vpnserviceaddr

某些 VPN 为不同的访问配置提供不同的身份验证组,例如用于完整隧道或拆分隧道连接。要显示不同的提供的身份验证组并获取有关该服务的一般信息,请使用

$ sudo openconnect --protocol=vpntype --authenticate vpnserviceaddr

某些 VPN 在连接时需要收集有关您计算机的信息。在这种情况下,"--csd-wrapper" 选项可能会有所帮助。要使用和调整的脚本可以在 "/usr/lib/openconnect/" 下找到。

$ sudo openconnect --protocol=vpntype --csd-wrapper=script vpnserviceaddr

某些 VPN 将身份验证委派给身份提供商 (IdP),例如 Google、Microsoft AzureActiveDirectory 或 Okta。这种情况通常称为单点登录 (SSO),通常采用 SAML 2.0 标准或 OIDC 标准。过程如下:在浏览器或 webview 中,您打开 VPN 的 SSO 地址,该地址重定向到 IdP,IdP 将您发送回 VPN 页面,您最终会得到一个 cookie。cookie 必须使用 "-C,--cookie" 或 "--cookie-on-stdin" 选项传递给 openconnect。要从浏览器复制 cookie,请使用其开发者工具。

$ sudo openconnect --protocol=vpntype --cookie-on-stdin vpnserviceaddr

对于 Fortinet SSO VPN,您可以使用 openfortivpn-webview-qtAUR 来获取 cookie,而无需摆弄浏览器的开发者工具

$ sudo openconnect --protocol=fortinet -C "$(openfortivpn-webview vpnserviceaddr)" vpnserviceaddr

OpenConnect 将几个环境变量传递给脚本,以配置 IP 路由和 DNS 路由。默认情况下,它是 "/etc/vpnc/vpnc-script"。它支持一些您可以在需要时设置的环境变量,例如 "CISCO_SPLIT_DNS" 以将额外的 DNS 域添加到网络接口,除了 VPN 推送的域之外。

$ sudo CISCO_SPLIT_DNS=~internal.example.com,~10.in-addr.arpa openconnect --protocol=vpntype vpnserviceaddr

您可以使用您自己的脚本来代替默认脚本,使用 "-s,--script" 选项

$ sudo openconnect --protocol=vpntype -s script vpnserviceaddr

您还可以将 OpenConnect 与像 ocproxy-gitAUR 这样的代理结合使用,以进行 SSH 风格的端口转发。例如,如果您运行以下命令,则使用 rdesktop 连接到 localhost:13389 的连接将通过 VPN 转发到 RDS 服务 rds.int.example.net:3389

$ openconnect --protocol=vpntype --script-tun -s "ocproxy -L 13389:rds.int.example.net:3389" vpnserviceaddr
$ rdesktop localhost:13389

使用 NetworkManager

NetworkManager 可以通过命令行界面 nmcli、通过终端用户界面 nmtui 以及通过许多桌面环境进行控制,这要归功于其 D-Bus API。对于 NetworkManager 来说,VPN 只是另一种类型为 "vpn" 的连接。要使用 CLI 创建一个基于 OpenConnect 且名为 "MyOrgVPN" 的连接,请运行

$ nmcli connection add \
	 connection.id MyOrgVPN \
	 connection.type vpn \
	 vpn.service-type openconnect \
	 vpn.data cookie-flags=2,gateway=vpnserviceaddr,protocol=vpntype vpn.secrets gateway=vpnserviceaddr,gwcert=

在大多数情况下,使用 nmcli connection up MyOrgVPN(即不带 --ask)或 GNOME 右上角的菜单或 GNOME 设置(也称为控制中心)激活连接会按预期工作:会打开一个窗口并要求输入用户名、密码,以及可能的 2FA/MFA;即使 VPN 类型为 anyconnectgp,SSO 场景通常也有效。对于其他桌面环境,您可能需要安装 network-manager-appletnm-connection-editor 或其他一些软件包,以便控制 NetworkManager 连接。

然而,使用 nmcli --ask connection up MyOrgVPNnmtuinmtui connect MyOrgVPN 激活连接并不能像人们期望的那样工作:不是要求输入用户名等,而是要求输入 "Cookie (vpn.secrets.cookie)"。要提供它,您可以使用像这样的 Bash 脚本

~/vpn-up.bash
#!/usr/bin/bash

connection_name=$(nmcli -t -g type,name connection \
	| grep -Po '^vpn:\K.*' \
	| sed 's/\\:/:/g' | fzf
)
eval "$(nmcli -t -g vpn.data connection show "$connection_name" \
	| grep -Po '(^|[ ,])(protocol|gateway)\ =\ [^,]*' \
	| sed 's/ //g')"
eval "$(openconnect --authenticate --protocol="$protocol" "$gateway")"
nmcli connection up "$connection_name" \
	passwd-file <(echo "vpn.secrets.cookie:$COOKIE")

要停用连接,请使用 nmcli connection down MyOrgVPNnmtui 或 GNOME 右上角的菜单或 GNOME 设置(也称为控制中心)。

注意: NetworkManager-openconnect 尚未处理所有 VPN 场景,因此在某些情况下,您可能必须使用如上所述的纯 OpenConnect。

使用 WebAuth 和 Anyconnect 的单点登录 (SSO)

networkmanager-openconnect 支持使用 WebAuth 为 Cisco Anyconnect 进行单点登录 (SSO)。要使用 WebAuth

  • 不要忘记为 networkmanager-openconnect 安装可选依赖项,例如 webkit2gtk-*
  • 对于此连接,在 VPN 选项卡上的 “User Agent” 字段中添加类似 “AnyConnect Linux_64 4.10.07061” 的内容

激活连接。它应该为您弹出一个带有浏览器的窗口,用于完成 WebAuth。如果成功,networkmanager-openconnect 将启动 openconnect 并传递 “webvpn” cookie 以进行连接。

使用 netctl

一个简单的 tuntap netctl.profile(5) 可以用于将 OpenConnect 集成到正常的 netctl 工作流程中。例如

/etc/netctl/vpn
Description='VPN'
Interface=vpn
Connection=tuntap
Mode=tun
#User=root
#Group=root

BindsToInterfaces=(enp0s25 wlp2s0)
IP=no

PIDFILE=/run/openconnect_${Interface}.pid
SERVER=vpn.example.net
AUTHGROUP='<AUTHGROUP>'
LOCAL_USERNAME=<USERNAME>
REMOTE_USERNAME=<VPN_USERNAME>
# Assuming the use of pass(1): 
PASSWORD_CMD="su ${LOCAL_USERNAME} -c \"pass ${REMOTE_USERNAME} | head -n 1\""

ExecUpPost="${PASSWORD_CMD} | /usr/bin/openconnect --background --pid-file=${PIDFILE} --interface='${Interface}' --authgroup='${AUTHGROUP}' --user='${REMOTE_USERNAME}' --passwd-on-stdin ${SERVER}"
ExecDownPre="kill -INT $(cat ${PIDFILE}) ; resolvconf -d ${Interface} ; ip link delete ${Interface}"

这允许像这样的执行

$ netctl start vpn
$ netctl restart vpn
$ netctl stop vpn

请注意,这依赖于 LOCAL_USERNAME 运行 gpg-agent,并且 PGP 密钥的密码已缓存。

如果需要 pass 的交互式查询,请为 PASSWORD_CMD 使用以下行

DISPLAY=":0"
PASSWORD_CMD="su ${LOCAL_USERNAME} -c \"DISPLAY=${DISPLAY} pass ${REMOTE_USERNAME} | head -n 1\""

根据需要调整 DISPLAY 变量。

故障排除

Cisco AnyConnect

对于 Cisco AnyConnect VPN,如果您尝试使用 2FA/MFA,但它没有提示您输入密码,则需要将 useragent 设置为 AnyConnect ... 。这是 Cisco 的一个问题,这是 OpenConnect 项目中的 相关问题