diff --git a/config/config.go b/config/config.go index bb3a121356..798a6f6423 100644 --- a/config/config.go +++ b/config/config.go @@ -261,6 +261,7 @@ func (cfg *Config) addTransports(h host.Host) error { } fxopts = append(fxopts, fx.Provide(PrivKeyToStatelessResetKey)) + fxopts = append(fxopts, fx.Provide(PrivKeyToTokenGeneratorKey)) if cfg.QUICReuse != nil { fxopts = append(fxopts, cfg.QUICReuse...) } else { diff --git a/config/quic_stateless_reset.go b/config/quic.go similarity index 53% rename from config/quic_stateless_reset.go rename to config/quic.go index a12be56f5b..66c40da97f 100644 --- a/config/quic_stateless_reset.go +++ b/config/quic.go @@ -11,7 +11,10 @@ import ( "github.com/quic-go/quic-go" ) -const statelessResetKeyInfo = "libp2p quic stateless reset key" +const ( + statelessResetKeyInfo = "libp2p quic stateless reset key" + tokenGeneratorKeyInfo = "libp2p quic token generator key" +) func PrivKeyToStatelessResetKey(key crypto.PrivKey) (quic.StatelessResetKey, error) { var statelessResetKey quic.StatelessResetKey @@ -25,3 +28,16 @@ func PrivKeyToStatelessResetKey(key crypto.PrivKey) (quic.StatelessResetKey, err } return statelessResetKey, nil } + +func PrivKeyToTokenGeneratorKey(key crypto.PrivKey) (quic.TokenGeneratorKey, error) { + var tokenKey quic.TokenGeneratorKey + keyBytes, err := key.Raw() + if err != nil { + return tokenKey, err + } + keyReader := hkdf.New(sha256.New, keyBytes, nil, []byte(tokenGeneratorKeyInfo)) + if _, err := io.ReadFull(keyReader, tokenKey[:]); err != nil { + return tokenKey, err + } + return tokenKey, nil +} diff --git a/p2p/net/swarm/dial_worker_test.go b/p2p/net/swarm/dial_worker_test.go index 6679bd9587..f3c46cb495 100644 --- a/p2p/net/swarm/dial_worker_test.go +++ b/p2p/net/swarm/dial_worker_test.go @@ -26,12 +26,13 @@ import ( "github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem" "github.com/libp2p/go-libp2p/p2p/muxer/yamux" tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader" - quic "github.com/libp2p/go-libp2p/p2p/transport/quic" + libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic" "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" "github.com/libp2p/go-libp2p/p2p/transport/tcp" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" + "github.com/quic-go/quic-go" "github.com/stretchr/testify/require" ) @@ -88,11 +89,11 @@ func makeSwarmWithNoListenAddrs(t *testing.T, opts ...Option) *Swarm { if err := s.AddTransport(tcpTransport); err != nil { t.Fatal(err) } - reuse, err := quicreuse.NewConnManager([32]byte{}) + reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}) if err != nil { t.Fatal(err) } - quicTransport, err := quic.NewTransport(priv, reuse, nil, nil, nil) + quicTransport, err := libp2pquic.NewTransport(priv, reuse, nil, nil, nil) if err != nil { t.Fatal(err) } @@ -968,7 +969,7 @@ func TestDialWorkerLoopHolePunching(t *testing.T) { for i := 0; i < len(addrs); i++ { delay := 10 * time.Second if addrs[i].Equal(t1) { - //fire t1 immediately + // fire t1 immediately delay = 0 } else if addrs[i].Equal(t2) { // delay t2 by 100ms diff --git a/p2p/net/swarm/swarm_addr_test.go b/p2p/net/swarm/swarm_addr_test.go index 8ab7d18bf6..be3e2d6689 100644 --- a/p2p/net/swarm/swarm_addr_test.go +++ b/p2p/net/swarm/swarm_addr_test.go @@ -14,7 +14,7 @@ import ( "github.com/libp2p/go-libp2p/p2p/net/swarm" swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing" circuitv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" - quic "github.com/libp2p/go-libp2p/p2p/transport/quic" + libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic" "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" "github.com/libp2p/go-libp2p/p2p/transport/tcp" webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport" @@ -22,6 +22,7 @@ import ( ma "github.com/multiformats/go-multiaddr" "github.com/multiformats/go-multibase" "github.com/multiformats/go-multihash" + "github.com/quic-go/quic-go" "github.com/stretchr/testify/require" ) @@ -81,10 +82,10 @@ func TestDialAddressSelection(t *testing.T) { tcpTr, err := tcp.NewTCPTransport(nil, nil) require.NoError(t, err) require.NoError(t, s.AddTransport(tcpTr)) - reuse, err := quicreuse.NewConnManager([32]byte{}) + reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}) require.NoError(t, err) defer reuse.Close() - quicTr, err := quic.NewTransport(priv, reuse, nil, nil, nil) + quicTr, err := libp2pquic.NewTransport(priv, reuse, nil, nil, nil) require.NoError(t, err) require.NoError(t, s.AddTransport(quicTr)) webtransportTr, err := webtransport.New(priv, nil, reuse, nil, nil) diff --git a/p2p/net/swarm/swarm_dial_test.go b/p2p/net/swarm/swarm_dial_test.go index badb53de94..a0579b6a10 100644 --- a/p2p/net/swarm/swarm_dial_test.go +++ b/p2p/net/swarm/swarm_dial_test.go @@ -139,7 +139,7 @@ func newTestSwarmWithResolver(t *testing.T, resolver *madns.Resolver) *Swarm { err = s.AddTransport(tpt) require.NoError(t, err) - connmgr, err := quicreuse.NewConnManager(quic.StatelessResetKey{}) + connmgr, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}) require.NoError(t, err) quicTpt, err := libp2pquic.NewTransport(priv, connmgr, nil, nil, &network.NullResourceManager{}) require.NoError(t, err) diff --git a/p2p/net/swarm/testing/testing.go b/p2p/net/swarm/testing/testing.go index 071a828b54..627114f645 100644 --- a/p2p/net/swarm/testing/testing.go +++ b/p2p/net/swarm/testing/testing.go @@ -21,11 +21,12 @@ import ( "github.com/libp2p/go-libp2p/p2p/muxer/yamux" "github.com/libp2p/go-libp2p/p2p/net/swarm" tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader" - quic "github.com/libp2p/go-libp2p/p2p/transport/quic" + libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic" "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" "github.com/libp2p/go-libp2p/p2p/transport/tcp" ma "github.com/multiformats/go-multiaddr" + "github.com/quic-go/quic-go" "github.com/stretchr/testify/require" ) @@ -175,11 +176,11 @@ func GenSwarm(t *testing.T, opts ...Option) *swarm.Swarm { } } if !cfg.disableQUIC { - reuse, err := quicreuse.NewConnManager([32]byte{}) + reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}) if err != nil { t.Fatal(err) } - quicTransport, err := quic.NewTransport(priv, reuse, nil, cfg.connectionGater, nil) + quicTransport, err := libp2pquic.NewTransport(priv, reuse, nil, cfg.connectionGater, nil) if err != nil { t.Fatal(err) } diff --git a/p2p/transport/quic/cmd/client/main.go b/p2p/transport/quic/cmd/client/main.go index f33d65ecd4..7873625321 100644 --- a/p2p/transport/quic/cmd/client/main.go +++ b/p2p/transport/quic/cmd/client/main.go @@ -8,13 +8,13 @@ import ( "log" "os" - "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" - ic "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/peer" libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic" + "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" ma "github.com/multiformats/go-multiaddr" + "github.com/quic-go/quic-go" ) func main() { @@ -41,7 +41,7 @@ func run(raddr string, p string) error { return err } - reuse, err := quicreuse.NewConnManager([32]byte{}) + reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}) if err != nil { return err } diff --git a/p2p/transport/quic/cmd/server/main.go b/p2p/transport/quic/cmd/server/main.go index e5144f496d..222841d42a 100644 --- a/p2p/transport/quic/cmd/server/main.go +++ b/p2p/transport/quic/cmd/server/main.go @@ -7,14 +7,14 @@ import ( "log" "os" - "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" - ic "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/peer" tpt "github.com/libp2p/go-libp2p/core/transport" libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic" + "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" ma "github.com/multiformats/go-multiaddr" + "github.com/quic-go/quic-go" ) func main() { @@ -41,7 +41,7 @@ func run(port string) error { return err } - reuse, err := quicreuse.NewConnManager([32]byte{}) + reuse, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}) if err != nil { return err } diff --git a/p2p/transport/quic/conn_test.go b/p2p/transport/quic/conn_test.go index cfbe7f1e50..d3e27a7e16 100644 --- a/p2p/transport/quic/conn_test.go +++ b/p2p/transport/quic/conn_test.go @@ -69,7 +69,7 @@ func runServer(t *testing.T, tr tpt.Transport, addr string) tpt.Listener { func newConnManager(t *testing.T, opts ...quicreuse.Option) *quicreuse.ConnManager { t.Helper() - cm, err := quicreuse.NewConnManager([32]byte{}, opts...) + cm, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, opts...) require.NoError(t, err) t.Cleanup(func() { cm.Close() }) return cm diff --git a/p2p/transport/quicreuse/connmgr.go b/p2p/transport/quicreuse/connmgr.go index 34867cbd75..22f802554f 100644 --- a/p2p/transport/quicreuse/connmgr.go +++ b/p2p/transport/quicreuse/connmgr.go @@ -25,8 +25,10 @@ type ConnManager struct { quicListenersMu sync.Mutex quicListeners map[string]quicListenerEntry - srk quic.StatelessResetKey - mt *metricsTracer + srk quic.StatelessResetKey + tokenKey quic.TokenGeneratorKey + + mt *metricsTracer } type quicListenerEntry struct { @@ -34,11 +36,12 @@ type quicListenerEntry struct { ln *quicListener } -func NewConnManager(statelessResetKey quic.StatelessResetKey, opts ...Option) (*ConnManager, error) { +func NewConnManager(statelessResetKey quic.StatelessResetKey, tokenKey quic.TokenGeneratorKey, opts ...Option) (*ConnManager, error) { cm := &ConnManager{ enableReuseport: true, quicListeners: make(map[string]quicListenerEntry), srk: statelessResetKey, + tokenKey: tokenKey, } for _, o := range opts { if err := o(cm); err != nil { @@ -153,6 +156,7 @@ func (c *ConnManager) transportForListen(network string, laddr *net.UDPAddr) (re Transport: quic.Transport{ Conn: conn, StatelessResetKey: &c.srk, + TokenGeneratorKey: &c.tokenKey, // The multiaddress encodes the QUIC version, thus there's no need to send Version Negotiation packets. DisableVersionNegotiationPackets: true, }, diff --git a/p2p/transport/quicreuse/connmgr_test.go b/p2p/transport/quicreuse/connmgr_test.go index 14809ac736..f3576a3905 100644 --- a/p2p/transport/quicreuse/connmgr_test.go +++ b/p2p/transport/quicreuse/connmgr_test.go @@ -54,7 +54,7 @@ func testListenOnSameProto(t *testing.T, enableReuseport bool) { if !enableReuseport { opts = append(opts, DisableReuseport()) } - cm, err := NewConnManager([32]byte{}, opts...) + cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, opts...) require.NoError(t, err) defer checkClosed(t, cm) defer cm.Close() @@ -83,7 +83,7 @@ func TestConnectionPassedToQUICForListening(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("skipping on windows. Windows doesn't support these optimizations") } - cm, err := NewConnManager([32]byte{}, DisableReuseport()) + cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, DisableReuseport()) require.NoError(t, err) defer cm.Close() @@ -107,7 +107,7 @@ func TestConnectionPassedToQUICForListening(t *testing.T) { func TestAcceptErrorGetCleanedUp(t *testing.T) { raddr := ma.StringCast("/ip4/127.0.0.1/udp/0/quic-v1") - cm, err := NewConnManager([32]byte{}, DisableReuseport()) + cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, DisableReuseport()) require.NoError(t, err) defer cm.Close() @@ -143,7 +143,7 @@ func TestConnectionPassedToQUICForDialing(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("skipping on windows. Windows doesn't support these optimizations") } - cm, err := NewConnManager([32]byte{}, DisableReuseport()) + cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, DisableReuseport()) require.NoError(t, err) defer cm.Close() @@ -218,7 +218,7 @@ func testListener(t *testing.T, enableReuseport bool) { if !enableReuseport { opts = append(opts, DisableReuseport()) } - cm, err := NewConnManager([32]byte{}, opts...) + cm, err := NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, opts...) require.NoError(t, err) id1, tlsConf1 := getTLSConfForProto(t, "proto1") diff --git a/p2p/transport/webtransport/transport_test.go b/p2p/transport/webtransport/transport_test.go index 7f5b3cf849..7b45240343 100644 --- a/p2p/transport/webtransport/transport_test.go +++ b/p2p/transport/webtransport/transport_test.go @@ -97,7 +97,7 @@ func getCerthashComponent(t *testing.T, b []byte) ma.Multiaddr { func newConnManager(t *testing.T, opts ...quicreuse.Option) *quicreuse.ConnManager { t.Helper() - cm, err := quicreuse.NewConnManager([32]byte{}, opts...) + cm, err := quicreuse.NewConnManager(quic.StatelessResetKey{}, quic.TokenGeneratorKey{}, opts...) require.NoError(t, err) t.Cleanup(func() { cm.Close() }) return cm