今天原本使用好好的政府 OpenData API (https://gcis.nat.gov.tw) 在 Dify 的 Http 節點中居然出現[SSL:CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1010)
的錯誤。
以下紀錄在部署 Dify 至 Ubuntu Docker Compose 環境時,遇到 SSL 憑證驗證失敗的問題,包含台灣政府 CA 安裝、Python certifi 處理、Proxy 設定與完整排查修復流程。
先在 Ubuntu 執行 curl 就出現curl: (60) SSL certificate problem: unable to get local issuer certificate的錯誤。
curl -v https://data.gcis.nat.gov.tw/od/data/api/5F64D864-61CB-4D0D-8AD9-492047CC1EA6?$format=json
結果為 curl: (60) SSL certificate problem: unable to get local issuer certificate
使用 openssl 檢查憑證鏈:
openssl s_client -connect data.gcis.nat.gov.tw:443
結果如下,
Server certificate
subject=C = TW, L = \E8\87\BA\E5\8C\97\E5\B8\82, O = \E6\94\BF\E5\BA\9C\E6\A9\9F\E9\97\9C-\E8\B3\87\E8\A8\8A\E5\AE\A4, CN = gcis.nat.gov.tw
issuer=C = TW, O = "Chunghwa Telecom Co., Ltd.", CN = HiPKI OV TLS CA - G1
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: ECDH, prime256v1, 256 bits
---
SSL handshake has read 7920 bytes and written 448 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
Verification error: unable to verify the first certificate可以發現沒有 Root CA。
到中華電信公開憑證下載HiPKI OV TLS CA,
並放到 /usr/local/share/ca-certificates/
目錄中
wget https://epki.com.tw/repository-h/download/OVTLSCA1_b64.crt -O /usr/local/share/ca-certificates/OVTLSCA1_b64.crt
接下來更新系統CA
sudo update-ca-certificates
結果如下,
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
再使用 openssl 檢查憑證鏈echo | openssl s_client -showcerts -connect data.gcis.nat.gov.tw:443
可以發現已經驗證成功,如下,
SSL handshake has read 7920 bytes and written 448 bytes
Verification: OK
完成後,再到 Dify 執行,還是出現[SSL:CERTIFICATE_VERIFY_FAILED]
錯誤,
接下來,要來查看 Dify Docker 中到底是什麼問題造成的?
docker compose logs api
輸出如下,
[ssrf_proxy.py:78] - Request to URL http://data.gcis.nat.gov.tw/od/data/api/5F64D864-61CB-4D0D-8AD9-492047CC1EA6?$format=json&$filter=Business_Accounting_NO eq 22425662 failed on attempt 1: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1010)
[node.py:103] - http request node 1743067744592 failed to run: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1010)
可以發現,跟我們在Dify的Http運行時,錯誤一樣。
進入 API Container
docker compose exec api bash
確認 Python certifi 使用的憑證:
python3 -c "import certifi; print(certifi.where())"
結果如下,
/app/api/.venv/lib/python3.12/site-packages/certifi/cacert.pem
ubuntu host 的憑證是 OK 的,所以可以在docker-compose.yaml
設定 volume,
修改 dify 的 docker-compose.yaml 在 api 的 volumes 加入以下設定
api:volumes:
- /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro
- /etc/ssl/certs/ca-certificates.crt:/app/api/.venv/lib/python3.12/site-packages/certifi/cacert.pem:ro
重新執行docker compose
並測試看看,
docker compose down
docker compose up -d
再從 dify 去測試,可以發現 Http 節點,已經可以順利執行成功了。
以上的 SSL 問題排查流程,驗證了一個 Containerized 架構下的典型 SSL 問題:
中華電信公開憑證
SSL Cert Verification
Install a root CA certificate in the trust store
update-ca-certificates 說明