使用 C++/libcurl/openssl 从应用程序保护服务器通信

Posted

技术标签:

【中文标题】使用 C++/libcurl/openssl 从应用程序保护服务器通信【英文标题】:Secure Server Communication from application using C++/libcurl/openssl 【发布时间】:2017-03-16 10:02:18 【问题描述】:

我正在使用 C++(跨平台;Windows、Mac 和 Linux)开发应用程序,该应用程序需要使用带有 libcurl 的 https 协议与服务器安全通信 (在 Windows/Mac/Linux 上使用 winssl/darwinssl/openssl 构建)分别)。我将 curl 选项 CURLOPT_SSL_VERIFYPEER0 更改为 1,这应该有助于防止中间人问题。

这导致了初始搜索指向关闭该选项的问题,但在深入挖掘后我发现:

获取可以验证远程服务器的 CA 证书,并在连接时使用适当的选项指出此 CA 证书以进行验证。对于 libcurl 黑客:curl_easy_setopt(curl, CURLOPT_CAPATH, capath);from curl docs

获得更好/不同/更新的 CA 证书包!一种选择是通过在 curl 构建树根目录中运行“make ca-bundle”来提取最近 Firefox 浏览器使用的版本,或者可能下载以这种方式为您生成的版本。 from curl docs

我实际上在捆绑包中使用了 CURLOPT_CAINFO,因为我在 Windows 上看到了一些使用 CURLOPT_CAPATH 的问题; curl docs。我已经在 Windows 和 Mac 上下载并安装了这个捆绑包以及应用程序,我想知道这是否是正确的方法,或者是否有更好的做法。

最初,这会给在某些公司网络或代理后面运行的应用程序的用户带来问题,这些问题似乎可以通过在 Windows 上针对 winssl 而不是 openssl 构建 libcurl 而得到解决;尽管可能将自己伪装成防火墙问题,但仍不清楚,尽管看起来很有可能。

抱歉,篇幅较长。

ca-cert-bundle.crt 与应用程序一起安装有什么愚蠢的地方吗?为了从这个已安装的应用程序与服务器进行安全通信,是否应该采取不同的措施?

一个稍微独立但仍然非常相关的问题是我在 Linux 上的 CURLOPT_CAINFO 给出了错误:

error setting certificate verify locations: CAfile: ../share/my_application/curl-ca-bundle.crt CApath: none

尽管尝试打开文件以从应用程序中读取确实可以成功。 编辑:我通过不在 Linux 上设置 CURLOPT_CAINFO 字段(将其留空) 并将依赖包 ca-certificates 添加到应用程序包中解决了这个问题。默认路径是正确的/etc/ssl/certs/ca-certificates.crt,并且似乎可以正常工作。对来说,这感觉比使用应用程序安装捆绑包要好一些。

Edit2: 虽然已解决,但似乎 ca-certificates 包有时不会安装 ca-certificates.crt 而是 ca-bundle.crt 并且位置在不同发行版上有所不同,如 this source, happyassassin.net 所示不同的 Linux 系统将 CA 包存储在不同的位置。对于如何处理,似乎没有明确的答案。我应该在配置文件中使用用户可以修改的值,还是对这个主题有任何其他想法?

Edit3: 一些用户指出我的名字存在于 curl 寻找的路径之一中,我不完全确定这如何可能是我为 curl 指定的唯一内容是我建立 openssl/cares 库的地方...

我意识到这是一个加载/多部分问题,但它与标题所述的主题相同,我将不胜感激。

谢谢。

【问题讨论】:

【参考方案1】:

默认的 libcurl 构建被设置为尝试使用“正确的”CA 包。

Linux

在 Linux 上构建的 libcurl 将扫描并检查 CA 存储在您的系统上的位置并使用它。如果您在常规 Linux 发行版上安装 libcurl,则应该使用该发行版的“典型”CA 存储来构建它。

macOS

如果您为 mac 构建 libcurl 并告诉它使用安全传输后端,它将自动使用 macOS CA 存储。 Apple 与 macOS 捆绑提供的默认安装的 curl 和 libcurl 也是如此。

窗口

如果您为 Windows 构建 libcurl 以使用 Schannel(Windows TLS 系统),它将默认使用 Windows CA 存储。

其他设置

如果您偏离这些设置,您基本上会选择不使用您正在使用的操作系统中捆绑的 CA 商店。然后您需要自己处理和更新 CA 存储。

【讨论】:

【参考方案2】:

在我看来,最好使用系统证书,然后将证书与应用程序打包(如果您没有使用一些特殊证书)。对于 linux,根据https://serverfault.com/questions/394815/how-to-update-curl-ca-bundle-on-redhat 应该很容易,对于 Windows,您可以使用 winssl 或从系统创建文件 https://superuser.com/questions/442793/why-cant-curl-properly-verify-a-certificate-on-windows Configure cURL to use default system cert store

【讨论】:

我目前在 Windows 上使用 WinSSL,但是我的初始方法与您提供的超级用户链接相同,将 CA 捆绑包与应用程序一起提供,我觉得有点奇怪 - 它还导致公司网络出现错误;自 WinSSL 更改以来,这些似乎已经消失,或更改为 DNS/防火墙问题。在 Linux 上,您提供的链接显示了 Redhat 和类似发行版的特定位置,但在 Debian/Ubuntu 上,ca-certificates 包似乎将它们放在不同的位置,因此将 CAPATH 设置为一个会错过另一个。 可能你应该把它留空,它应该采用默认的 CA 路径。但是,它不适用于某些发行版(网络中有一些错误报告)。因此,您需要对不同的版本进行一些测试并相应地使用路径... 我实际上并没有在 linux 上指定 CA PATH,所以这就是应该发生的事情,我看到我的最后一条评论看起来像是我设置的,对不起,我只是想说使用该选项可以在一个地方工作,但不能在另一个地方工作。

以上是关于使用 C++/libcurl/openssl 从应用程序保护服务器通信的主要内容,如果未能解决你的问题,请参考以下文章

Windows 编译libcurl(openssl+zlib)(使用VC编译)

使用 Nginx 的 https SSL 证书验证因自定义构建的 libcurl+openssl 而失败,但适用于系统 curl

Arduino到期HTTPS支持

Facebook API页面提要没有向我的webhook发送信息?

模块化数据中心设计探讨

如何在backbone.js中安全地发送/接收数据