PHP cURL 遇到的錯誤:cURL Error: Peer reports incompatible or unsupported protocol version.
,探討解決方案。
範例程式碼
以下是我使用的範例程式碼,用於向 API Server 傳送資料:
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_DEFAULT);
// 執行 cURL 請求
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURL Error: ' . curl_error($ch) . "\n";
} else {
echo "Response:\n";
echo $response;
}
此程式碼導致錯誤,因為主機與 API Server 支援的 SSL/TLS 協議不匹配。
系統環境
發生原因
檢查 OpenSSL 版本後發現,OpenSSL 1.0.2k-fips 只支持到 TLS 1.2,但目標 API Server 僅允許 TLS 1.3。這就導致了協議不匹配,從而引發了錯誤。
OpenSSL 1.0.2k-fips 支援的 SSL/TLS 協議:
因為 OpenSSL 1.0.2 不支持 TLS 1.3,而 API Server 僅允許 TLS 1.3,導致 SSL/TLS 協議不兼容。
解決方案
1. 升級主機的 SSL/TLS 支援
若 API Server 僅支援 TLS 1.3,主機必須升級至支援 TLS 1.3 的 OpenSSL 版本(至少為 OpenSSL 1.1.1)。這樣可以確保 PHP 主機與 API Server 之間的 SSL/TLS 協議匹配。
2. 讓 API Server 向下兼容 TLS 1.2
如果 API Server 能夠向下兼容 TLS 1.2,則可以暫時允許 TLS 1.2 通訊,以解決當前的不兼容問題。儘管 TLS 1.3 更加安全,但在過渡期間允許使用 TLS 1.2,可以確保現有系統正常運行。
實作過程
在我的情況下,由於主機當前無法即時升級至支援 TLS 1.3 的 OpenSSL,我選擇了讓 API Server 向下兼容 TLS 1.2 的方案。這樣系統可以恢復運作,並且在未來 OpenSSL 升級至支援 TLS 1.3 時,再切換至僅支持 TLS 1.3 的模式。
在 Plesk 中,可以使用以下命令來啟用 TLS 1.2 和 TLS 1.3:
# plesk bin server_pref -u -ssl-protocols 'TLSv1.2 TLSv1.3'
執行此命令後,請重啟相關服務(如 Apache、Nginx、PHP-FPM)以應用更改。
這樣可以臨時解決協議不兼容的問題。
檢測工具
當不確定目標主機支援哪些 TLS 協議版本時,可以使用 SSL Labs 工具來檢查目標主機的 TLS 支援情況。該工具可以幫助你確定目標主機的協議支援,從而避免不兼容問題的發生。
參考資料
https://www.plesk.com/kb/support/how-to-enable-disable-tls-protocol-versions-in-plesk-for-linux/
https://talk.plesk.com/threads/best-practice-for-upgrading-openssl-on-centos-7-9-obsidian-v18-0-54.371042/
https://www.isres.com/jingyan2/79.html
https://blog.csdn.net/weixin_46858088/article/details/135718447
[……]