使用自定义构建的 libcurl+openssl 时,Nginx 的 https SSL 证书验证失败,但适用于系统curl
我正在使用 libcurl 通过 https 与两个独立的 Web 服务器通信。
第一个服务器在 64 位 Ubuntu 10.04 上运行 Lighttpd 1.4.26-1。 Lightty 是针对 openssl 版本 0.9.8k 构建的。
第二台服务器在 32 位 Ubuntu 10.04 上运行 Nginx 0.7.65。 Nginx 是针对 openssl 版本 0.9.8k 构建的。
这两个服务器都使用相同的证书,并且 DNS 在它们之间进行循环。我使用 /etc/hosts 来管理我正在访问的两个中的哪一个。
我正在使用针对 openssl 1.0.0c 构建的 libcurl 版本 7.21.2。
这样,libcurl 可以成功向 lightty 服务器发出 https 请求,但不能向 nginx 服务器发出 https 请求。我可以使用curl 命令行界面复制此内容。这是curl -v的输出:
* About to connect() to <hostname> port 443 (#0)
* Trying <ip>... connected
* Connected to <hostname> (<ip>) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: cadata
CApath: none
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
* Closing connection #0
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
如果我使用旧版本的curl(7.19.7和openssl 0.9.8l),我碰巧在同一系统上有相同的请求:
* About to connect() to <hostname> port 443 (#0)
* Trying <ip>... connected
* Connected to <hostname> (<ip>) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: certdata
CApath: none
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using DHE-RSA-AES256-SHA
* Server certificate:
认为这与较新的版本有关版本的curl和/或openssl,我使用相同的版本和启用的选项重建了我的curl和libcurl:
Broken (my build):
seldon:bin ryanowen$ ./curl -V
curl 7.19.7 (i386-apple-darwin10.7.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
Protocols: tftp ftp telnet dict ldap http file https ftps
Features: GSS-Negotiate IPv6 Largefile NTLM SSL libz
Works (system version):
seldon:bin ryanowen$ /usr/bin/curl -V
curl 7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
Protocols: tftp ftp telnet dict ldap http file https ftps
Features: GSS-Negotiate IPv6 Largefile NTLM SSL libz
不幸的是,这似乎没有什么区别。我的 curl 构建仍然失败(但仅在与 nginx 服务器通信时),而系统构建当然仍然有效。
我的 libcurl 构建可能有什么不同导致 SSL 握手失败?是否有任何选项未反映在我需要启用的 -V 输出中?关于 Nginx 方面有什么我应该研究的吗?
I'm using libcurl to talk to two separate web servers over https.
The first server is running Lighttpd 1.4.26-1 on 64-bit Ubuntu 10.04. Lightty is built against openssl version 0.9.8k.
The second server is running Nginx 0.7.65 on 32-bit Ubuntu 10.04. Nginx is built against openssl version 0.9.8k.
Both of these servers use the same certificate, and DNS is round-robined between them. I use /etc/hosts to manage which of the two I'm hitting.
I'm using libcurl version 7.21.2 built against openssl 1.0.0c.
With this, libcurl can successfully make an https request to the lightty server, but not the nginx server. I can duplicate this with the curl command-line interface. Here's the output of curl -v:
* About to connect() to <hostname> port 443 (#0)
* Trying <ip>... connected
* Connected to <hostname> (<ip>) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: cadata
CApath: none
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
* Closing connection #0
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
If I use an older version of curl (7.19.7 with openssl 0.9.8l) that I happen to have on the same system, the same request works:
* About to connect() to <hostname> port 443 (#0)
* Trying <ip>... connected
* Connected to <hostname> (<ip>) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: certdata
CApath: none
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using DHE-RSA-AES256-SHA
* Server certificate:
Thinking this was something to do with the newer versions of curl and/or openssl, I rebuilt my curl and libcurl with the same version and options enabled:
Broken (my build):
seldon:bin ryanowen$ ./curl -V
curl 7.19.7 (i386-apple-darwin10.7.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
Protocols: tftp ftp telnet dict ldap http file https ftps
Features: GSS-Negotiate IPv6 Largefile NTLM SSL libz
Works (system version):
seldon:bin ryanowen$ /usr/bin/curl -V
curl 7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
Protocols: tftp ftp telnet dict ldap http file https ftps
Features: GSS-Negotiate IPv6 Largefile NTLM SSL libz
Unfortunately, this didn't seem to make a difference. My curl build still fails (but only when talking to the nginx server) while the system build of course still works.
What could be different about my libcurl build that is causing it to fail the SSL handshake? Are there any options not reflected in the -V output that I need to enable? Anything about the Nginx side of things that I should look into?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
最后我发现问题出在Nginx端。 Nginx 配置引用了服务器证书和密钥,但没有引用 CA 捆绑包。将 CA 捆绑包连接到服务器证书文件的末尾似乎已经解决了问题。
我提供给 libcurl 的 CA 数据包括 CA 证书,但不包括链中的其他一些证书。我猜想系统curl一定把这些证书藏在某个地方了。
I finally discovered the problem on the Nginx side. The Nginx config referenced the server certificate and key, but not the CA bundle. Concatenating the CA bundle onto the end of the server certificate file seems to have solved the problem.
The CA data I was giving to libcurl included the CA certificate, but not some of the other certificates in the chain. I guess the system curl must have had those certificates stashed away somewhere.