Skip to content

Commit 8590508

Browse files
authored
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
1 parent 17afcdb commit 8590508

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

CONTRIBUTING.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,11 @@ The tests always log to the console. See the [Logging documentation](https://ssh
4141
### Wireshark
4242

4343
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.
44+
45+
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".
46+
47+
```c#
48+
using Renci.SshNet;
49+
50+
SshNetLoggingConfiguration.WiresharkKeyLogFilePath = @"C:\tmp\sshkeylogfile.txt";
51+
```

src/Renci.SshNet/Session.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ private set
320320
/// Gets the client init message.
321321
/// </summary>
322322
/// <value>The client init message.</value>
323-
public Message ClientInitMessage { get; private set; }
323+
public KeyExchangeInitMessage ClientInitMessage { get; private set; }
324324

325325
/// <summary>
326326
/// Gets the server version string.
@@ -1582,6 +1582,16 @@ internal void OnNewKeysReceived(NewKeysMessage message)
15821582
_clientCompression = _keyExchange.CreateCompressor();
15831583
_serverDecompression = _keyExchange.CreateDecompressor();
15841584

1585+
#if DEBUG
1586+
if (SshNetLoggingConfiguration.WiresharkKeyLogFilePath is string path
1587+
&& _keyExchange is KeyExchange kex)
1588+
{
1589+
System.IO.File.AppendAllText(
1590+
path,
1591+
$"{ToHex(ClientInitMessage.Cookie)} SHARED_SECRET {ToHex(kex.SharedKey)}{Environment.NewLine}");
1592+
}
1593+
#endif
1594+
15851595
// Dispose of old KeyExchange object as it is no longer needed.
15861596
_keyExchange.HostKeyReceived -= KeyExchange_HostKeyReceived;
15871597
_keyExchange.Dispose();

src/Renci.SshNet/SshNetLoggingConfiguration.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,17 @@ public static void InitializeLogging(ILoggerFactory loggerFactory)
2222
ThrowHelper.ThrowIfNull(loggerFactory);
2323
LoggerFactory = loggerFactory;
2424
}
25+
26+
#if DEBUG
27+
/// <summary>
28+
/// Gets or sets the path to which to write session secrets which
29+
/// Wireshark can read and use to inspect encrypted traffic.
30+
/// </summary>
31+
/// <remarks>
32+
/// To configure in Wireshark, go to Edit -> Preferences -> Protocols
33+
/// -> SSH and set the same value for "Key log filename".
34+
/// </remarks>
35+
public static string? WiresharkKeyLogFilePath { get; set; }
36+
#endif
2537
}
2638
}

0 commit comments

Comments
 (0)