通信時に利用されるSSL/TLSバージョンと暗号仕様の確認方法

## 調査対象
お題は
「Db2クライアントとDb2サーバ間でのSSL/TLS通信時に使われるTLSバージョンとCipher Spec(暗号仕様)の調べ方」
です。

「どのTLSバージョン/暗号仕様が利用可能であるか、どれだけのバリエーションが提供されるか」は利用環境や構成パラメーターによって決まる要素ですが、複数の選択肢が存在するうち、実際の通信時にどの暗号仕様が使われるのかは、クライアント-サーバー間で通信を確立する時点で決まります。

まずクライアント側が利用可能な暗号仕様を提示し、それを受けたサーバー側が、提示されたうち、サーバー自身でも利用可能なものを選択します。(下図の黄色部分：(1)-(3))

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/17494186-3403-46cc-b776-bfd254b26071.png)

 ※図 引用元：[SSL/TLS暗号化ガイドライン　v3.1](https://www.ipa.go.jp/security/crypto/guideline/gmcbt80000005ufv-att/ipa-cryptrec-gl-3001-3.1.1.pdf)

<br>

では、実際にどの暗号仕様が使われているかを知りたい場合、どうしたらよいか？

Db2 JDBCクライアントの場合はパケットトレースしか確認方法が無さそうです。
確認ツールとしては、利用可能であれば、Wiresharkが一目瞭然でわかりやすいです。



## 環境・構成
以下の構成にて確認。
 * DBクライアント
     * Ubuntu22.04 (WSL2)
     * Semeru Runtime (Java runtime) 21.0.4.1
     * WebSphere Liberty (※構成ファイルは末尾に記載)
     * Db2 JCC(JDBC) Driver 4.34.30
 * DBサーバー
     * RHEL 9.4
     * Db2 12.1.1

以下の状態となっていることを前提とします。
 * クライアント - サーバ間のSSL/TLS接続構成が済んでいること
 * 疎通確認が出来ていること


## 手順（概要）

以下の手順で確認を行います

Step1. ネットワークインターフェース(NIC)の確認
Step2. tcpdumpコマンドによるパケットキャプチャ取得
Step3. Wiresharkによる確認

※ Step3.は、tcpdump -r でテキスト化することでも代替可能


## 手順（Step by Step）
### Step1. ネットワークインターフェース(NIC)の確認
パケットキャプチャ取得にあたって大事なこととして、取得対象を極力絞り込みたいです。
標準的なWindows上に構成したWSL2のUbuntu環境では、eth0とloがあります。
今回は、他サーバ宛通信のためeth0が使われると思われますが本当にそうであるか、事前に確認します。

前提として、今回はクライアント側でパケットキャプチャを行います。
(サーバー側で取得してもOK)

**目的のサーバ宛に通信を行う**
今回利用するのはWebアプリのためブラウザから1回JDBCアプリを実行し、クライアント(Liberty)-サーバー(Db2)間通信を確立させておきます。

**利用されるネットワークインターフェースを確認する**

DBアクセスアプリの実行完了後、クライアント上でnetstatコマンドを実行し、ESTABLISHEDのエントリーを探します。

DBサーバーのIPアドレス、ポート番号を含むエントリーを探します。(今回は2行出力あり)
同じ行のひと列左側にあるのが、クライアントが利用するIPアドレスとポート番号の情報。

```
# netstat -ano | grep -i establ
tcp6       0      0 ::1:34472               ::1:19080               ESTABLISHED オフ (0.00/0/0)
tcp6       0      0 ::1:19080               ::1:34472               ESTABLISHED キープアライブ (7195.71/0/0)
tcp6       0      0 172.24.203.74:35358     10.44.51.139:25123      ESTABLISHED キープアライブ (0.63/0/0)
tcp6       0      0 ::1:19080               ::1:34464               ESTABLISHED キープアライブ (7194.10/0/0)
tcp6       0      0 ::1:34464               ::1:19080               ESTABLISHED オフ (0.00/0/0)
tcp6       0      0 172.24.203.74:35370     10.44.51.139:25123      ESTABLISHED キープアライブ (0.86/0/0)
```

次に、DBサーバーとの通信に利用されている172.24.203.74 というアドレスは、クライアントのどのネットワークインターフェースについているものか、確認。

```
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet 10.255.255.254/32 brd 10.255.255.254 scope global lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1320 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:7f:4f:7c brd ff:ff:ff:ff:ff:ff
    inet 172.24.203.74/20 brd 172.24.207.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fe7f:4f7c/64 scope link
       valid_lft forever preferred_lft forever
```

予想通りeth0でした。

ということで、パケットキャプチャ時には以下の情報をオプションに指定することで、取得するパケット量の絞り込みが出来そうです。

| tcpdumpオプション |指定する値 | 意味 |
|:-|:-|:-|
| -i  | eth0  | キャプチャ対象のネットワークインターフェース  |
|-v port   | 25123  | キャプチャー対象のポート  |



### Step2. tcpdumpコマンドによるパケットキャプチャ取得

以下コマンドを実行して以下の状態になったら準備完了。

```
# tcpdump -i eth0 -w test_`date "+%Y%m%d_%H%M%S"`_tcpdump.cap -v port 25123
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
Got 0

```

通信をキャプチャしたいアプリケーションを実行します。
アプリ実行が完了したことを確認したら、Ctrl-c で tcpdump を終了します。

```
# tcpdump -i eth0 -w test_`date "+%Y%m%d_%H%M%S"`_tcpdump.cap -v port 25123
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C43 packets captured
43 packets received by filter
0 packets dropped by kernel

```

-w オプションで指定したファイル名で、キャプチャファイルが生成されていることを確認します。
```
# ls -ltr . | grep tcpdump
-rw-r--r-- 1 tcpdump tcpdump   13126  5月 12 16:11  test_20250512_161109_tcpdump.cap
```


### Step3. Wiresharkによる確認

Linuxのtcpdumpコマンドで取得されたcapファイルを、Windowsに導入したWiresharkで開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/fd8b0437-1261-4cd9-84c6-f9e1f0549075.png)

Protocol列にTLSv1.3と表示されていることから、この例ではTLSv1.3で通信が行われていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/7606a767-e747-4483-a668-75ad7f681e7c.png)


## 確認結果：Db2 V12.1.1クライアント - サーバー間SSL/TLS通信時に使用されるCipher Spec

Client Helloには、クライアント側が利用可能な暗号仕様(Cipher Spec)が提示されます。
その返信としてサーバーから返されるServer Helloに、今回の通信時に利用するとサーバーが決定したCipher Specの情報が含まれます。

**Client Hello**

利用可能なCipher Suitesとして37 suitesが提示されています。
37 suitesのうち上3つが、TLS 1.3のもの。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/2bc97634-53cb-4cbf-a983-1abcd33f940e.png)




**Server Hello**

クライアント側が提示したTLS 1.3のsuitesのうち1つが選択されていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/b0787c6b-a231-4c9f-9679-1f6245764711.png)


## 補足：server.xml
今回の確認に使用したLibertyサーバー構成は以下の通り。

平常運用においては不要なJDBCトレースを取得しているのはCipher Spec,TLSバージョンなどの情報がJDBC(JCC)トレースに出ているかもしれないと期待したためですが、記録されていませんでした。

下記構成には含みませんがLibertyのトレースも仕掛けてはみました。しかしJDBCトレース同様、情報は得られませんでした。

```xml: server.xml抜粋(JDBC接続定義のみ)
<!-- DataSource Conig(Db2)  -->
<library id="DB2JCC4Lib">
  <fileset dir="${shared.resource.dir}/db2" includes="db2jcc4.jar"/>
</library>

<!-- Declare the runtime database -->
<dataSource id="Db2-DS1" jndiName="jdbc/sample">
 <jdbcDriver libraryRef="DB2JCC4Lib"/>
 <properties.db2.jcc
         databaseName="nocon"
         driverType="4"
         serverName="db2.myssl-test.com"
         portNumber="25123"
         user="my1211"
         password="xxxxxxxx"
         sslConnection="true"
         sslTrustStoreLocation="${shared.resource.dir}/db2/myTrustStore.jks"
         sslTrustStorePassword="xxxxxxxx"
         traceLevel="-1"
         traceFile="/work/logs/jdbctrc/trc.log"/>

</dataSource>
```