エラーメッセージ
remote error: tls: unknown certificate authority
Go のサーバーは「http: TLS handshake error from <client>: remote error: tls: unknown certificate authority」とログに記録します。ecdsa.com のテストでは、同じ証明書を TLS 1.3 で拒否した OpenSSL 3.5 クライアントについて、Go 1.27 のサーバーは代わりに「local error: tls: bad record MAC」と記録しました。また、Go クライアントは bad_certificate を送信します(「remote error: tls: bad certificate」と記録されます)。
Go crypto/tls — TLS alert 48 (unknown_ca) received from the peer, e.g. an OpenSSL-based client rejecting a Go server's certificate
このエラーの意味
ピアが TLS アラート 48(unknown_ca)を送信しました。受け取った証明書から、自身が信頼する CA までのチェーンを構築できなかったということです。Go サーバーのログに出ている場合は、クライアント(OpenSSL ベースのもの:curl、Python、Ruby、PHP、プロキシとしての nginx)が TLS 1.2 のハンドシェイク中にサーバーの証明書を拒否したことを意味します。Go クライアントで出ている場合は、相互 TLS でサーバーがクライアント証明書を拒否したことを意味します。
発生する理由
クライアントが発行元の CA を信頼していない
よくあるクライアントのマシンやコンテナーにインストールされていない、プライベート CA や社内 CA が該当します。
Go サーバーがリーフ証明書しか送信していない
よくあるListenAndServeTLS は、ファイルに含まれる証明書をそのまま送信します。ファイルにリーフ証明書しかなければ、クライアントはルートまでたどり着けません。
相互 TLS:サーバーがクライアントの CA を信頼していない
ときどきクライアント側でこのアラートが出た場合は、サーバーの ClientCAs にクライアント証明書の発行者が含まれていないことを意味します。
修正方法
- 1.
サーバーが返すチェーンをクライアント側から確認する
リーフ証明書しか送信されていない場合は、ファイルを修正してください。チェーンがプライベートなルートで終わっている場合は、そのルートをクライアントにインストールしてください。
bash openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:|Verify return code' - 2.
Go サーバーでフルチェーンを送信する
ListenAndServeTLS(または tls.LoadX509KeyPair)に渡す PEM ファイルに、リーフ証明書とその中間証明書を含めてください。
go // Leaf + intermediates in one file; Go sends every certificate in it srv := &http.Server{Addr: ":443"} log.Fatal(srv.ListenAndServeTLS("fullchain.pem", "server.key")) - 3.
プライベートルートをクライアントにインストールする
社内サービスの場合は、そのサーバーを呼び出すシステムとコンテナーに社内のルートを配布してください。
bash # Private CA: install the root on the clients (Debian/Ubuntu example) sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt && sudo update-ca-certificates