Skip to main content

症狀

同一臺機器上,curl 呼叫 api.apiyi.com 一切正常,但 Python 程式(尤其是 Conda 環境)報錯:
有時表現為 443 埠連線超時、握手階段就斷開。沒有連 VPN,換個網路環境(比如手機熱點)又能通。

簡短回答

這不是 API易 服務端的問題,也不是證書問題,而是你的 OpenSSL 版本與所在網路的中間裝置不相容。 先對比兩邊的 OpenSSL 版本:
如果報錯的那一邊是 OpenSSL 3.5 或更新版本,而正常的那一邊低於 3.5,基本就是這個原因。

原因

OpenSSL 從 3.5 開始,TLS 握手預設帶上後量子金鑰交換(X25519MLKEM768)。這會讓握手的第一個包(ClientHello)從約 300 位元組漲到約 1500 位元組,超過一個 TCP 報文段的大小,必須拆成兩段傳送。 部分企業防火牆、TLS 檢測裝置和運營商側的深度包檢測裝置處理不了被拆開的握手包,或者不認識這個新的金鑰交換演算法,會直接把連線斷開。客戶端看到的就是「EOF occurred in violation of protocol」。 API易 的所有邊緣節點都支援這種後量子握手,2026-09-11 (UTC+8) 我們用 OpenSSL 3.6.4 逐臺驗證過,全部通過。握手包是在你的網路裡被丟棄的,服務端收不到,所以服務端無法替你修復。

三條命令自證

報錯的那個環境裡的 openssl(Conda 環境請先啟用)依次執行:

修復方法(任選其一)

1

方法一:用配置檔案關閉後量子金鑰交換(推薦)

新建一個檔案,例如 ~/no-pq.cnf
執行程式前設定環境變數:
這會讓該環境裡所有基於 OpenSSL 的程式(Python、curl、pip 等)都不再發送後量子金鑰份額,握手包縮回約 300 位元組。不影響加密強度,只是回到 3.5 之前的預設行為。
2

方法二:降級 Conda 裡的 OpenSSL

3.5 之前的版本預設不帶後量子金鑰交換。注意這會連帶調整依賴它的包,生產環境請先在測試環境驗證。
3

方法三:讓網路部門升級中間裝置

主流防火牆和 TLS 檢測裝置在 2025 年之後的韌體版本都已支援混合後量子握手。這是根治辦法,也能避免以後訪問其他站點時出現同樣的問題。

常見追問

瀏覽器和你的程式走的可能不是同一條網路路徑(比如瀏覽器配置了系統代理),而且瀏覽器在握手失敗時會自動重試不帶後量子份額的握手,程式不會。
只要 TLS 庫是 OpenSSL 3.5 或更新版本就可能遇到,包括用新版 OpenSSL 編譯的 curl 8.x。Go 和 Java 使用自己的 TLS 實現,是否預設啟用後量子交換取決於各自的版本,判斷方法相同:用上面三條命令看是否只有預設握手失敗。
沒用。連線在握手階段就被斷開,還沒到證書驗證這一步。關閉證書驗證既不能解決問題,還會帶來安全風險。
握手的第一個包是客戶端發出的,被丟在你的網路裡時服務端根本收不到,服務端配置對此無能為力。如果你按上面的三條命令測出「對其他站點預設握手成功、只對 api.apiyi.com 失敗」,請把結果發給客服,我們會進一步排查。

相關問題

使用 API 介面需要代理網路嗎?

API易 支援直連,無需代理或 VPN

超時配置建議

連線超時與讀取超時應該怎麼設