sublimer.hatenablog.com
Node.js本体のDTLS APIを使ってみた
### はじめに
Node.js 26.9.0から、Node.js本体にDTLSのAPIが実装されました。
github.com
現在は実験的なAPIという扱いで、Node.jsのビルド時にフラグを指定してビルドすることで利用可能になります。
サーバーとクライアントそれぞれのサンプルを作って動かしてみたので、動かす手順などをブログにまとめておこうと思います。
### 環境
* macOS Sequoia 15.8
* Apple clang version 17.0.0 (clang-1700.6.4.2)
### Node.jsのビルド
公式で配布されているNode.jsはDTLSを有効化せずにビルドされているため、DTLSを使うためには自前ビルドする必要があります。
ビルド手順は以下のドキュメントに書かれています。
github.com
以下のコマンドを実行すると、Node.js 26.9.0のソースコードのダウンロードとビルドができます。
今回はDTLS機能を有効化するので、`./configure` 実行時に `--experimental-dtls` を指定しました。
wget https://github.com/nodejs/node/archive/refs/tags/v26.9.0.zip
unzip v26.9.0.zip
cd node-26.9.0
./configure --experimental-dtls
make -j8
### DTLSサーバーの実装
以下のドキュメントに記載されているコードを元に、サーバーのコードを実装します。
nodejs.org
// server.js
import { listen } from 'node:dtls';
import { readFileSync } from 'node:fs';
const endpoint = listen(
(session) => {
session.onmessage = (data) => {
console.log('Received: ', data.toString());
session.send('ack');
};
session.onhandshake = (protocol) => {
console.log('Handshake Completed: ', protocol);
};
},
{
cert: readFileSync('./keys/server-cert.pem'),
key: readFileSync('./keys/server-key.pem'),
port: 4433,
},
);
console.log('DTLS server listening on ', endpoint.address);
今回実装したコードは、DTLSで受信したデータをログ出力し、その後で `ack` という文字列を返すだけのシンプルなものです。
### DTLSクライアントの実装
クライアント側も同様に、以下のドキュメントに記載されているコードを元に実装します。
nodejs.org
// client.js
import { connect } from 'node:dtls';
import { readFileSync } from 'node:fs';
const session = connect('127.0.0.1', 4433, {
ca: [readFileSync('./keys/ca-cert.pem')],
});
const { protocol } = await session.opened;
console.log('Handshake Completed: ', protocol);
const { resolve: messageReceived, promise: messageReceivedPromise } =
Promise.withResolvers();
session.onmessage = (data) => {
console.log('Received: ', data.toString());
messageReceived();
};
session.send('Hello');
await messageReceivedPromise;
await session.close();
process.exit(0);
`Hello` という文字列をサーバーに送信し、サーバーからメッセージが返ってくるのを待機した後、メッセージが受信できたら接続を閉じてからプロセスを終了するようになっています。
### 証明書の作成
DTLSの暗号化で利用するための証明書を作成します。
今回は、自前で認証局(CA)を作ってそこから証明書の払い出しをします。
以下のコマンドを実行して、サーバー用の証明書と秘密鍵、CA証明書を作成します。
mkdir keys
cd keys
openssl genrsa -out ca-key.pem 2048
openssl req -x509 -new -key ca-key.pem -sha256 -days 3650 \
-subj "/CN=DTLS Example CA" -out ca-cert.pem
openssl genrsa -out server-key.pem 2048
openssl req -new -key server-key.pem -subj "/CN=localhost" -out server.csr
echo 'subjectAltName=DNS:localhost,IP:127.0.0.1' > san.cnf
openssl x509 -req -in server.csr \
-CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial \
-days 365 -sha256 -extfile san.cnf -out server-cert.pem
### 動作確認
サーバーとクライアントをそれぞれ実行して動作確認します。
デフォルトではDTLSの機能は有効化されないため、Node.js実行時に `--experimental-dtls` オプションを付与する必要があります。
* server
./node-26.9.0/node --experimental-dtls server.js
(node:4702) ExperimentalWarning: dtls is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
DTLS server listening on { address: '0.0.0.0', family: 'IPv4', port: 4433 }
Handshake Completed: DTLSv1.2
Received: Hello
* client
./node-26.9.0/node --experimental-dtls client.js
(node:4735) ExperimentalWarning: dtls is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Handshake Completed: DTLSv1.2
Received: ack
DTLS 1.2が使われ、正常にメッセージのやり取りができたことがわかります。
また、Wiresharkでパケットキャプチャをすると、実際に通信が行われたことも確認できます。
### 具体的なユースケースについて
今回、実験的なAPIとしてNode.jsでDTLSが利用できるようになりましたが、具体的なユースケースはあまり思いつきませんでした。
WebRTCではDTLSが使われておりNode.jsの公式ドキュメントでもDTLS-SRTPのコード例が載っていますが、WebRTCを構成する他のプロトコルやメディア処理はNode.js本体には実装されていないため、直近でNode.jsが公式にWebRTCに対応する可能性は低いように思います。
nodejs.org
実装時のPRを読むと、「QUIC対応の合間に作ってみた」旨が書かれており、「OpenSSLに既にDTLSの機能があるので、それを呼び出す形で実験的に対応する」ということで実装されたようです。(余談ですが、実装者の方はCloudflareの中の人のようです)
github.com
PRではIoTで利用されるCoAPというプロトコルが挙げられているので、もしかしたらIoT製品の通信で利用される場面があるのかもしれません。
なお、Node.jsでのDTLS対応については2015年に要望が出されており、こちらは2018年にクローズされています。
github.com
2026年の2月に新しく以下のissueが作成され、今回それが実装されたということのようです。
github.com
### おわりに
Node.js 26.9.0から利用できるようになったDTLSを試してみました。
なお、Node.js 26.10.0では追加の変更が行われ、より多くのオプションが指定できるようになっています。
github.com
また、APIのステータスも「Stability: 1 - Experimental」から「Stability: 1.1 - Active Development」に変更されています。
現在はフラグ付きでの自前ビルドと実行時のフラグ指定の両方が必要なので将来的に正式化されるかどうかは分かりませんが、今後の状況は注視していきたいと思います。
### 参考サイト
* DTLS | Node.js v26.9.0 Documentation
* src,lib: implement experimental DTLS API by jasnell · Pull Request #63182 · nodejs/node · GitHub