mirror of https://github.com/grpc/grpc-java.git
netty: add exporting SSL/TLS master key log feature (#7724)
Enable this feature by setting the system property -Dio.netty.ssl.masterKeyHandler=true or System.setProperty(SslMasterKeyHandler.SYSTEM_PROP_KEY, "true"); The keys will be written to the log named "io.netty.wireshark" in the warnning level. To export the keys to a file, you can configure log factory like: (with log4j.xml for example) <appender name="key-file" class="org.apache.log4j.RollingFileAppender"> <param name="file" value="d:/keyfile.txt"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%m%n"/> </layout> </appender> <category name="io.netty.wireshark"> <priority value="DEBUG" /> <appender-ref ref="key-file" /> </category> Wireshark can analyze the messages gRPC over TLS with this key log file. close #7199
This commit is contained in:
parent
2dba43c727
commit
9bc05fba67
|
|
@ -64,6 +64,7 @@ import io.netty.handler.ssl.SslContext;
|
|||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import io.netty.handler.ssl.SslHandshakeCompletionEvent;
|
||||
import io.netty.handler.ssl.SslMasterKeyHandler;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import io.netty.util.AsciiString;
|
||||
import io.netty.util.Attribute;
|
||||
|
|
@ -396,6 +397,14 @@ final class ProtocolNegotiators {
|
|||
ctx.pipeline().addBefore(ctx.name(), /* name= */ null, this.executor != null
|
||||
? new SslHandler(sslEngine, false, this.executor)
|
||||
: new SslHandler(sslEngine, false));
|
||||
|
||||
// Support exporting the key and session identifier to the log named
|
||||
// "io.netty.wireshark" when the system property named "io.netty.ssl.masterKeyHandler"
|
||||
// is "true". This feature is used to analyze gRPC traffic with Wireshark.
|
||||
if (Boolean.getBoolean(SslMasterKeyHandler.SYSTEM_PROP_KEY)) {
|
||||
ctx.pipeline().addBefore(ctx.name(), null,
|
||||
SslMasterKeyHandler.newWireSharkSslMasterKeyHandler());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -572,6 +581,14 @@ final class ProtocolNegotiators {
|
|||
ctx.pipeline().addBefore(ctx.name(), /* name= */ null, this.executor != null
|
||||
? new SslHandler(sslEngine, false, this.executor)
|
||||
: new SslHandler(sslEngine, false));
|
||||
|
||||
// Support exporting the key and session identifier to the log named
|
||||
// "io.netty.wireshark" when the system property named "io.netty.ssl.masterKeyHandler"
|
||||
// is "true". This feature is used to analyze gRPC traffic with Wireshark.
|
||||
if (Boolean.getBoolean(SslMasterKeyHandler.SYSTEM_PROP_KEY)) {
|
||||
ctx.pipeline().addBefore(ctx.name(), null,
|
||||
SslMasterKeyHandler.newWireSharkSslMasterKeyHandler());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -94,17 +94,20 @@ import io.netty.handler.ssl.SslContext;
|
|||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import io.netty.handler.ssl.SslHandshakeCompletionEvent;
|
||||
import io.netty.handler.ssl.SslMasterKeyHandler;
|
||||
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
|
||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.logging.Filter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
|
@ -1210,4 +1213,53 @@ public class ProtocolNegotiatorsTest {
|
|||
ctx.pipeline().fireUserEventTriggered(ProtocolNegotiationEvent.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clientTlsHandler_serverTlsHandler_sslMasterKeyLog() throws Exception {
|
||||
final List<LogRecord> logs = new ArrayList<>();
|
||||
Handler handler = new Handler() {
|
||||
@Override public void publish(LogRecord record) {
|
||||
logs.add(record);
|
||||
}
|
||||
|
||||
@Override public void flush() {}
|
||||
|
||||
@Override public void close() {}
|
||||
};
|
||||
|
||||
Logger logger = Logger.getLogger("io.netty.wireshark");
|
||||
logger.addHandler(handler);
|
||||
|
||||
String oldPropValue = System.getProperty(SslMasterKeyHandler.SYSTEM_PROP_KEY);
|
||||
try {
|
||||
// The master key log feature should be disabled
|
||||
// when the "io.netty.ssl.masterKeyHandler" property is missing.
|
||||
System.clearProperty(SslMasterKeyHandler.SYSTEM_PROP_KEY);
|
||||
clientTlsHandler_firesNegotiation();
|
||||
assertThat(logs).isEmpty();
|
||||
|
||||
// The master key log feature should be disabled
|
||||
// when the value of "io.netty.ssl.masterKeyHandler" property is not "true".
|
||||
System.setProperty(SslMasterKeyHandler.SYSTEM_PROP_KEY, "false");
|
||||
clientTlsHandler_firesNegotiation();
|
||||
assertThat(logs).isEmpty();
|
||||
|
||||
// The master key log feature should be enabled
|
||||
// when the value of "io.netty.ssl.masterKeyHandler" property is "true".
|
||||
System.setProperty(SslMasterKeyHandler.SYSTEM_PROP_KEY, "true");
|
||||
clientTlsHandler_firesNegotiation();
|
||||
|
||||
// writing key twice because both client and server will enable key log feature
|
||||
assertThat(logs.size()).isEqualTo(2);
|
||||
assertThat(logs.get(0).getMessage()).containsMatch("^RSA Session-ID:.+ Master-Key:");
|
||||
assertThat(logs.get(1).getMessage()).containsMatch("^RSA Session-ID:.+ Master-Key:");
|
||||
} finally {
|
||||
logger.removeHandler(handler);
|
||||
if (oldPropValue != null) {
|
||||
System.setProperty(SslMasterKeyHandler.SYSTEM_PROP_KEY, oldPropValue);
|
||||
} else {
|
||||
System.clearProperty(SslMasterKeyHandler.SYSTEM_PROP_KEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue