できない.dev

Node.js で fetch が「self-signed certificate in certificate chain」で接続できない

Node.js 組み込み fetch は OpenSSL の信頼ストアで TLS チェーンを検証するため、社内 CA や自己署名証明書を挟んだ環境では接続できません。
`NODE_EXTRA_CA_CERTS` で追加 CA を読み込ませるのが安全な対処で、`NODE_TLS_REJECT_UNAUTHORIZED=0` は検証を完全に切ってしまうため本番では使いません。

#fetch#tls#certificate#undici

公開:

要約

Node.js 組み込み fetch は OpenSSL の信頼ストアで TLS チェーンを検証するため、社内プロキシや MITM 装置で挿入された自己署名 CA を信頼していない環境では self-signed certificate in certificate chain で接続できません。NODE_EXTRA_CA_CERTS で追加 CA を読み込ませるのが安全な対処で、NODE_TLS_REJECT_UNAUTHORIZED=0 は検証を完全に切ってしまうため本番では使いません。

よくある原因

  1. 社内プロキシや MITM 装置が挿入する自己署名 CA が Node.js の信頼ストアに入っていない
  2. サーバが中間 CA を返しておらず、不完全なチェーンになっている
  3. Node.js は独自の CA バンドルを内蔵し、OS の信頼ストアを自動では参照しない
  4. Docker / CI で /etc/ssl/certs をマウントしていない、または ca-certificates が古い

解決策

1. CA を環境変数で追加する(推奨)

社内 CA の PEM ファイルを NODE_EXTRA_CA_CERTS で指定すると、Node 内蔵バンドルに 追加 して信頼します(公式ドキュメント)。

export NODE_EXTRA_CA_CERTS=/etc/ssl/private/corp-root-ca.pem
node app.js

複数 CA が必要なら同じ PEM ファイル内に連結します。

2. OS の信頼ストアを使う

Node.js 22 以降では --use-system-ca で OS の信頼ストアを参照できます。
社員 PC に CA が配布されている環境ではこちらが楽です。

node --use-system-ca app.js
# あるいは
NODE_OPTIONS="--use-system-ca" node app.js

3. undici Agent で CA を渡す

特定のリクエストだけ別 CA を使いたい場合は undiciAgent を組み立てて fetch に渡します。

import { Agent, fetch } from "undici";
import { readFileSync } from "node:fs";
 
const agent = new Agent({
  connect: { ca: readFileSync("./corp-ca.pem") },
});
 
const res = await fetch("https://internal.example.com/", { dispatcher: agent });

4. 開発検証時のみ検証を切る

NODE_TLS_REJECT_UNAUTHORIZED=0 node debug.js

このフラグはプロセス全体で TLS 検証を無効化するため、CI / 本番では使わないでください。process.env への直接代入も避け、コマンドラインから一時的に渡します。

この記事は役立ちましたか?