使用 NetworkManager 进行 Openconnect 证书验证

使用 NetworkManager 进行 Openconnect 证书验证

在我的 Cinnamon (linux) 桌面上,我在 NetworkManager 中设置了一个 openconnect VPN 连接。连接时,我似乎没有遇到任何问题:连接已建立,网络流量通过它路由。但是,我的系统日志包含一个令人担忧的条目:

openconnect[2935]: SSL negotiation with (...)
openconnect[2935]: Server certificate verify failed: signer not found
openconnect[2935]: Connected to HTTPS on (...)
openconnect[2935]: Got CONNECT response: HTTP/1.1 200 OK

我尝试openconnect从命令行使用,它没有打印任何有关证书问题的信息(即使在详细模式下)。此外,在 Firefox 或使用中该网站没有证书错误wget(我不知道 openconnect 使用哪个证书存储...)。

这是否意味着该连接容易受到中间人攻击?如果无法验证证书,为什么在连接和发送我的凭据之前没有确认提示要求我信任证书?为什么只有在使用 NetworkManager 连接时才会出现此问题?

命令行openconnect

/usr/sbin/openconnect --servercert sha1:bee140657db50a73ee69f47fee9e4d670905206e --syslog --cookie-on-stdin --script /usr/lib/NetworkManager/nm-openconnect-service-openconnect-helper --interface vpn0 (ip):443

如果我没有在 NetworkManager 中明确设置 CA 证书,也会出现警告。

答案1

该问题在 Ubuntu 18.04 中仍然存在network-manager-openconnect

我认为这里的问题是连接到 VPN 服务器的 IP 地址,而不是它的 DNS 名称:

$ ps aux | grep openconnect
/usr/sbin/openconnect --servercert sha256:<hash> --syslog --cookie-on-stdin --script /usr/lib/NetworkManager/nm-openconnect-service-openconnect-helper --interface vpn0 <ip>:443

手动运行命令,不带--servercert参数:

$ /usr/sbin/openconnect <ip>:443 --authenticate
POST https://<ip>/
Connected to <ip>:443
SSL negotiation with <ip>
Server certificate verify failed: certificate does not match hostname
Certificate from VPN server "<ip>" failed verification.
Reason: certificate does not match hostname
To trust this server in future, perhaps add this to your command line:
   --servercert sha256:<hash>
Enter 'yes' to accept, 'no' to abort; anything else to view: 

注意证书验证失败。

现在使用主机名而不是 IP:

$ /usr/sbin/openconnect <hostname>:443 --authenticate
POST https://<hostname>/
Connected to <ip>:443
SSL negotiation with <hostname>
Connected to HTTPS on <hostname>
XML POST enabled
Please enter your username and password.

没有证书错误。

现在,使用带有 servercert 参数的 IP:

$ /usr/sbin/openconnect <ip>:443 --authenticate --servercert sha256:<hash>
POST https://<ip>/
Connected to <ip>:443
SSL negotiation with <ip>
Server certificate verify failed: signer not found
Connected to HTTPS on <ip>
XML POST enabled
Please enter your username and password.

将错误与第一个示例进行比较 - 这是一个不同的错误。这个错误失败是因为找不到签名者。考虑到我们只是指定一个哈希,我想这是有道理的,因为没有信任链可以遵循。

对我来说,我认为根本原因是网络管理器出于某种原因连接到 IP 地址而不是主机名。不确定它为什么会这样做?

答案2

我在 Arch Linux 中使用 networkmanager-connect 和 network-manager-applet 时遇到了同样的问题。我通过手动下载 ca 证书解决了这个问题:

echo -n | openssl s_client -connect <HOST>:<PORTNUMBER> \
| sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/vpn.crt

[来源]

然后我在 Gnome 的网络设置中的 VPN 配置菜单中选择了该文件。这会将以下行添加到配置文件 /etc/NetworkManager/system-connections/MyVpn.nmconnection:

[vpn]
...
cacert=/home/<my username>/vpn.crt

它可能会更改配置文件中的其他一些行。我没有运行 diff 来找出原因。但无论如何,我随后能够通过网络管理器连接到我的 vpn。

答案3

正如@curvy所述,network-manager-openconnect 使用 ip 地址而不是主机名。这是提供仅主机名证书的 vpn 网关的问题。

为了避免这个问题,你可以重新编译https://gitlab.gnome.org/GNOME/NetworkManager-openconnect应用这个简单的补丁。

diff --git a/src/nm-openconnect-service.c b/src/nm-openconnect-service.c
index 348c19a..273efb5 100644
--- a/src/nm-openconnect-service.c
+++ b/src/nm-openconnect-service.c
@@ -415,9 +415,10 @@ nm_openconnect_start_openconnect_binary (NMOpenconnectPlugin *plugin,
        return -1;
    }
 
-   /* The actual gateway to use (after redirection) comes from the auth
-      dialog, so it's in the secrets hash not the properties */
-   props_vpn_gw = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY);
+   /* Replaced nm_setting_vpn_get_secret with nm_setting_vpn_get_data_item
+      because if we use ip to get connection we may have problems with
+        certificates signed only with hostnames */
+   props_vpn_gw = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_GATEWAY);
    if (!props_vpn_gw || !strlen (props_vpn_gw) ) {
        g_set_error (error,
                     NM_VPN_PLUGIN_ERROR,
@@ -596,7 +597,7 @@ real_need_secrets (NMVpnServicePlugin *plugin,
    }
 
    /* We just need the WebVPN cookie, and the final IP address of the gateway
-      (after HTTP redirects, which do happen). All the certificate/SecurID 
+      (after HTTP redirects, which do happen). All the certificate/SecurID
       nonsense can be handled for us, in the user's context, by auth-dialog */
    if (!nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY)) {
        *setting_name = NM_SETTING_VPN_SETTING_NAME;

相关内容