はじめに
この記事では、JavaアプリケーションのHTTPS通信(TLS)における下記要素を解析する手順を紹介しています。
- URL
- Header
- Body
これらの要素を解析する以下2つの方法のうち、本記事では後者の方法を紹介しています。
- MockServerを使う方法
- jSSLKeyLog.Jarを使う方法
前者の方法については次の記事で関連情報を紹介していますのでご参考いただければと思います。
MockServerを利用して光の速さでDebug用のProxyサーバーを作ってみる
jSSLKeyLog.Jarとは?
jSSLKeyLog.jarは、JavaプログラムのSSL/TLS通信で使われる暗号鍵情報をログファイルに記録するためのJavaエージェントです。これにより、WiresharkなどのツールでSSL通信の復号が可能になります。主にJavaアプリケーションの通信解析やデバッグに使われます。
jSSLKeyLog.Jarを光の速さで使ってみる
Javaのサンプルコードと動作確認
jSSLKeyLog.jarを利用する前に、動作確認用のJavaコードを実行して正しく動作するか確認します。
次のコードではhttpbin.orgを利用してPOSTリクエストとしてRequest Body {"TestKey":"TestValue"} を送信しています。
なお、今回はtestディレクトリを作成して動作確認をしています。
mkdir test
cd test
cat << ___EOF___ > TestHTTPS.java
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class TestHTTPS {
public static void main(String[] args) throws Exception {
HttpURLConnection connection = (HttpURLConnection) new URL("https://httpbin.org/post").openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setDoOutput(true);
try (OutputStream os = connection.getOutputStream()) {
os.write("{\"TestKey\":\"TestValue\"}".getBytes("UTF-8"));
}
System.out.println("response code: \n" + connection.getResponseCode());
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) sb.append(line).append(System.lineSeparator());
System.out.println("response body: \n" + sb);
}
}
}
___EOF___
javac TestHTTPS.java
java TestHTTPS
jSSLKeyLogを使った解析
次の手順で解析を進めてゆきます。
-
testディレクトリで次のtcpdumpコマンドでパケットキャプチャの取得を開始しておきます。
sudo tcpdump -w jSSLKeyLogTest.pcap -
testディレクトリで次のコマンドを実行してjSSLKeyLog.Jarを取得、解凍します。
wget https://github.com/jsslkeylog/jsslkeylog/releases/download/v1.4.0/jSSLKeyLog-1.4.zip
unzip jSSLKeyLog-1.4.zip -
testディレクトリで次のコマンドを実行してJavaコードの実行時にSSL/TLS通信で使われる暗号鍵情報をログファイルに記録します。
java -javaagent:jSSLKeyLog.jar=jSSLKeyLog.log TestHTTPS -
Step1で実行していたtcpdumpコマンドをCtrl+Cで停止します。
-
Wiresharkを起動してtestディレクトリに出力されているファイル jSSLKeyLogTest.pcap を読み込ませます。
-
Wiresharkのメインメニューより [編集] > [設定] を選択、更に設定画面の左側のツリーより [Protocols] > [TLS] を選択して次のようにtestディレクトリに出力されているファイル jSSLKeyLog.log を指定します。

-
Wiresharkでhttpbin.orgとの通信を探しやすいようにフィルタを指定して(nslookupで取得したIPアドレスをip.addr == XXX or ip.addr == ...の形式で指定)、Protocol=HTTP のレコードを右クリック [追跡] > [HTTPストリーム] を選択します。

jSSLKeyLog.Jarの利用方法
java -javaagent:jSSLKeyLog.jar=jSSLKeyLog.log TestHTTPS のように、ダウンロード・解答した jSSLKeyLog.jar のファイルパス、および出力するログファイル(暗号鍵情報、コマンド例では jSSLKeyLog.log)のファイルパスを指定します。
紹介したコマンド例ではファイル名のみ指定しているため相対パスとして扱われ、カレントディレクトリであるtestディレクトリ上のファイルが利用されています。
おわりに
手元にデバッグ対象のJavaコードがあっても、コードの変更や再コンパイルには抵抗を感じる事ってありますよね(技術的にもコスト的にも)。そのような場合でも、今回ご紹介した手順なら比較的心理的なハードルが低く、デバッグを進めやすいと思います。ぜひお試しくださいませ。

