DTLSにコネクションIDを導入する提案仕様

DTLSにコネクションIDを導入する「The Datagram Transport Layer Security (DTLS) Connection Identifier」という提案が出ています。

DTLS1.3の議論を進める中で出てきたトピックであり、既にWG Draft になっています。

DTLSとセッション

DTLSはUDPのようなコネクションのないトランスポート上で暗号化された通信を行うためのプロトコルです。下位層にコネクションのないトランスポートを使っている一方で、現在のDTLSは送信元IP・送信先IP・送信元ポート番号・送信先ポート番号でDTLSのセッションを識別しています。

そのため、それらのうちどれかが変わってしまうと、鍵交換を含むハンドシェイクを初めからやり直す必要があります。特にIoTデバイスなどが普及していく中で、移動する端末や通信頻度が低いもの(NATリバインディングが起こる)は容易に起こるでしょう。さらにそういった端末はリソースが潤沢でない可能性があります。

DTLS Connection Identifier では、DTLSにコネクションIDを導入しIPやポート番号が変わっても通信を維持できるようにします。これにより、ハンドシェイクを1からやり直す手間が省けます。

DTLS Connection Identifier

The Datagram Transport Layer Security (DTLS) Connection Identifier」では、DTLS1.2とDTLS1.3両方について対応します。

この提案仕様では、DTLSに以下を追加します

  • connection_id拡張:ClientHelloとServerHelloで使われる、コネクションIDの使用をネゴシエーションするための拡張
  • RequestConnectionId:DTLS1.3で相手にコネクションIDを要求するメッセージ
  • NewConnectionId:DTLS1.3で相手にコネクションIDを通知するメッセージ (コネクションIDをすぐに使うか、予備か指定可)
  • Record Layer Extensions:レコードに現在のコネクションIDを指定できるように変更される。

例えば、DTLS1.2では、以下のようにcidが追加されます。

     struct {
        ContentType type;
        ProtocolVersion version;
        uint16 epoch;
        uint48 sequence_number;
        opaque cid[cid_length];               // New field
        uint16 length;
        select (CipherSpec.cipher_type) {
           case block:  GenericBlockCipher;
           case aead:   GenericAEADCipher;
        } fragment;
     } DTLSCiphertext;

コネクションIDの使用

DTLS1.3及びDTLS1.2で微妙に手順は異なるが、ハンドシェイク中にconnection_id拡張でコネクションIDの使用が合意されると、以降コネクションIDが含まれたメッセージを交換するようになる。

以下は、DTLS1.2の例である
f:id:ASnoKaze:20171230233015p:plain