nodejs / nodejs/node

TLS verification fails for IPv6 IP subjectAltName in v22.23.0 and v24.17.0

オープン
#64,032 コメント 0 件 リアクション 3 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

tls
主要言語
JavaScript
スター
122k
フォーク
37.3k
平均マージ
4日 2時間
マージ済み PR(30日)
283

説明

Version

22.23.0, 24.17.0

Platform
Linux Debian 12 amd64, Linux Debian 12 arm64
Subsystem

SSL/TLS tls.connect()

What steps will reproduce the bug?

After update to 22.23.0, changes seem to have impacted TLS host verification for certificates created with IPv6 numeric address as the X509v3 Subject Alternative Name: IP Address field. This may be related recent changes "tls: normalize hostname for server identity checks" and "tls: fix case-sensitive SNI context matching"

  • Create a TLS CA certificate for use to sign server certificates and use as client's CA certificate.
basicConstraints = critical,CA:true,pathlen:0
keyUsage = cRLSign, keyCertSign
  • Create TLS server certificate with numeric IPv6 SAN.
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
[alt_names]
IP.1=192.168.34.55
IP.2=fc00:34::55
  • On one computer, start openssl s_server
openssl s_server -accept 8002 -cert my-server-cert.pem -key my-server-key.pem -cert_chain my-CA-cert.pem
  • On second computer, run code to reproduce
// open-socket.js
'use strict';

const tls = require('tls');
const fs = require('fs');

const socket = tls.connect({
  host: 'fc00:34::55',
  port: 8002,

  ca: fs.readFileSync('my-CA-cert.pem'),

  // true: Certificate is only accepted if IP address matches certificate X509v3 Subject Alternative Name: "IP address" value.
  rejectUnauthorized: true

  // Do not include "servername" property. Server name for the SNI (Server Name Indication) must not an IP address (Node.js docs, tls.connect options)

}, () => {
  console.log('TLS connected');
  console.log('authorized:', socket.authorized);
  console.log('authorizationError:', socket.authorizationError);
  console.log('Sending: "This is a test message.\\n"');
  socket.end('This is a test message.\n');
});

socket.on('error', (err) => {
  console.error('TLS socket error:', err.message);
  process.exitCode = 1;
});

socket.on('close', () => {
  console.log('TLS socket closed');
});
How often does it reproduce? Is there a required condition?

Each time tls.connect( ... ) is called using certificate with numeric IPv6 IP SAN.

What is the expected behavior? Why is that the expected behavior?

Using previous version of Node v22.22.3 or v24.16.0, connect succeeds without error

  • Client opens socket and sends test message to server
$ nvm use 22.22.3
Now using node v22.22.3 (npm v11.15.0)

$ node open-socket.js 
TLS connected
authorized: true
authorizationError: null
Sending: "This is a test message.\n"
TLS socket closed
  • Server shows test message "This is a test message", no errors
openssl s_server -accept 8002 -cert my-server-cert.pem -key my-server-key.pem -cert_chain my-CA-cert.pem

This is a test message.
DONE
shutting down SSL
CONNECTION CLOSED
What do you see instead?

Using current Node v22.23.0 or v24.17.0 TLS verification fails.

  • Client
$ nvm use 22.23.0
Now using node v22.23.0 (npm v10.9.8)

$ node open-socket.js 
TLS socket error: Hostname/IP does not match certificate's altnames: Host: fc00:34::55. is not cert's CN: my-server-CN
TLS socket closed

$ nvm use 24.17.0
Now using node v24.17.0 (npm v11.13.0)

$ node open-socket.js 
TLS socket error: Hostname/IP does not match certificate's altnames: Host: fc00:34::55. is not cert's CN: my-server-CN
TLS socket closed
  • Server
openssl s_server -accept 8002 -cert my-server-cert.pem -key my-server-key.pem -cert_chain my-CA-cert.pem

ERROR
20D0199D7F000000:error:0A000126:SSL routines::unexpected eof while reading:../ssl/record/rec_layer_s3.c:698:
shutting down SSL
CONNECTION CLOSED

ERROR
20D0199D7F000000:error:0A000126:SSL routines::unexpected eof while reading:../ssl/record/rec_layer_s3.c:698:
shutting down SSL
CONNECTION CLOSED
Additional information

The strongest clue is the period after IPv6 address in the error message, possible domain name syntax.

Only IPv6 is impacted. Certificates with numeric IPv4 IP SAN work as expected.

These are example decoded TLS certificates

$ openssl x509 -in my-CA-cert.pem -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            4f:65:a0:84:24:4a:ac:40:66:c5:fc:e3:19:4c:ae:7c:9f:73:ee:f5
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O = my-org-name, CN = my_CA_CN
        Validity
            Not Before: Jun 20 14:22:52 2026 GMT
            Not After : Jun 20 14:22:52 2027 GMT
        Subject: O = my-org-name, CN = my_CA_CN
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:e3:21: ...
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                86:9F:90:CD:0F:45:3B:83:E2:00:64:A5:06:94:7D:0A:FD:00:E9:3E
            X509v3 Authority Key Identifier: 
                86:9F:90:CD:0F:45:3B:83:E2:00:64:A5:06:94:7D:0A:FD:00:E9:3E
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 Key Usage: 
                Certificate Sign, CRL Sign
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        d4:f3:8c: ...


$ openssl x509 -in my-server-cert.pem -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            0a:52:54:3a:67:b7:46:f4:57:c8:03:e5:10:0d:38:4e:58:39:c3:b7
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O = my-org-name, CN = my_CA_CN
        Validity
            Not Before: Jun 20 14:22:52 2026 GMT
            Not After : Jun 20 14:22:52 2027 GMT
        Subject: O = my-org-name, CN = my-server-CN
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:e8:4c:be: ... 
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Authority Key Identifier: 
                86:9F:90:CD:0F:45:3B:83:E2:00:64:A5:06:94:7D:0A:FD:00:E9:3E
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Key Usage: 
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Subject Key Identifier: 
                24:9A:3B:F6:DC:20:47:69:9C:AE:51:6F:E6:B5:1E:3D:45:E0:50:22
            X509v3 Subject Alternative Name: 
                IP Address:192.168.34.55, IP Address:FC00:34:0:0:0:0:0:55
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        48:54:8a:85: ...

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

open-socket.js の再現と tls.connect() のホスト検証パスから始め、影響を受ける Node.js バージョンと動作するバージョンを比較します。数値形式の IPv6 Subject Alternative Name がどのように照合されるかを追跡し、報告された証明書のカバレッジを追加して、authorized を true に設定した状態で接続が成功することを確認します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
javascript, node.js
領域
networking, security
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
52/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。