1 | initial version |
However, if I don't call the built-in TLS dissector, the inner payload is decrypted, which seems weird to me.
This is a sign that the dissector is using the new keys from the second handshake and replacing the earlier keys, and trying them on the outer TLS layer, which doesn't work. The problem is that the TLS session is stored in a conversation created using the addresses, ports, and port types, none of which change from the interposing dissector. You can verify this by having the TLS dissector write to a log file
You can work around this by artificially changing the port type and then changing it back, which will cause it to create a different session for the tunneled protocol:
local save_port_type = pktinfo.port_type
pktinfo.port_type = _EPAN.PT_NONE -- any value other than _EPAN.PT_TCP
Dissector.get("tls"):call(tvb, pktinfo, tunnel_tree)
pktinfo.port_type = save_port_type
You will then need to deal with a second issue, reassembling some of the inner TLS records that are split across multiple packets. The pinfo
(or pktinfo
in Lua) struct has a member can_desegment
that has to be at least 1 for desegmentation to be allowed in a dissector. It is decremented by 1 each time a dissector is called. Dissectors which know that defragmentation is possible should set it to 2, so that it has the value 1 in the next dissector:
local save_port_type = pktinfo.port_type
pktinfo.port_type = _EPAN.PT_NONE
local save_can_desegment = pktinfo.can_desegment
pktinfo.can_desegment = 2 -- should really be pktinfo.saved_can_desegment
Dissector.get("tls"):call(tvb, pktinfo, tunnel_tree)
pktinfo.port_type = save_port_type
pktinfo.can_desegment = save_can_desegment
For tunneling purposes, there's another value in pinfo
called saved_can_desegment
, which tunneling dissectors like Socks use. That has the value in the previous dissector, and is used for tunneling dissectors that shouldn't decrement the value, but also want the value in the previous layer (in case, for example, some error means that TCP didn't think that desegmentation was possible.) That's what should be used, except it's not exposed to Lua currently. I'll fix that.
Do that, and add DissectorTable.get("tls.alpn"):add("h2", trojan)
to your enableDissector()
registration (to override the value for the ALPN), and it will work.