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データの情報表示部分だと思われる。
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のポインタを返している。
/* 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は、以下の部分で設定されているようである。
/* 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となるはず。
以下のようにソース修正しビルドしてみる。
/* 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解釈


コメント