使用带有SNI的cURL(服务器名称指示)

Jus*_*tin 21 php ssl curl sni

我正在尝试使用cURL发布到刚刚开始使用SNI的API(因此他们可以在1个IP地址上托管多个ssl证书).

由于此次转向SNI,我的cURL停止了工作.他们解释说这是因为cURL返回*.domain-a.com而不是*.domain-b.com所以SSL失败了.

这似乎是cURL中的一个错误,因为API URL在从浏览器访问时没有错误.

使用此代码,它确实有效:

exec('curl -k -d "parameters=here", https://urlhere.com/', $output);
print_r($output);
Run Code Online (Sandbox Code Playgroud)

但是,使用-k是不好的,因为它不验证SSL证书.

使用此代码不起作用:

exec('curl -d "parameters=here", https://urlhere.com/', $output);
print_r($output);
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,如何在SNI中使用curl并仍然验证SSL(不必使用-k).PHP或cURL选项中是否有其他设置我可以设置解决此问题?

Bru*_*uno 46

为了能够使用SNI,需要三个条件:

  • 根据更改日志,使用支持它的Curl版本,至少7.18.1 .
  • 使用针对支持SNI的库编译的Curl版本,例如OpenSSL 0.9.8j(取决于某些旧版本的编译选项).
  • 至少使用TLS 1.0(不是SSLv3).

请注意,Curl的调试代码(-v)仅显示主要版本号(主要用于区分SSLv2和SSLv3 +类型的消息,请参阅ssl_tls_trace),因此当您使用TLS 1.0或更高版本时它仍会显示"SSLv3"(因为它们实际上是SSL) v3.1或更高版本,3是相同的主要版本号).

您可以使用Wireshark检查已安装的curl版本是否可以使用SNI.如果您使用连接curl -1 https://something,如果展开"客户端Hello"消息,您应该能够看到" server_name"扩展名.

我不确定默认情况下使用哪个SSL/TLS版本(取决于您的编译选项)当您使用curlwithout -1(对于TLS 1.0)或-3(对于SSLv3)时,但您可以尝试强制-1执行命令,因为它赢了'无论如何都要使用SSLv3.

  • 请注意,与-k或--insecure一起使用时,Mac OS X(Yosemite)上的卷曲不会发送SNI. (8认同)
  • BTW是一个很好的答案的例子.谢谢 (3认同)

小智 9

连同所需的库和Curl版本一起,请求应使用resolve在curl中发送SNI:

curl -vik --resolve example.com:443:198.18.110.10 https://example.com/
Run Code Online (Sandbox Code Playgroud)

  • 就我而言,我是通过 IP 访问服务器的。证书是通过使用 Firefox 通过 IP 访问同一服务器来下载的。如果我信任 Mac 钥匙串中的证书,那么通过 IP 访问它就可以正常工作,无需验证 cURL 中的证书。但是,当我从 Keychain 中删除该证书并尝试在 cURL 中验证它时,我不断收到“验证失败”错误,直到我将该 IP 解析为我从中下载原始证书的名称,如这个答案所示。 (2认同)