簡體   English   中英

PHP stream_socket_client無法連接

[英]PHP stream_socket_client fails to connect

我正在嘗試通過php的stream_socket_client()命令聯系url,該命令失敗,沒有錯誤代碼或msg。 是否使用openssl,curl或其他? 該網站使用https,並且可以通過網絡瀏覽器正常運行。

在此處輸入圖片說明

當我直接致電openssl時,它會連接,但證書鏈顯示為hphppy。

root@drupal7 drupal7/includes# openssl s_client -connect test.cgps.org:443
CONNECTED(00000003)
Verify return code: 21 (unable to verify the first certificate)

一樣卷曲

curl https://test.cgps.org/?q=/admin/config/search/clean-urls/check
curl: (60) SSL certificate problem: unable to get local issuer certificate

因此,我認為我需要將中間證書安裝到Linux中,方法是將Apache使用的相同中間證書放入/ usr / local / share / ca-certificates並運行update-ca-certificates。

root@drupal7 drupal7/includes# update-ca-certificates
Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.

還是沒有運氣...

盡管評論中有聲明說PHP的steam_socket_client()太低級,無法處理證書,但我知道它確實在乎,因為我發現它在標准位置缺少某些證書的系統上返回false ,在該位置提供流上下文(告訴它在哪里可以找到證書)阻止了這種情況的發生。

令人沮喪的是,在您修復此問題之前, $errno可以保持為0,因此最好先使用其他工具檢查您的證書授權目錄。

診斷

通過curl

為了使curl起作用,通常可以通過添加--verbose標志來弄清楚發生了什么。 這應該告訴您正在使用哪個串聯的證書PEM文件(CAfile / cacert)和CA目錄(capath)(如果有)。 在輸出的頂部,您將獲得類似以下內容的信息:

[...]
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: /home2/wynddorg/private_html/trusted_roots
[...]

知道這些默認設置后,您就可以調整系統配置,或者簡單地添加--cacert <concatenated_cert_path>標志或--capath <c_rehash'd_directory>或兩者。

通過openssl s_client

使用s_client比較麻煩。 您可能可以訪問其-trace選項,具體取決於您的版本及其編譯方式,但是請嘗試:

strace -e open,stat openssl s_client -connect test.cgps.org:443 [-CApath <dir>]
# this trick provided by the amazing xemdetia in irc://freenode/%23%23openssl

CONNECTED(00000003)消息后大約5行,您應該看到一個open("...", O_RDONLY) (或幾行),該行應該揭示正在使用哪些位置查找證書。


我缺少一個或多個證書。 怎么辦?

一旦知道缺少哪些證書,就可以按照此處所示下載它們,然后執行任何操作:

  • 將它們串聯成一個PEM文件(最好按順序排列 ),然后在嘗試連接到站點時指定該文件
  • 將它們另存為默認目錄中的“ .crt”文件,然后在該目錄上運行c_rehash (可能需要root / sudo)
  • 將它們另存為另一個“ .crt”文件在另一個目錄中,並在連接時顯式指定為capath。 您可能希望在共享主機上執行此操作,或者如果您不希望所有應用程序僅信任某些證書,則可以這樣做。

一旦可以使用openssl s_clientcurl或同時使用二者,就可以指定相同的選項,如下所示:

$context = stream_context_create();
stream_context_set_option($context, 'ssl', 'cafile', <concatenated_cert_file_path>);
stream_context_set_option($context, 'ssl', 'capath', <c_rehashed_cert_dir_path>);
// You only really need to provide one of the two options above. Using capath is
// faster, but this only matters if you'll be making a huge number of
// connections.
$ssc = stream_socket_client(
    'ssl://subdomain.example.com:443',
    $errno,
    $errstr,
    30,
    STREAM_CLIENT_CONNECT,
    $context
);
if ($ssc) { /* ... */  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM