Add a debug helper for reading traffic with Wireshark (#1627)

Wireshark can already helpfully dissect the initial SSH handshake. When given the
session keys, it can also dissect the encrypted traffic for inspection/debugging.
This adds a helper in Debug mode to write out that information in the format
Wireshark requires.

Usage is to set `SshNetLoggingConfiguration.WiresharkKeyLogFilePath` before connecting, and supply the same value to Wireshark in Edit -> Preferences -> Protocols
-> SSH -> "Key log filename".

The description of the format is at https://wiki.wireshark.org/SSH#key-log-format
This commit is contained in:
Rob Hague
2025-05-04 11:38:55 +02:00
committed by GitHub
parent 17afcdb0fe
commit 85905082db
3 changed files with 31 additions and 1 deletions
+8
View File
@@ -41,3 +41,11 @@ The tests always log to the console. See the [Logging documentation](https://ssh
### Wireshark
Wireshark is able to dissect initial connection packets, such as key exchange, before encryption happens. Enter "ssh" as the display filter. See https://wiki.wireshark.org/SSH.md for more information.
The Debug build of SSH.NET has helpers to also allow dissection of the encrypted traffic by dumping the session keys in a format that Wireshark understands. Set a value for `SshNetLoggingConfiguration.WiresharkKeyLogFilePath` before connecting, and supply the same value to Wireshark in Edit -> Preferences -> Protocols -> SSH -> "Key log filename".
```c#
using Renci.SshNet;
SshNetLoggingConfiguration.WiresharkKeyLogFilePath = @"C:\tmp\sshkeylogfile.txt";
```
+11 -1
View File
@@ -320,7 +320,7 @@ namespace Renci.SshNet
/// Gets the client init message.
/// </summary>
/// <value>The client init message.</value>
public Message ClientInitMessage { get; private set; }
public KeyExchangeInitMessage ClientInitMessage { get; private set; }
/// <summary>
/// Gets the server version string.
@@ -1582,6 +1582,16 @@ namespace Renci.SshNet
_clientCompression = _keyExchange.CreateCompressor();
_serverDecompression = _keyExchange.CreateDecompressor();
#if DEBUG
if (SshNetLoggingConfiguration.WiresharkKeyLogFilePath is string path
&& _keyExchange is KeyExchange kex)
{
System.IO.File.AppendAllText(
path,
$"{ToHex(ClientInitMessage.Cookie)} SHARED_SECRET {ToHex(kex.SharedKey)}{Environment.NewLine}");
}
#endif
// Dispose of old KeyExchange object as it is no longer needed.
_keyExchange.HostKeyReceived -= KeyExchange_HostKeyReceived;
_keyExchange.Dispose();
@@ -22,5 +22,17 @@ namespace Renci.SshNet
ThrowHelper.ThrowIfNull(loggerFactory);
LoggerFactory = loggerFactory;
}
#if DEBUG
/// <summary>
/// Gets or sets the path to which to write session secrets which
/// Wireshark can read and use to inspect encrypted traffic.
/// </summary>
/// <remarks>
/// To configure in Wireshark, go to Edit -> Preferences -> Protocols
/// -> SSH and set the same value for "Key log filename".
/// </remarks>
public static string? WiresharkKeyLogFilePath { get; set; }
#endif
}
}