![curl 可以成功发送 https 请求,apache2 却不行](https://linux22.com/image/722710/curl%20%E5%8F%AF%E4%BB%A5%E6%88%90%E5%8A%9F%E5%8F%91%E9%80%81%20https%20%E8%AF%B7%E6%B1%82%EF%BC%8Capache2%20%E5%8D%B4%E4%B8%8D%E8%A1%8C.png)
Ubuntu 服务器 14.04。
我必须通过 https 连接到网络外部的应用程序。我正在使用 apache2 在 https 层上建立通信。
另一方面,它要求进行客户端证书身份验证。我在 Ubuntu 中安装了所有证书链。CA、中间证书以及它们的公共证书。
一个实际的例子:
curl -lv https://this-application/receiving-link
* Hostname was NOT found in DNS cache
* Trying 111.222.333.444...
* Connected to application-something (111.222.333.444) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* 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: unable to get local issuer certificate
* Closing connection 0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
我期望的正是这个结果。
我在这里加载了所有证书链 + 公共(pem 格式和散列、软链接):/etc/apache2/mytrustedclientcerts
curl -lvvvvv --capath "/etc/apache2/mytrustedclientcerts/" https://this-application/receiving-link
* Hostname was NOT found in DNS cache
* Trying 111.222.333.444...
* Connected to application-something (111.222.333.444) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/apache2/mytrustedclientcerts/
* 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, Request CERT (13):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, CERT (11):
* 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 ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
* information about the certificate here
* ...
* ...
* ...
* ...
* SSL certificate verify ok.
> GET /b2b/httpReceiver HTTP/1.1
> User-Agent: curl/7.35.0
> Host: application-something.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Mon, 04 Jun 2018 13:16:20 GMT
* Server Server is not blacklisted
< Server: Server
< Content-Length: 155
< test: some_thing
< test: 0:1
< Content-Type: text/html; charset=ISO-8859-1
<
<html><head><title>Server</title></head>
<body><h1>Hello</h1>
Ready.
</body></html>
* Connection #0 to host application-something.com left intact
完美。这就是我如何判断自己是否能够连接,而我确实做到了。
现在轮到 Apache2 了。
我添加到我的已启用站点 配置配置文件:
SSLCACertificatePath "/etc/apache2/mytrustedclientcerts/"
SSLVerifyDepth 10
SSLVerifyClient optional #this must be optional because of many reasons
就像我在测试服务器中所做的那样,更改后连接立即生效。在此生产服务器(两者都是 Ubuntu 14.04)中,连接不起作用。
我在我的申请日志中看到:
06/04/18 11:42:31 SenderModule: Connecting to: https://this-application/receiving-link [message-for-sending-hash]
06/04/18 11:42:32 SenderModule: Failed to connect to partner using SSL certificate. Please run the SSL certificate checker utility to identify the issue: https://this-application/receiving-link [message-for-sending-hash]
我尝试过了核实证书也是如此:
openssl verify -verbose -x509_strict -CApath /etc/apache2/mytrustedclientcerts/ /etc/apache2/mytrustedclientcerts/4.https_public.pem
其中写道:
/etc/apache2/mytrustedclientcerts/4.https_public.pem: OK
我重新启动了 Apache2 来应用更改 - 我不想在 CURL 上使用“-k”选项,因为这不是重点。
我问是否有人知道为什么 Apache2 无法获取这些证书并使用它们。可能是我遗漏了文档中的某些内容:https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcacertificatepath但老实说,我不这么认为。如能提供任何帮助我将不胜感激!
答案1
这不是我想要的但至少现在我可以正常工作了。
我的目标是告诉Apache2使用专门为证书创建的文件夹,我希望 Apache2 只信任和连接该证书,而不是整个系统。这个文件夹是/etc/apache2/mytrustedclientcerts/
。就像我对 CURL 所做的一样。
由于我需要准备好连接,因此我在系统中全局信任了证书:
- 复制 .crt 扩展名中的证书编码版本,
/etc/ssl/cert
- 运行我为散列和链接证书准备的小脚本(见下文)。
此后,与 Apache 的 HTTPS 连接就可以正常工作了。尽管不是我想要的,但至少它可以正常工作。
#!/bin/bash
hash=$(openssl x509 -noout -hash -in "$1")
if [ $(ls -1 "${hash}."* 2>/dev/null | wc -l) -gt 0 ]; then
inc=$(ls -t "${hash}."* | head -1 | awk -F"." '{print $2}')
((inc+=1))
else
inc=0
fi
ln -s "$1" "${hash}.${inc}"