Repository: libp2p/go-libp2p
Pull request #2750 (2024-03-22 07:45:02)

feat: add tls `WithKeyLogWriter` option
`KeyLogWriter` can help us use Wireshark to analyze TLS decrypted network packets.
Details can be found at: https://wiki.wireshark.org/TLS#using-the-pre-master-secret


Patch:
diff --git a/p2p/security/tls/crypto.go b/p2p/security/tls/crypto.go
index 385de5a1..70a594d0 100644
--- a/p2p/security/tls/crypto.go
+++ b/p2p/security/tls/crypto.go
@@ -11,6 +11,7 @@ import (
 	"encoding/asn1"
 	"errors"
 	"fmt"
+	"io"
 	"math/big"
 	"os"
 	"runtime/debug"
@@ -41,6 +42,7 @@ type Identity struct {
 // IdentityConfig is used to configure an Identity
 type IdentityConfig struct {
 	CertTemplate *x509.Certificate
+	KeyLogWriter io.Writer
 }
 
 // IdentityOption transforms an IdentityConfig to apply optional settings.
@@ -53,6 +55,18 @@ func WithCertTemplate(template *x509.Certificate) IdentityOption {
 	}
 }
 
+// WithKeyLogWriter optionally specifies a destination for TLS master secrets
+// in NSS key log format that can be used to allow external programs
+// such as Wireshark to decrypt TLS connections.
+// See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.
+// Use of KeyLogWriter compromises security and should only be
+// used for debugging.
+func WithKeyLogWriter(w io.Writer) IdentityOption {
+	return func(c *IdentityConfig) {
+		c.KeyLogWriter = w
+	}
+}
+
 // NewIdentity creates a new identity
 func NewIdentity(privKey ic.PrivKey, opts ...IdentityOption) (*Identity, error) {
 	config := IdentityConfig{}
@@ -83,6 +97,7 @@ func NewIdentity(privKey ic.PrivKey, opts ...IdentityOption) (*Identity, error)
 			},
 			NextProtos:             []string{alpn},
 			SessionTicketsDisabled: true,
+			KeyLogWriter:           config.KeyLogWriter,
 		},
 	}, nil
 }
diff --git a/p2p/transport/quicreuse/listener.go b/p2p/transport/quicreuse/listener.go
index c9d482c0..4ee20042 100644
--- a/p2p/transport/quicreuse/listener.go
+++ b/p2p/transport/quicreuse/listener.go
@@ -30,7 +30,6 @@ type protoConf struct {
 
 type quicListener struct {
 	l         *quic.Listener
-	closeMx   sync.Mutex
 	transport refCountedQuicTransport
 	running   chan struct{}
 	addrs     []ma.Multiaddr
@@ -125,13 +124,7 @@ func (l *quicListener) Add(tlsConf *tls.Config, allowWindowIncrease func(conn qu
 
 func (l *quicListener) Run() error {
 	defer close(l.running)
-	defer func() {
-		// transport close is not safe to use concurrently with listener close.
-		// remove after https://github.com/quic-go/quic-go/issues/4266 is fixed.
-		l.closeMx.Lock()
-		defer l.closeMx.Unlock()
-		l.transport.DecreaseCount()
-	}()
+	defer l.transport.DecreaseCount()
 	for {
 		conn, err := l.l.Accept(context.Background())
 		if err != nil {
@@ -154,12 +147,7 @@ func (l *quicListener) Run() error {
 }
 
 func (l *quicListener) Close() error {
-	// listener close is not safe to use concurrently with transport close.
-	// remove after https://github.com/quic-go/quic-go/issues/4266 is fixed.
-	l.closeMx.Lock()
 	err := l.l.Close()
-	l.closeMx.Unlock()
-
 	<-l.running // wait for Run to return
 	return err
 }


Test patch:
diff --git a/p2p/http/example_test.go b/p2p/http/example_test.go
index bad042e9..719badea 100644
--- a/p2p/http/example_test.go
+++ b/p2p/http/example_test.go
@@ -138,7 +138,7 @@ func ExampleHost_Serve() {
 func ExampleHost_SetHTTPHandler() {
 	server := libp2phttp.Host{
 		InsecureAllowHTTP: true, // For our example, we'll allow insecure HTTP
-		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/50222/http")},
+		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/0/http")},
 	}
 
 	server.SetHTTPHandler("/hello/1", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -172,7 +172,7 @@ func ExampleHost_SetHTTPHandler() {
 func ExampleHost_SetHTTPHandlerAtPath() {
 	server := libp2phttp.Host{
 		InsecureAllowHTTP: true, // For our example, we'll allow insecure HTTP
-		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/50224/http")},
+		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/0/http")},
 	}
 
 	server.SetHTTPHandlerAtPath("/hello/1", "/other-place/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -209,7 +209,7 @@ func ExampleHost_NamespacedClient() {
 	// Create the server
 	server := libp2phttp.Host{
 		InsecureAllowHTTP: true, // For our example, we'll allow insecure HTTP
-		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/50221/http")},
+		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/0/http")},
 	}
 
 	server.SetHTTPHandlerAtPath("/hello/1", "/other-place/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -247,7 +247,7 @@ func ExampleHost_NamespaceRoundTripper() {
 	// Create the server
 	server := libp2phttp.Host{
 		InsecureAllowHTTP: true, // For our example, we'll allow insecure HTTP
-		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/50223/http")},
+		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/0/http")},
 	}
 
 	server.SetHTTPHandler("/hello/1", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -291,7 +291,7 @@ func ExampleHost_NewConstrainedRoundTripper() {
 	// Create the server
 	server := libp2phttp.Host{
 		InsecureAllowHTTP: true, // For our example, we'll allow insecure HTTP
-		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/50225/http")},
+		ListenAddrs:       []ma.Multiaddr{ma.StringCast("/ip4/127.0.0.1/tcp/0/http")},
 	}
 
 	server.SetHTTPHandler("/hello/1", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {