WiresharkでTLS Layerのパケットを調べていた時に、表示されていたプロトコルが何を指しているのか疑問になったので調べてみた。
具体的には以下に表示されている部分である。HTTPでないプロトコルだと思っていたけれどhttp-over-tlsと表示されていたので、HTTP??と思ってしまった。Record部分は、暗号化されていて読めないはずなのに何故HTTPと分かったのか?、という疑問である。
ポート番号で判断している?
もし、パケットの中身を見てHTTPと判断しているのならば、ポート番号を変えてアクセスしてもhttp-over-tls
と表示されるはずである。
ということで試してみた。
Dst Portを8443としてみた。ApacheでListen 8443 httpsと設定し自己署名証明書をセットしてある。
結果、http-over-tls
と表示されてはいなかった。実際には、Webブラウザで、Webページhttps://<address>:8443/
にアクセスしているので、HTTPプロトコルでデータを送受信しているはずである。このことから、Wiresharkはポートのみで判断して表示しているのではと推測できる。
Wiresharkのプロトコル解釈に関する記事
検索するとPortで判断しているような記述があり、その線が濃厚そうだ。
- https://serverfault.com/questions/263530/how-can-i-filter-https-when-monitoring-traffic-with-wireshark/263533
- https://support.f5.com/csp/article/K69625939
- https://stackoverflow.com/questions/50085714/wireshark-is-not-displaying-http-and-https-packets
Wiresharkのソースはどうなってる?
念のためソースも少し確認しておく。大まかな予想をつけてソースを眺めてみる。以下の箇所がTLSデータの情報表示部分だと思われる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
case SSL_ID_APP_DATA: { dissector_handle_t app_handle; /* show on info column what we are decoding */ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Application Data"); /* app_handle discovery is done here instead of dissect_ssl_payload() * because the protocol name needs to be displayed below. */ app_handle = session->app_handle; if (!app_handle) { /* Unknown protocol handle, ssl_starttls_ack was not called before. * Try to find a port-based protocol and use it if there is no * heuristics dissector (see process_ssl_payload). */ app_handle = dissector_get_uint_handle(ssl_associations, pinfo->srcport); if (!app_handle) app_handle = dissector_get_uint_handle(ssl_associations, pinfo->destport); } proto_item_set_text(ssl_record_tree, "%s Record Layer: %s Protocol: %s", val_to_str_const(version, ssl_version_short_names, "SSL"), val_to_str_const(content_type, ssl_31_content_type, "unknown"), app_handle ? dissector_handle_get_dissector_name(app_handle) : "Application Data"); proto_tree_add_item(ssl_record_tree, hf_tls_record_appdata, tvb, offset, record_length, ENC_NA); |
プロトコルのTreeの部分に表示されている%s Record Layer: %s Protocol: %s
の部分が該当箇所であろう。http-over-tls
の表示箇所であるdissector_handle_get_dissector_name
を追ってみると、以下のようになっており、app_handleの変数nameのポインタを返している。
1 2 3 4 5 6 7 8 9 |
/* Get a dissector name from handle. */ const char * dissector_handle_get_dissector_name(const dissector_handle_t handle) { if (handle == NULL) { return NULL; } return handle->name; } |
app_handleは、以下の部分で設定されているようである。
1 2 3 4 5 6 7 8 9 10 |
/* app_handle discovery is done here instead of dissect_ssl_payload() * because the protocol name needs to be displayed below. */ app_handle = session->app_handle; if (!app_handle) { /* Unknown protocol handle, ssl_starttls_ack was not called before. * Try to find a port-based protocol and use it if there is no * heuristics dissector (see process_ssl_payload). */ app_handle = dissector_get_uint_handle(ssl_associations, pinfo->srcport); if (!app_handle) app_handle = dissector_get_uint_handle(ssl_associations, pinfo->destport); } |
pinfo->srcport
、pinfo->destport
の値をもとにapp_handleを決定しているように見える。portの値をもとに決定しているとすると、ここに443の数値を入れると、http-over-tls
となるはず。
以下のようにソース修正しビルドしてみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* app_handle discovery is done here instead of dissect_ssl_payload() * because the protocol name needs to be displayed below. */ app_handle = session->app_handle; if (!app_handle) { /* Unknown protocol handle, ssl_starttls_ack was not called before. * Try to find a port-based protocol and use it if there is no * heuristics dissector (see process_ssl_payload). */ app_handle = dissector_get_uint_handle(ssl_associations, pinfo->srcport); if (!app_handle) app_handle = dissector_get_uint_handle(ssl_associations, 443); // destを443にする } proto_item_set_text(ssl_record_tree, "%s Record Layer: %s Protocol: %s dst = %d src = %d", val_to_str_const(version, ssl_version_short_names, "SSL"), val_to_str_const(content_type, ssl_31_content_type, "unknown"), app_handle ? dissector_handle_get_dissector_name(app_handle) : "Application Data (unknown)", pinfo->destport, pinfo->srcport ); |
上記ではDestPortを443にしている。結果は以下のとおりとなった。DestPortは60881であるがhttp-over-tls
と表示されている。SrcPortのケースも同様に443とすると、http-over-tls
と表示されることが分かった。
TLSのレコードプロトコル
念のためTLSのレコードプロトコル構造を確認しておく。上位レイヤであるHTTPのヘッダとボディのデータはペイロードに含まれる。
- TCPヘッダ
- Content-Type(1 Byte)
- Version(2 Bytes)
- Length(2 Bytes)
- ペイロード
- MAC
まとめ
WiresharkのTLSレコードのhttp-over-tlsの表示は、SrcまたはDestのPortを見て決定している。
ただし、session->app_handle
が決定済みのケースは、今回追っていない。
参考
- https://datatracker.ietf.org/doc/html/rfc5246#page-15
- https://www.ipa.go.jp/security/rfc/RFC5246-06JA.html
- https://milestone-of-se.nesuke.com/nw-basic/tls/https-structure/
- wiresharkのprotocol解釈
コメント