ClientHelloとServerHelloをJavaのDebugログで確認する

Java

SSLハンドシェイクにおいて基本となるのは、通信処理の最初に実施する『ClientHello(クライアントハロー)』と『ServerHello(サーバハロー)』です。


今回は、このSSLハンドシェイクの挙動をJavaのDebugログで出力して、ClientHelloとServerHelloの動きを確認していこうと思います。


環境情報


  • OS:Windows10
  • Java:Java1.8.0_281

SSLハンドシェイクの実験プログラム


SSLハンドシェイクを確認するために、Javaの実験プログラムを作成して、実行結果をログ出力してみます。
実験プログラムは、ポータルサイトである「Excite」にアクセスしているのみです。


import java.io.FileOutputStream;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HTTPReq {

    public static void main(String[] args){

        try {
            FileOutputStream fos = new FileOutputStream("out.txt");
            PrintStream ps = new PrintStream(fos);
            System.setOut(ps); 

            System.out.print("start: main\r\n");

            // 1回目コネクション
            URL url = new URL("https://www.excite.co.jp/");
            HttpURLConnection con = null;

            con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("POST");
            con.connect();

            int statusCode = con.getResponseCode();
            System.out.print("statusCode=" + Integer.toString(statusCode) + "\r\n");

        } catch (Exception e) {
            System.out.print("例外が発生!");
            e.printStackTrace();
        } finally {
        }
        System.out.print("end: main\r\n");
    }
}

Javaの実行バッチは以下になります。


@echo on
set CLASSPATH=.
java -Djavax.net.debug=all HTTPReq >> result.txt 2>&1

Javaのデバッグログは、debug=all」オプションを付けることで出力されます。

-Djavax.net.debug=all

Javaの標準出力は「out.txt」に出力し、デバッグログは「result.txt」に出力しています。


ClientHello


ClientHelloからServerHelloの流れは、SSLハンドシェイクの開始部分となります。
開始部分であっても、Javaのデバッグログには大量の情報が出力されます。


ClientHelloで、クライアントからサーバに対して送信するデータに以下があります。

  • SSL/TLSのバージョン
  • CipherSuiteのリスト
  • セッションID
  • ランダム値
  • 圧縮アルゴリズム
  • TLS拡張情報

実際に出力されるのは以下のような情報となります。

"ClientHello": {
  "client version"      : "TLSv1.2",
  "random"              : "XXX",
  "session id"          : "",
  "cipher suites"       : "[TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(0xC02C), ・・・]",
  "compression methods" : "00",
  "extensions"          : [
    "server_name (0)": {
      type=host_name (0), value=www.excite.co.jp
    },
    "supported_groups (10)": {
      "versions": [secp256r1, ・・・]
    },
    "ec_point_formats (11)": {
      "formats": [uncompressed]
    },
    "signature_algorithms (13)": {
      "signature schemes": [ecdsa_secp256r1_sha256, ・・・]
    },
    "signature_algorithms_cert (50)": {
      "signature schemes": [ecdsa_secp256r1_sha256, ・・・]
    },
    "extended_master_secret (23)": {
      
    },
    "supported_versions (43)": {
      "versions": [TLSv1.2, TLSv1.1, TLSv1]
    }
  ]
}

SSL/TLSのバージョンのバージョンは、クライアントで使用できるTLSバージョンをサーバに通知しています。
TLS1、1.1、1.2などがあります。


CipherSuiteのリストは、クライアントで使用できるCipherSuiteをリストとしてサーバに通知しています。
このログ以前にも様々な情報が出力されるのですが、クライアントで使用できるCipherSuiteのリストを算出し、サーバに通知します。


セッションIDはクライアント側で保持しているセッションのIDです。
複数の通信をおこなう場合、クライアントはセッションで保持している情報を使用してSSLハンドシェイクをおこないます。
セッションIDを使用した場合、SSLハンドシェイクの手順をスキップすることができます。


ServerHello


ClientHelloに対するサーバ側のレスポンスがServerHelloになります。


ServerHelloで、サーバからクライアントに対して送信するデータには以下の種類があります。


  • 合意したSSL/TLSのバージョン
  • ランダム値
  • セッションID
  • 合意したCipherSuite
  • 圧縮アルゴリズム
  • TLS拡張情報

"ServerHello": {
  "server version"      : "TLSv1.2",
  "random"              : "XXX",
  "session id"          : "YYY",
  "cipher suite"        : "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(0xC02F)",
  "compression methods" : "00",
  "extensions"          : [
    "renegotiation_info (65,281)": {
      "renegotiated connection": []
    },
    "server_name (0)": {
      
    },
    "ec_point_formats (11)": {
      "formats": [uncompressed, ansiX962_compressed_prime, ansiX962_compressed_char2]
    },
    "extended_master_secret (23)": {
      
    }
  ]
}

SSL/TLSのバージョンのバージョンは、クライアント側から提案したTLSのバージョンに対するサーバ側の返却になります。
このバージョンが一致しなければ、SSLハンドシェイクは成立しません。
サーバ側はTLS1.2で要求しているのにサーバ側がTLS1.0のみを許可している、といった場合がそのパターンになります。


合意したCipherSuiteは、クライアント側から提案したCipherSuiteのリストを受信したサーバ側が、そのリストから使用するCipherSuiteを決定します。


最終的に、ServerHelloDoneが出力されれば、ClientHelloからServerHelloの一連の動きは成功となります。


javax.net.ssl|FINE|01|main|2021-04-24 23:11:34.992 JST|ServerHelloDone.java:151|Consuming ServerHelloDone handshake message (

)