Wireshark-dev: Re: [Wireshark-dev] Dissecting TLS and non-TLS using the same ports

From: John Thacker <johnthacker@xxxxxxxxx>
Date: Thu, 13 Jul 2023 11:10:46 -0400
On Thu, Jul 13, 2023, 10:49 AM Markku Leiniö <markku@xxxxxx> wrote:
Hi,

In my Zabbix dissector I'm currently using
dissector_add_uint_range_with_preference("tcp.port", ZABBIX_TCP_PORTS,
zabbix_handle) to define the TCP ports (defaulting to "10050,10051").

I'm now attempting to use ssl_dissector_add() to dissect also
TLS-encrypted Zabbix protocol packets, using the same ports (that's how
Zabbix works: some agents use TLS, some don't, and they all connect to
the same port on the server). I see port number 0 being used in some
dissectors (for example in packet-kafka.c), but that does not seem to
work. From some comments I understand that it enables to use manual
"Decode as" or something like that.

So, apparently I need to use ssl_dissector_add() with all the configured
ports. I see examples of using range_foreach() to do that, so I used it
like this:

        range_t *zabbix_tcp_range;
        zabbix_tcp_range = prefs_get_range_value("zabbix", "tcp.port");
        range_foreach(zabbix_tcp_range, range_add_zabbix_tls_callback,
NULL);

It seems to work with TLS packets, but now it won't dissect non-TLS
Zabbix packets at all.

In Lua (with my previous dissector) I was able to do simply this:

     DissectorTable.get("tcp.port"):add(default_settings.ports,
zabbix_protocol)
     DissectorTable.get("tls.port"):add(default_settings.ports,
zabbix_protocol)

and that worked fine, it dissected both TLS and non-TLS packets correctly.

How do I get the same behaviour with C dissector?

The short answer is don't use ssl_dissector_add(), just 

dissector_add_uint_range("tls.port", zabbix_tcp_range, zabbix_protocol);

There's also a version _with_preference that takes a string instead. That will be the same as what you did in Lua.

Longer answer:
ssl_dissector_add() does two things:

1. Registers your protocol in the "tls.port" table so TLS calls it on that port.
2. Registers TLS in the "tcp.port" table so TCP calls TLS on that port.

Only one protocol can be registered to a given port for TCP.

With protocols like Zabbix, the choices are:
1. Register the non TLS version in the TCP port table, have it reject packets that are not Zabbix, the TLS heuristic dissector should pick it up if all goes well and forward it along after dissecting the TLS portion. Sounds like that worked for you on Lua, so it should work here.
2. Register the TLS version in the TCP port and a heuristic dissector for Zabbix; if the non TLS protocol doesn't look like TLS, the TLS dissector should reject it, and your heuristic dissector should pick it up.
3. Register some kind of helper dissector to the TCP port that can detect whether this is straight Zabbix or TLS, calling the TLS dissector if necessary. This can end up making `pinfo->layers` have an extra entry, especially for the first TLS packet in the first pass.

Probably TMI, because the first should work for you.

John Thacker