連載「wolfの実力」 第三回:DTLSの実力(その1 DTLSの動作)

これまでTLSの実力についてみてきましたが、ここで少し寄り道をしてTLSの兄弟分であるDTLS(Datagram Transport Layer Security) について紹介することにします。DTLSはご存じのようにUDP(User Datagram Protocol)のセキュリティを実現するためのトランスポート層のプロトコルです。UDPはTCPのような接続の概念がなく、単純にパケットを送受することができる軽量で簡単に使えるプロトコルとして広く使われてきましたが、この分野でも本格的な応用ではセキュリティが求められることも多々あります。そのような場合に活躍するのがDTLSです。

とはいえ、DTLSについてはTLSに比べるとなじみの少ない方も大勢おられるかと思います。連載枠を二回にわけて、今回その1はDTLSのしくみ、動作について簡単に紹介して、次回その2でパフォーマンなど実力について見ていくことにします。

IETFでのDTLSの標準化は当初TLSとは比較的独立に行われていたのですが、最近はTLSと歩調をあわせるようになってきています。DTLS1.0の次の検討ではTLS1.2と歩調を合わせるために、プロトコルのバージョン名も一つスキップしてDTLS1.2としています。IETFのワーキンググループでは次のバージョンDTLS1.3の内容が議論されていますが、DTLS1.3の内容もすでに標準が発行しているTLS1.3で実現した多くの強化、改善が取り込まれていく見込みです。とはいえ、残念ながらDTLS1.3についてはまだ不確定要素も多くあるので、今回はすでに広く使われておりwolfSSLでも利用可能なDTLS1.2に基づいて紹介していくことにします。

UDPは軽量のプロトコルである一方で、パケットロスや転送順序の保証がなかったりといった暗号処理には少々やっかいな問題をかかえています。そこで、ハンドシェークの間だけはDTLSの処理の下層部分でパケットロスや順序保障といった処理を行わせています。

【図1 DTLSプロトコルの処理】

DTLSではそのような管理の上にセキュリティプロトコルを実現します。一方、DTLSのプロトコル自身はTLSによく似たプロトコルになっています。TLSと同様に通信ノードの役割はクライアントとサーバに分かれていて、接続の概念もTLSと同様です。DTLSの通信はクライアントからの接続要求からはじまり、クライアントとサーバの間で一連のハンドシェークが行われ安全な接続を確立し、実際のアプリケーションデータの転送が行います。

【図2 wolfSSLのAPIを使ったDTLSの概要】

図2は、アプリケーションプログラムでDTLSの通信の実現の概要をwolfSSLのAPIで示したものです。このように、DTLSのAPIは最初のコンテクストを確保するところでDTLSを指定する以外、ほとんどTLS向けのAPIの使い方と同じとなっています。1つ違う点は、UDPの場合、接続の概念がないため通信の相手を何等かの形でwolfSSLライブラリ側に伝えなくてはならない点です。サーバ側ではクライアント側からClientHelloのパケットを受け取ったときはじめて通信相手が確定します。そのためUDPレイヤーの受信(recvfrom)をMSG_PEEKモードで受信して、そのあとハンドシェークを行うクライアントのアドレスをwolfSSLライブラリに登録する必要があります。これはwolfSSL_dtls_set_peerないしBSD Socketの場合にはconnectにて行います。クライアント側ではwolfSSL_dtls_set_peerで接続したいサーバのアドレスを登録します。

【図3 DTLSパケットの様子】

図3では、パケットキャプチャを使ってDTLSの簡単な通信の様子を見てみました。

DTLSもTLSと同様にアプリケーションデータの送受信に先立って、安全な接続のためのハンドシェークが行われていることがわかります。TLSと異なるのは、DoS攻撃の防衛のために最初のClientHelloに対して、HelloVerifyRequestと呼ばれるレコードでサーバからクライアントに対してクッキーが渡され、クライアントはこれを以後の通信で引き継がないといけないようになっている点です。ハンドシェークのあとは暗号化されたアプリケーションデータの通信が行われます。この部分はアプリケーションの必要に応じて、必要なレコードを必要な回数往復させることができます。

では、次回はDTLSの通信をベンチマークしてみることにしましょう。

連載「WOLFの実力」を最新版から続けて読む
第一回 SP最適化でハンドシェイク所要時間を大幅削減
第二回:データ転送速度をさぐる