go-libp2p denial of service vulnerability from lack of resource management
Description
go-libp2p is the offical libp2p implementation in the Go programming language. Version 0.18.0 and older of go-libp2p are vulnerable to targeted resource exhaustion attacks. These attacks target libp2p’s connection, stream, peer, and memory management. An attacker can cause the allocation of large amounts of memory, ultimately leading to the process getting killed by the host’s operating system. While a connection manager tasked with keeping the number of connections within manageable limits has been part of go-libp2p, this component was designed to handle the regular churn of peers, not a targeted resource exhaustion attack. Users are advised to upgrade their version of go-libp2p to version 0.18.1 or newer. Users unable to upgrade may consult the denial of service (dos) mitigation page for more information on how to incorporate mitigation strategies, monitor your application, and respond to attacks.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/libp2p/go-libp2pGo | < 0.18.0 | 0.18.0 |
Affected products
1Patches
115d7dfbf5426Merge pull request #1275 from libp2p/rcmgr
30 files changed · +681 −170
config/config.go+13 −5 modified@@ -87,10 +87,12 @@ type Config struct { AddrsFactory bhost.AddrsFactory ConnectionGater connmgr.ConnectionGater - ConnManager connmgr.ConnManager - NATManager NATManagerC - Peerstore peerstore.Peerstore - Reporter metrics.Reporter + ConnManager connmgr.ConnManager + ResourceManager network.ResourceManager + + NATManager NATManagerC + Peerstore peerstore.Peerstore + Reporter metrics.Reporter MultiaddrResolver *madns.Resolver @@ -148,6 +150,9 @@ func (cfg *Config) makeSwarm() (*swarm.Swarm, error) { if cfg.DialTimeout != 0 { opts = append(opts, swarm.WithDialTimeout(cfg.DialTimeout)) } + if cfg.ResourceManager != nil { + opts = append(opts, swarm.WithResourceManager(cfg.ResourceManager)) + } // TODO: Make the swarm implementation configurable. return swarm.NewSwarm(pid, cfg.Peerstore, opts...) } @@ -179,11 +184,14 @@ func (cfg *Config) addTransports(h host.Host) error { if cfg.ConnectionGater != nil { opts = append(opts, tptu.WithConnectionGater(cfg.ConnectionGater)) } + if cfg.ResourceManager != nil { + opts = append(opts, tptu.WithResourceManager(cfg.ResourceManager)) + } upgrader, err := tptu.New(secure, muxer, opts...) if err != nil { return err } - tpts, err := makeTransports(h, upgrader, cfg.ConnectionGater, cfg.PSK, cfg.Transports) + tpts, err := makeTransports(h, upgrader, cfg.ConnectionGater, cfg.PSK, cfg.ResourceManager, cfg.Transports) if err != nil { return err }
config/constructor_types.go+20 −11 modified@@ -7,7 +7,6 @@ import ( "github.com/libp2p/go-libp2p-core/connmgr" "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/host" - "github.com/libp2p/go-libp2p-core/mux" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" "github.com/libp2p/go-libp2p-core/peerstore" @@ -21,41 +20,51 @@ var ( hostType = reflect.TypeOf((*host.Host)(nil)).Elem() networkType = reflect.TypeOf((*network.Network)(nil)).Elem() transportType = reflect.TypeOf((*transport.Transport)(nil)).Elem() - muxType = reflect.TypeOf((*mux.Multiplexer)(nil)).Elem() + muxType = reflect.TypeOf((*network.Multiplexer)(nil)).Elem() securityType = reflect.TypeOf((*sec.SecureTransport)(nil)).Elem() privKeyType = reflect.TypeOf((*crypto.PrivKey)(nil)).Elem() pubKeyType = reflect.TypeOf((*crypto.PubKey)(nil)).Elem() pstoreType = reflect.TypeOf((*peerstore.Peerstore)(nil)).Elem() connGaterType = reflect.TypeOf((*connmgr.ConnectionGater)(nil)).Elem() upgraderType = reflect.TypeOf((*transport.Upgrader)(nil)).Elem() + rcmgrType = reflect.TypeOf((*network.ResourceManager)(nil)).Elem() // concrete types peerIDType = reflect.TypeOf((peer.ID)("")) pskType = reflect.TypeOf((pnet.PSK)(nil)) ) var argTypes = map[reflect.Type]constructor{ - upgraderType: func(_ host.Host, u transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater) interface{} { return u }, - hostType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater) interface{} { return h }, - networkType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater) interface{} { + upgraderType: func(_ host.Host, u transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater, _ network.ResourceManager) interface{} { + return u + }, + hostType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater, _ network.ResourceManager) interface{} { + return h + }, + networkType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater, _ network.ResourceManager) interface{} { return h.Network() }, - pskType: func(_ host.Host, _ transport.Upgrader, psk pnet.PSK, _ connmgr.ConnectionGater) interface{} { + pskType: func(_ host.Host, _ transport.Upgrader, psk pnet.PSK, _ connmgr.ConnectionGater, _ network.ResourceManager) interface{} { return psk }, - connGaterType: func(_ host.Host, _ transport.Upgrader, _ pnet.PSK, cg connmgr.ConnectionGater) interface{} { return cg }, - peerIDType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater) interface{} { + connGaterType: func(_ host.Host, _ transport.Upgrader, _ pnet.PSK, cg connmgr.ConnectionGater, _ network.ResourceManager) interface{} { + return cg + }, + peerIDType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater, _ network.ResourceManager) interface{} { return h.ID() }, - privKeyType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater) interface{} { + privKeyType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater, _ network.ResourceManager) interface{} { return h.Peerstore().PrivKey(h.ID()) }, - pubKeyType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater) interface{} { + pubKeyType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater, _ network.ResourceManager) interface{} { return h.Peerstore().PubKey(h.ID()) }, - pstoreType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater) interface{} { + pstoreType: func(h host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater, _ network.ResourceManager) interface{} { return h.Peerstore() }, + rcmgrType: func(_ host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater, rcmgr network.ResourceManager) interface{} { + return rcmgr + }, } func newArgTypeSet(types ...reflect.Type) map[reflect.Type]constructor {
config/muxer.go+11 −10 modified@@ -3,14 +3,15 @@ package config import ( "fmt" - "github.com/libp2p/go-libp2p-core/host" - "github.com/libp2p/go-libp2p-core/mux" - msmux "github.com/libp2p/go-stream-muxer-multistream" + + "github.com/libp2p/go-libp2p-core/network" + + "github.com/libp2p/go-libp2p-core/host" ) // MuxC is a stream multiplex transport constructor. -type MuxC func(h host.Host) (mux.Multiplexer, error) +type MuxC func(h host.Host) (network.Multiplexer, error) // MsMuxC is a tuple containing a multiplex transport constructor and a protocol // ID. @@ -25,8 +26,8 @@ var muxArgTypes = newArgTypeSet(hostType, networkType, peerIDType, pstoreType) // using reflection. func MuxerConstructor(m interface{}) (MuxC, error) { // Already constructed? - if t, ok := m.(mux.Multiplexer); ok { - return func(_ host.Host) (mux.Multiplexer, error) { + if t, ok := m.(network.Multiplexer); ok { + return func(_ host.Host) (network.Multiplexer, error) { return t, nil }, nil } @@ -35,16 +36,16 @@ func MuxerConstructor(m interface{}) (MuxC, error) { if err != nil { return nil, err } - return func(h host.Host) (mux.Multiplexer, error) { - t, err := ctor(h, nil, nil, nil) + return func(h host.Host) (network.Multiplexer, error) { + t, err := ctor(h, nil, nil, nil, nil) if err != nil { return nil, err } - return t.(mux.Multiplexer), nil + return t.(network.Multiplexer), nil }, nil } -func makeMuxer(h host.Host, tpts []MsMuxC) (mux.Multiplexer, error) { +func makeMuxer(h host.Host, tpts []MsMuxC) (network.Multiplexer, error) { muxMuxer := msmux.NewBlankTransport() transportSet := make(map[string]struct{}, len(tpts)) for _, tptC := range tpts {
config/muxer_test.go+7 −6 modified@@ -3,18 +3,19 @@ package config import ( "testing" + "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/peer" swarmt "github.com/libp2p/go-libp2p-swarm/testing" bhost "github.com/libp2p/go-libp2p/p2p/host/basic" - "github.com/libp2p/go-libp2p-core/mux" yamux "github.com/libp2p/go-libp2p-yamux" ) func TestMuxerSimple(t *testing.T) { // single - _, err := MuxerConstructor(func(_ peer.ID) mux.Multiplexer { return nil }) + _, err := MuxerConstructor(func(_ peer.ID) network.Multiplexer { return nil }) if err != nil { t.Fatal(err) } @@ -27,14 +28,14 @@ func TestMuxerByValue(t *testing.T) { } } func TestMuxerDuplicate(t *testing.T) { - _, err := MuxerConstructor(func(_ peer.ID, _ peer.ID) mux.Multiplexer { return nil }) + _, err := MuxerConstructor(func(_ peer.ID, _ peer.ID) network.Multiplexer { return nil }) if err != nil { t.Fatal(err) } } func TestMuxerError(t *testing.T) { - _, err := MuxerConstructor(func() (mux.Multiplexer, error) { return nil, nil }) + _, err := MuxerConstructor(func() (network.Multiplexer, error) { return nil, nil }) if err != nil { t.Fatal(err) } @@ -45,8 +46,8 @@ func TestMuxerBadTypes(t *testing.T) { func() error { return nil }, func() string { return "" }, func() {}, - func(string) mux.Multiplexer { return nil }, - func(string) (mux.Multiplexer, error) { return nil, nil }, + func(string) network.Multiplexer { return nil }, + func(string) (network.Multiplexer, error) { return nil, nil }, nil, "testing", } {
config/reflection_magic.go+6 −4 modified@@ -6,6 +6,8 @@ import ( "reflect" "runtime" + "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/pnet" "github.com/libp2p/go-libp2p-core/connmgr" @@ -80,7 +82,7 @@ func callConstructor(c reflect.Value, args []reflect.Value) (interface{}, error) return val, err } -type constructor func(h host.Host, u transport.Upgrader, psk pnet.PSK, cg connmgr.ConnectionGater) interface{} +type constructor func(host.Host, transport.Upgrader, pnet.PSK, connmgr.ConnectionGater, network.ResourceManager) interface{} func makeArgumentConstructors(fnType reflect.Type, argTypes map[reflect.Type]constructor) ([]constructor, error) { params := fnType.NumIn() @@ -131,7 +133,7 @@ func makeConstructor( tptType reflect.Type, argTypes map[reflect.Type]constructor, opts ...interface{}, -) (func(host.Host, transport.Upgrader, pnet.PSK, connmgr.ConnectionGater) (interface{}, error), error) { +) (func(host.Host, transport.Upgrader, pnet.PSK, connmgr.ConnectionGater, network.ResourceManager) (interface{}, error), error) { v := reflect.ValueOf(tpt) // avoid panicing on nil/zero value. if v == (reflect.Value{}) { @@ -155,10 +157,10 @@ func makeConstructor( return nil, err } - return func(h host.Host, u transport.Upgrader, psk pnet.PSK, cg connmgr.ConnectionGater) (interface{}, error) { + return func(h host.Host, u transport.Upgrader, psk pnet.PSK, cg connmgr.ConnectionGater, rcmgr network.ResourceManager) (interface{}, error) { arguments := make([]reflect.Value, 0, len(argConstructors)+len(opts)) for i, makeArg := range argConstructors { - if arg := makeArg(h, u, psk, cg); arg != nil { + if arg := makeArg(h, u, psk, cg, rcmgr); arg != nil { arguments = append(arguments, reflect.ValueOf(arg)) } else { // ValueOf an un-typed nil yields a zero reflect
config/security.go+1 −1 modified@@ -42,7 +42,7 @@ func SecurityConstructor(security interface{}) (SecC, error) { return nil, err } return func(h host.Host) (sec.SecureTransport, error) { - t, err := ctor(h, nil, nil, nil) + t, err := ctor(h, nil, nil, nil, nil) if err != nil { return nil, err }
config/transport.go+7 −6 modified@@ -3,14 +3,15 @@ package config import ( "github.com/libp2p/go-libp2p-core/connmgr" "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/pnet" "github.com/libp2p/go-libp2p-core/transport" ) // TptC is the type for libp2p transport constructors. You probably won't ever // implement this function interface directly. Instead, pass your transport // constructor to TransportConstructor. -type TptC func(host.Host, transport.Upgrader, pnet.PSK, connmgr.ConnectionGater) (transport.Transport, error) +type TptC func(host.Host, transport.Upgrader, pnet.PSK, connmgr.ConnectionGater, network.ResourceManager) (transport.Transport, error) var transportArgTypes = argTypes @@ -38,27 +39,27 @@ var transportArgTypes = argTypes func TransportConstructor(tpt interface{}, opts ...interface{}) (TptC, error) { // Already constructed? if t, ok := tpt.(transport.Transport); ok { - return func(_ host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater) (transport.Transport, error) { + return func(_ host.Host, _ transport.Upgrader, _ pnet.PSK, _ connmgr.ConnectionGater, _ network.ResourceManager) (transport.Transport, error) { return t, nil }, nil } ctor, err := makeConstructor(tpt, transportType, transportArgTypes, opts...) if err != nil { return nil, err } - return func(h host.Host, u transport.Upgrader, psk pnet.PSK, cg connmgr.ConnectionGater) (transport.Transport, error) { - t, err := ctor(h, u, psk, cg) + return func(h host.Host, u transport.Upgrader, psk pnet.PSK, cg connmgr.ConnectionGater, rcmgr network.ResourceManager) (transport.Transport, error) { + t, err := ctor(h, u, psk, cg, rcmgr) if err != nil { return nil, err } return t.(transport.Transport), nil }, nil } -func makeTransports(h host.Host, u transport.Upgrader, cg connmgr.ConnectionGater, psk pnet.PSK, tpts []TptC) ([]transport.Transport, error) { +func makeTransports(h host.Host, u transport.Upgrader, cg connmgr.ConnectionGater, psk pnet.PSK, rcmgr network.ResourceManager, tpts []TptC) ([]transport.Transport, error) { transports := make([]transport.Transport, len(tpts)) for i, tC := range tpts { - t, err := tC(h, u, psk, cg) + t, err := tC(h, u, psk, cg, rcmgr) if err != nil { return nil, err }
config/transport_test.go+2 −2 modified@@ -33,10 +33,10 @@ func TestConstructorWithOpts(t *testing.T) { var options []int c, err := TransportConstructor(func(_ transport.Upgrader, opts ...int) (transport.Transport, error) { options = opts - return tcp.NewTCPTransport(nil) + return tcp.NewTCPTransport(nil, nil) }, 42, 1337) require.NoError(t, err) - _, err = c(nil, nil, nil, nil) + _, err = c(nil, nil, nil, nil, nil) require.NoError(t, err) require.Equal(t, []int{42, 1337}, options) }
defaults.go+18 −0 modified@@ -10,6 +10,7 @@ import ( noise "github.com/libp2p/go-libp2p-noise" "github.com/libp2p/go-libp2p-peerstore/pstoremem" quic "github.com/libp2p/go-libp2p-quic-transport" + rcmgr "github.com/libp2p/go-libp2p-resource-manager" tls "github.com/libp2p/go-libp2p-tls" yamux "github.com/libp2p/go-libp2p-yamux" "github.com/libp2p/go-tcp-transport" @@ -85,6 +86,19 @@ var DefaultEnableRelay = func(cfg *Config) error { return cfg.Apply(EnableRelay()) } +var DefaultResourceManager = func(cfg *Config) error { + // Default memory limit: 1/8th of total memory, minimum 128MB, maximum 1GB + limiter := rcmgr.NewDefaultLimiter() + SetDefaultServiceLimits(limiter) + + mgr, err := rcmgr.NewResourceManager(limiter) + if err != nil { + return err + } + + return cfg.Apply(ResourceManager(mgr)) +} + // Complete list of default options and when to fallback on them. // // Please *DON'T* specify default options any other way. Putting this all here @@ -121,6 +135,10 @@ var defaults = []struct { fallback: func(cfg *Config) bool { return !cfg.RelayCustom }, opt: DefaultEnableRelay, }, + { + fallback: func(cfg *Config) bool { return cfg.ResourceManager == nil }, + opt: DefaultResourceManager, + }, } // Defaults configures libp2p to use the default options. Can be combined with
go.mod+13 −12 modified@@ -22,23 +22,24 @@ require ( github.com/libp2p/go-eventbus v0.2.1 github.com/libp2p/go-libp2p-asn-util v0.1.0 github.com/libp2p/go-libp2p-blankhost v0.3.0 - github.com/libp2p/go-libp2p-circuit v0.4.1-0.20220104091935-28fb8d25f785 - github.com/libp2p/go-libp2p-core v0.13.1-0.20220104083644-a3dd401efe36 - github.com/libp2p/go-libp2p-mplex v0.4.1 + github.com/libp2p/go-libp2p-circuit v0.6.0 + github.com/libp2p/go-libp2p-core v0.14.0 + github.com/libp2p/go-libp2p-mplex v0.5.0 github.com/libp2p/go-libp2p-nat v0.1.0 github.com/libp2p/go-libp2p-noise v0.3.0 github.com/libp2p/go-libp2p-peerstore v0.6.0 - github.com/libp2p/go-libp2p-quic-transport v0.15.2 - github.com/libp2p/go-libp2p-swarm v0.9.1-0.20220104091227-f776b7e504b1 - github.com/libp2p/go-libp2p-testing v0.6.1-0.20211214061856-c642a397cccd + github.com/libp2p/go-libp2p-quic-transport v0.16.0 + github.com/libp2p/go-libp2p-resource-manager v0.1.0 + github.com/libp2p/go-libp2p-swarm v0.10.0 + github.com/libp2p/go-libp2p-testing v0.7.0 github.com/libp2p/go-libp2p-tls v0.3.1 - github.com/libp2p/go-libp2p-transport-upgrader v0.6.1-0.20220104084635-5fc0a74b41f0 - github.com/libp2p/go-libp2p-yamux v0.7.0 + github.com/libp2p/go-libp2p-transport-upgrader v0.7.0 + github.com/libp2p/go-libp2p-yamux v0.8.0 github.com/libp2p/go-msgio v0.1.0 - github.com/libp2p/go-netroute v0.1.6 - github.com/libp2p/go-stream-muxer-multistream v0.3.0 - github.com/libp2p/go-tcp-transport v0.4.1-0.20220104085503-4ad75e6f32a5 - github.com/libp2p/go-ws-transport v0.5.1-0.20220104085536-0bac7beec89d + github.com/libp2p/go-netroute v0.2.0 + github.com/libp2p/go-stream-muxer-multistream v0.4.0 + github.com/libp2p/go-tcp-transport v0.5.0 + github.com/libp2p/go-ws-transport v0.6.0 github.com/libp2p/zeroconf/v2 v2.1.1 github.com/multiformats/go-multiaddr v0.5.0 github.com/multiformats/go-multiaddr-dns v0.3.1
go.sum+38 −33 modified@@ -334,7 +334,6 @@ github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscw github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= github.com/ipfs/go-log/v2 v2.3.0/go.mod h1:QqGoj30OTpnKaG/LKTGTxoP2mmQtjVMEnK72gynbe/g= -github.com/ipfs/go-log/v2 v2.4.0/go.mod h1:nPZnh7Cj7lwS3LpRU5Mwr2ol1c2gXIEXuF6aywqrtmo= github.com/ipfs/go-log/v2 v2.5.0 h1:+MhAooFd9XZNvR0i9FriKW6HB0ql7HNXUuflWtc0dd4= github.com/ipfs/go-log/v2 v2.5.0/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= @@ -368,8 +367,9 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -405,8 +405,8 @@ github.com/libp2p/go-libp2p-asn-util v0.1.0/go.mod h1:wu+AnM9Ii2KgO5jMmS1rz9dvzT github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= github.com/libp2p/go-libp2p-blankhost v0.3.0 h1:kTnLArltMabZlzY63pgGDA4kkUcLkBFSM98zBssn/IY= github.com/libp2p/go-libp2p-blankhost v0.3.0/go.mod h1:urPC+7U01nCGgJ3ZsV8jdwTp6Ji9ID0dMTvq+aJ+nZU= -github.com/libp2p/go-libp2p-circuit v0.4.1-0.20220104091935-28fb8d25f785 h1:zMKE9nQDjrfHoTFUMVAvY5GDYS7EYkr3oWNJjm729j0= -github.com/libp2p/go-libp2p-circuit v0.4.1-0.20220104091935-28fb8d25f785/go.mod h1:RsRUIXmHoYoSgM/Xi2dQY+YcWaBiK0oLpGkPwhsHNDk= +github.com/libp2p/go-libp2p-circuit v0.6.0 h1:rw/HlhmUB3OktS/Ygz6+2XABOmHKzZpPUuMNUMosj8w= +github.com/libp2p/go-libp2p-circuit v0.6.0/go.mod h1:kB8hY+zCpMeScyvFrKrGicRdid6vNXbunKE4rXATZ0M= github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= @@ -418,10 +418,11 @@ github.com/libp2p/go-libp2p-core v0.8.6/go.mod h1:dgHr0l0hIKfWpGpqAMbpo19pen9wJf github.com/libp2p/go-libp2p-core v0.10.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= github.com/libp2p/go-libp2p-core v0.11.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= github.com/libp2p/go-libp2p-core v0.12.0/go.mod h1:ECdxehoYosLYHgDDFa2N4yE8Y7aQRAMf0sX9mf2sbGg= -github.com/libp2p/go-libp2p-core v0.13.1-0.20220104083644-a3dd401efe36 h1:b/pMmgc5EV+dqSc+MjkX5xPa1nV6EKiOb0L0XT03Lic= -github.com/libp2p/go-libp2p-core v0.13.1-0.20220104083644-a3dd401efe36/go.mod h1:KlkHsZ0nKerWsXLZJm3LfFQwusI5k3iN4BgtYTE4IYE= -github.com/libp2p/go-libp2p-mplex v0.4.1 h1:/pyhkP1nLwjG3OM+VuaNJkQT/Pqq73WzB3aDN3Fx1sc= +github.com/libp2p/go-libp2p-core v0.14.0 h1:0kYSgiK/D7Eo28GTuRXo5YHsWwAisVpFCqCVPUd/vJs= +github.com/libp2p/go-libp2p-core v0.14.0/go.mod h1:tLasfcVdTXnixsLB0QYaT1syJOhsbrhG7q6pGrHtBg8= github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= +github.com/libp2p/go-libp2p-mplex v0.5.0 h1:vt3k4E4HSND9XH4Z8rUpacPJFSAgLOv6HDvG8W9Ks9E= +github.com/libp2p/go-libp2p-mplex v0.5.0/go.mod h1:eLImPJLkj3iG5t5lq68w3Vm5NAQ5BcKwrrb2VmOYb3M= github.com/libp2p/go-libp2p-nat v0.1.0 h1:vigUi2MEN+fwghe5ijpScxtbbDz+L/6y8XwlzYOJgSY= github.com/libp2p/go-libp2p-nat v0.1.0/go.mod h1:DQzAG+QbDYjN1/C3B6vXucLtz3u9rEonLVPtZVzQqks= github.com/libp2p/go-libp2p-noise v0.3.0 h1:NCVH7evhVt9njbTQshzT7N1S3Q6fjj9M11FCgfH5+cA= @@ -432,30 +433,32 @@ github.com/libp2p/go-libp2p-peerstore v0.6.0/go.mod h1:DGEmKdXrcYpK9Jha3sS7MhqYd github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= github.com/libp2p/go-libp2p-quic-transport v0.13.0/go.mod h1:39/ZWJ1TW/jx1iFkKzzUg00W6tDJh73FC0xYudjr7Hc= -github.com/libp2p/go-libp2p-quic-transport v0.15.2 h1:wHBEceRy+1/8Ec8dAIyr+/P7L2YefIGprPVy5LrMM+k= -github.com/libp2p/go-libp2p-quic-transport v0.15.2/go.mod h1:wv4uGwjcqe8Mhjj7N/Ic0aKjA+/10UnMlSzLO0yRpYQ= +github.com/libp2p/go-libp2p-quic-transport v0.16.0 h1:aVg9/jr+R2esov5sH7wkXrmYmqJiUjtLMLYX3L9KYdY= +github.com/libp2p/go-libp2p-quic-transport v0.16.0/go.mod h1:1BXjVMzr+w7EkPfiHkKnwsWjPjtfaNT0q8RS3tGDvEQ= +github.com/libp2p/go-libp2p-resource-manager v0.1.0 h1:tYpbhLPVC4egLavupAi9jGKKLeMemyGq5tnfBc8taBs= +github.com/libp2p/go-libp2p-resource-manager v0.1.0/go.mod h1:wJPNjeE4XQlxeidwqVY5G6DLOKqFK33u2n8blpl0I6Y= github.com/libp2p/go-libp2p-swarm v0.8.0/go.mod h1:sOMp6dPuqco0r0GHTzfVheVBh6UEL0L1lXUZ5ot2Fvc= -github.com/libp2p/go-libp2p-swarm v0.9.1-0.20220104091227-f776b7e504b1 h1:LsJE5h8hrv/WtmrxNi4WV+ctN0/ut7XxTl8hQu8VV2c= -github.com/libp2p/go-libp2p-swarm v0.9.1-0.20220104091227-f776b7e504b1/go.mod h1:BTllovQKjG9wYSVE9vP14kg7tSTW8ECcOlVXod2dgRs= +github.com/libp2p/go-libp2p-swarm v0.10.0 h1:1yr7UCwxCN92cw9g9Q+fnJSlk7lOB1RetoEewxhGVL0= +github.com/libp2p/go-libp2p-swarm v0.10.0/go.mod h1:71ceMcV6Rg/0rIQ97rsZWMzto1l9LnNquef+efcRbmA= github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= github.com/libp2p/go-libp2p-testing v0.5.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= -github.com/libp2p/go-libp2p-testing v0.6.0/go.mod h1:QBk8fqIL1XNcno/l3/hhaIEn4aLRijpYOR+zVjjlh+A= -github.com/libp2p/go-libp2p-testing v0.6.1-0.20211214061856-c642a397cccd h1:kGqONcelOVC+DxSuhhLYZ6itE64pKi6/Omxmu0kyp8I= -github.com/libp2p/go-libp2p-testing v0.6.1-0.20211214061856-c642a397cccd/go.mod h1:fi7jML2yROjVlnDhVwd45iGA6KP2Auaet/oCmyI/9u8= +github.com/libp2p/go-libp2p-testing v0.7.0 h1:9bfyhNINizxuLrKsenzGaZalXRXIaAEmx1BP/PzF1gM= +github.com/libp2p/go-libp2p-testing v0.7.0/go.mod h1:OLbdn9DbgdMwv00v+tlp1l3oe2Cl+FAjoWIA2pa0X6E= github.com/libp2p/go-libp2p-tls v0.3.0/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= github.com/libp2p/go-libp2p-tls v0.3.1 h1:lsE2zYte+rZCEOHF72J1Fg3XK3dGQyKvI6i5ehJfEp0= github.com/libp2p/go-libp2p-tls v0.3.1/go.mod h1:fwF5X6PWGxm6IDRwF3V8AVCCj/hOd5oFlg+wo2FxJDY= github.com/libp2p/go-libp2p-transport-upgrader v0.5.0/go.mod h1:Rc+XODlB3yce7dvFV4q/RmyJGsFcCZRkeZMu/Zdg0mo= -github.com/libp2p/go-libp2p-transport-upgrader v0.6.1-0.20220104084635-5fc0a74b41f0 h1:eD/QJCpcImYOUl6MdBuxMByVaEe5VMm463zJG6oUg9o= -github.com/libp2p/go-libp2p-transport-upgrader v0.6.1-0.20220104084635-5fc0a74b41f0/go.mod h1:ByIyNe8asQhgcyIHetb4f+UgV+hDrA8pQ3L/TgNs+RI= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.0 h1:ADnLrL7fC4Vy7HPjk9oGof7nDeTqGXuof85Ar6kin9Q= +github.com/libp2p/go-libp2p-transport-upgrader v0.7.0/go.mod h1:GIR2aTRp1J5yjVlkUoFqMkdobfob6RnAwYg/RZPhrzg= github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= -github.com/libp2p/go-libp2p-yamux v0.7.0 h1:bVXHbTj/XH4uBBsPrg26BlDABk5WYRlssY73P0SjhPc= -github.com/libp2p/go-libp2p-yamux v0.7.0/go.mod h1:fMyA0CsPfHkIuBU0wjRGrCjTBFiXTXxG0k5M4ETv+08= +github.com/libp2p/go-libp2p-yamux v0.8.0 h1:APQYlttIj+Rr5sfa6siojwsi0ZwcIh/exHIUl9hZr6o= +github.com/libp2p/go-libp2p-yamux v0.8.0/go.mod h1:yTkPgN2ib8FHyU1ZcVD7aelzyAqXXwEPbyx+aSKm9h8= github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= -github.com/libp2p/go-mplex v0.3.0 h1:U1T+vmCYJaEoDJPV1aq31N56hS+lJgb397GsylNSgrU= github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-mplex v0.4.0 h1:Ukkez9/4EOX5rTw4sHefNJp10dksftAA05ZgyjplUbM= +github.com/libp2p/go-mplex v0.4.0/go.mod h1:y26Lx+wNVtMYMaPu300Cbot5LkEZ4tJaNYeHeT9dh6E= github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= github.com/libp2p/go-msgio v0.1.0 h1:8Q7g/528ivAlfXTFWvWhVjTE8XG8sDTkRUKPYh9+5Q8= @@ -465,8 +468,8 @@ github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= github.com/libp2p/go-netroute v0.1.5/go.mod h1:V1SR3AaECRkEQCoFFzYwVYWvYIEtlxx89+O3qcpCl4A= -github.com/libp2p/go-netroute v0.1.6 h1:ruPJStbYyXVYGQ81uzEDzuvbYRLKRrLvTYd33yomC38= -github.com/libp2p/go-netroute v0.1.6/go.mod h1:AqhkMh0VuWmfgtxKPp3Oc1LdU5QSWS7wl0QLhSZqXxQ= +github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= +github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= @@ -477,26 +480,25 @@ github.com/libp2p/go-reuseport-transport v0.1.0 h1:C3PHeHjmnz8m6f0uydObj02tMEoi7 github.com/libp2p/go-reuseport-transport v0.1.0/go.mod h1:vev0C0uMkzriDY59yFHD9v+ujJvYmDQVLowvAjEOmfw= github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= github.com/libp2p/go-sockaddr v0.1.0/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-sockaddr v0.1.1 h1:yD80l2ZOdGksnOyHrhxDdTDFrf7Oy+v3FMVArIRgZxQ= -github.com/libp2p/go-sockaddr v0.1.1/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-stream-muxer-multistream v0.3.0 h1:TqnSHPJEIqDEO7h1wZZ0p3DXdvDSiLHQidKKUGZtiOY= github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= +github.com/libp2p/go-stream-muxer-multistream v0.4.0 h1:HsM/9OdtqnIzjVXcxTXjmqKrj3gJ8kacaOJwJS1ipaY= +github.com/libp2p/go-stream-muxer-multistream v0.4.0/go.mod h1:nb+dGViZleRP4XcyHuZSVrJCBl55nRBOMmiSL/dyziw= github.com/libp2p/go-tcp-transport v0.4.0/go.mod h1:0y52Rwrn4076xdJYu/51/qJIdxz+EWDAOG2S45sV3VI= -github.com/libp2p/go-tcp-transport v0.4.1-0.20220104085503-4ad75e6f32a5 h1:/x3GSszKipn1nlKY0C5at59fBLYyJeObd5gm32DrobM= -github.com/libp2p/go-tcp-transport v0.4.1-0.20220104085503-4ad75e6f32a5/go.mod h1:YPwlF5gW5BnFikKoQBuJeQkPXAn+z2wTzDpJKamkgjY= -github.com/libp2p/go-ws-transport v0.5.1-0.20220104085536-0bac7beec89d h1:2C9MSQsQ4teo3JRtBlN2CbS6xXC/Qk40kgMFO0rdjEM= -github.com/libp2p/go-ws-transport v0.5.1-0.20220104085536-0bac7beec89d/go.mod h1:aXV24UYVRjIiMXhs+/qygvfYklQmhUzmhVi5cSiQu5Y= +github.com/libp2p/go-tcp-transport v0.5.0 h1:3ZPW8HAuyRAuFzyabE0hSrCXKKSWzROnZZX7DtcIatY= +github.com/libp2p/go-tcp-transport v0.5.0/go.mod h1:UPPL0DIjQqiWRwVAb+CEQlaAG0rp/mCqJfIhFcLHc4Y= +github.com/libp2p/go-ws-transport v0.6.0 h1:326XBL6Q+5CQ2KtjXz32+eGu02W/Kz2+Fm4SpXdr0q4= +github.com/libp2p/go-ws-transport v0.6.0/go.mod h1:dXqtI9e2JV9FtF1NOtWVZSKXh5zXvnuwPXfj8GPBbYU= github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux/v2 v2.3.0 h1:luRV68GS1vqqr6EFUjtu1kr51d+IbW0gSowu8emYWAI= -github.com/libp2p/go-yamux/v2 v2.3.0/go.mod h1:iTU+lOIn/2h0AgKcL49clNTwfEw+WSfDYrXe05EyKIs= +github.com/libp2p/go-yamux/v3 v3.0.1 h1:lIdxHGVZ+y/EHgCrqGNt4Q+Mk9qu26MbOWH/yRw+Ihk= +github.com/libp2p/go-yamux/v3 v3.0.1/go.mod h1:s2LsDhHbh+RfCsQoICSYt58U2f8ijtPANFD8BmE74Bo= github.com/libp2p/zeroconf/v2 v2.1.1 h1:XAuSczA96MYkVwH+LqqqCUZb2yH3krobMJ1YE+0hG2s= github.com/libp2p/zeroconf/v2 v2.1.1/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= -github.com/lucas-clemente/quic-go v0.24.0 h1:ToR7SIIEdrgOhgVTHvPgdVRJfgVy+N0wQAagH7L4d5g= -github.com/lucas-clemente/quic-go v0.24.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= +github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc= +github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -508,6 +510,8 @@ github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2i github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= +github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -639,7 +643,6 @@ github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= @@ -648,6 +651,8 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
libp2p_test.go+1 −1 modified@@ -45,7 +45,7 @@ func TestTransportConstructor(t *testing.T) { _ connmgr.ConnectionGater, upgrader transport.Upgrader, ) transport.Transport { - tpt, err := tcp.NewTCPTransport(upgrader) + tpt, err := tcp.NewTCPTransport(upgrader, nil) require.NoError(t, err) return tpt }
limits.go+157 −0 added@@ -0,0 +1,157 @@ +package libp2p + +import ( + "github.com/libp2p/go-libp2p-core/protocol" + + "github.com/libp2p/go-libp2p/p2p/host/autonat" + relayv1 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv1/relay" + circuit "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/proto" + relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" + "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" + "github.com/libp2p/go-libp2p/p2p/protocol/identify" + "github.com/libp2p/go-libp2p/p2p/protocol/ping" + + rcmgr "github.com/libp2p/go-libp2p-resource-manager" +) + +// SetDefaultServiceLimits sets the default limits for bundled libp2p services +// +// More specifically this sets the following limits: +// - identify: +// 128 streams in, 128 streams out, 256 streams total, 4MB min, 64MB max svc memory +// 16/16/32 streams per peer +// - ping: +// 128 streams in, 128 sreams out, 256 streasms total, 4MB min, 64MB max svc memory +// 2/3/4 streams per peer +// - autonat +// 128 streams in, 128 streams out, 128 streams total, 4MB min, 64MB max svc memory +// 2/2/2 streams per peer +// - holepunch +// 128 streams in, 128 streams out, 128 streams total, 4MB min, 64MB max svc memory +// 2/2/2 streams per peer +// - relay v1 and v2 (separate services) +// 1024 streams in, 1024 streams out, 1024 streams total, 4MB min, 64MB max svc memory +// 64/64/64 streams per peer +func SetDefaultServiceLimits(limiter *rcmgr.BasicLimiter) { + if limiter.ServiceLimits == nil { + limiter.ServiceLimits = make(map[string]rcmgr.Limit) + } + if limiter.ServicePeerLimits == nil { + limiter.ServicePeerLimits = make(map[string]rcmgr.Limit) + } + if limiter.ProtocolLimits == nil { + limiter.ProtocolLimits = make(map[protocol.ID]rcmgr.Limit) + } + if limiter.ProtocolPeerLimits == nil { + limiter.ProtocolPeerLimits = make(map[protocol.ID]rcmgr.Limit) + } + + // identify + setServiceLimits(limiter, identify.ServiceName, + limiter.DefaultServiceLimits. + WithMemoryLimit(1, 4<<20, 64<<20). // max 64MB service memory + WithStreamLimit(128, 128, 256), // max 256 streams -- symmetric + peerLimit(16, 16, 32)) + + setProtocolLimits(limiter, identify.ID, + limiter.DefaultProtocolLimits.WithMemoryLimit(1, 4<<20, 32<<20), + peerLimit(16, 16, 32)) + setProtocolLimits(limiter, identify.IDPush, + limiter.DefaultProtocolLimits.WithMemoryLimit(1, 4<<20, 32<<20), + peerLimit(16, 16, 32)) + setProtocolLimits(limiter, identify.IDDelta, + limiter.DefaultProtocolLimits.WithMemoryLimit(1, 4<<20, 32<<20), + peerLimit(16, 16, 32)) + + // ping + setServiceLimits(limiter, ping.ServiceName, + limiter.DefaultServiceLimits. + WithMemoryLimit(1, 4<<20, 64<<20). // max 64MB service memory + WithStreamLimit(128, 128, 128), // max 128 streams - asymmetric + peerLimit(2, 3, 4)) + setProtocolLimits(limiter, ping.ID, + limiter.DefaultProtocolLimits.WithMemoryLimit(1, 4<<20, 64<<20), + peerLimit(2, 3, 4)) + + // autonat + setServiceLimits(limiter, autonat.ServiceName, + limiter.DefaultServiceLimits. + WithMemoryLimit(1, 4<<20, 64<<20). // max 64MB service memory + WithStreamLimit(128, 128, 128), // max 128 streams - asymmetric + peerLimit(2, 2, 2)) + setProtocolLimits(limiter, autonat.AutoNATProto, + limiter.DefaultProtocolLimits.WithMemoryLimit(1, 4<<20, 64<<20), + peerLimit(2, 2, 2)) + + // holepunch + setServiceLimits(limiter, holepunch.ServiceName, + limiter.DefaultServiceLimits. + WithMemoryLimit(1, 4<<20, 64<<20). // max 64MB service memory + WithStreamLimit(128, 128, 256), // max 256 streams - symmetric + peerLimit(2, 2, 2)) + setProtocolLimits(limiter, holepunch.Protocol, + limiter.DefaultProtocolLimits.WithMemoryLimit(1, 4<<20, 64<<20), + peerLimit(2, 2, 2)) + + // relay/v1 + setServiceLimits(limiter, relayv1.ServiceName, + limiter.DefaultServiceLimits. + WithMemoryLimit(1, 4<<20, 64<<20). // max 64MB service memory + WithStreamLimit(1024, 1024, 1024), // max 1024 streams - asymmetric + peerLimit(64, 64, 64)) + + // relay/v2 + setServiceLimits(limiter, relayv2.ServiceName, + limiter.DefaultServiceLimits. + WithMemoryLimit(1, 4<<20, 64<<20). // max 64MB service memory + WithStreamLimit(1024, 1024, 1024), // max 1024 streams - asymmetric + peerLimit(64, 64, 64)) + + // circuit protocols, both client and service + setProtocolLimits(limiter, circuit.ProtoIDv1, + limiter.DefaultProtocolLimits. + WithMemoryLimit(1, 4<<20, 64<<20). + WithStreamLimit(1280, 1280, 1280), + peerLimit(128, 128, 128)) + setProtocolLimits(limiter, circuit.ProtoIDv2Hop, + limiter.DefaultProtocolLimits. + WithMemoryLimit(1, 4<<20, 64<<20). + WithStreamLimit(1280, 1280, 1280), + peerLimit(128, 128, 128)) + setProtocolLimits(limiter, circuit.ProtoIDv2Stop, + limiter.DefaultProtocolLimits. + WithMemoryLimit(1, 4<<20, 64<<20). + WithStreamLimit(1280, 1280, 1280), + peerLimit(128, 128, 128)) + +} + +func setServiceLimits(limiter *rcmgr.BasicLimiter, svc string, limit rcmgr.Limit, peerLimit rcmgr.Limit) { + if _, ok := limiter.ServiceLimits[svc]; !ok { + limiter.ServiceLimits[svc] = limit + } + if _, ok := limiter.ServicePeerLimits[svc]; !ok { + limiter.ServicePeerLimits[svc] = peerLimit + } +} + +func setProtocolLimits(limiter *rcmgr.BasicLimiter, proto protocol.ID, limit rcmgr.Limit, peerLimit rcmgr.Limit) { + if _, ok := limiter.ProtocolLimits[proto]; !ok { + limiter.ProtocolLimits[proto] = limit + } + if _, ok := limiter.ProtocolPeerLimits[proto]; !ok { + limiter.ProtocolPeerLimits[proto] = peerLimit + } +} + +func peerLimit(numStreamsIn, numStreamsOut, numStreamsTotal int) rcmgr.Limit { + return &rcmgr.StaticLimit{ + // memory: 256kb for window buffers plus some change for message buffers per stream + Memory: int64(numStreamsTotal * (256<<10 + 16384)), + BaseLimit: rcmgr.BaseLimit{ + StreamsInbound: numStreamsIn, + StreamsOutbound: numStreamsOut, + Streams: numStreamsTotal, + }, + } +}
options.go+11 −0 modified@@ -346,6 +346,17 @@ func ConnectionGater(cg connmgr.ConnectionGater) Option { } } +// ResourceManager configures libp2p to use the given ResourceManager. +func ResourceManager(rcmgr network.ResourceManager) Option { + return func(cfg *Config) error { + if cfg.ResourceManager != nil { + return errors.New("cannot configure multiple resource managers") + } + cfg.ResourceManager = rcmgr + return nil + } +} + // NATPortMap configures libp2p to use the default NATManager. The default // NATManager will attempt to open a port in your network's firewall using UPnP. func NATPortMap() Option {
p2p/host/autonat/client.go+15 −1 modified@@ -36,12 +36,26 @@ func (c *client) DialBack(ctx context.Context, p peer.ID) (ma.Multiaddr, error) if err != nil { return nil, err } + + if err := s.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to autonat service: %s", err) + s.Reset() + return nil, err + } + + if err := s.Scope().ReserveMemory(maxMsgSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("error reserving memory for autonat stream: %s", err) + s.Reset() + return nil, err + } + defer s.Scope().ReleaseMemory(maxMsgSize) + s.SetDeadline(time.Now().Add(streamTimeout)) // Might as well just reset the stream. Once we get to this point, we // don't care about being nice. defer s.Close() - r := protoio.NewDelimitedReader(s, network.MessageSizeMax) + r := protoio.NewDelimitedReader(s, maxMsgSize) w := protoio.NewDelimitedWriter(s) req := newDialMessage(peer.AddrInfo{ID: c.h.ID(), Addrs: c.addrFunc()})
p2p/host/autonat/svc.go+20 −1 modified@@ -19,6 +19,12 @@ import ( var streamTimeout = 60 * time.Second +const ( + ServiceName = "libp2p.autonat" + + maxMsgSize = 4096 +) + // AutoNATService provides NAT autodetection services to other peers type autoNATService struct { instanceLock sync.Mutex @@ -45,13 +51,26 @@ func newAutoNATService(c *config) (*autoNATService, error) { } func (as *autoNATService) handleStream(s network.Stream) { + if err := s.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to autonat service: %s", err) + s.Reset() + return + } + + if err := s.Scope().ReserveMemory(maxMsgSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("error reserving memory for autonat stream: %s", err) + s.Reset() + return + } + defer s.Scope().ReleaseMemory(maxMsgSize) + s.SetDeadline(time.Now().Add(streamTimeout)) defer s.Close() pid := s.Conn().RemotePeer() log.Debugf("New stream from %s", pid.Pretty()) - r := protoio.NewDelimitedReader(s, network.MessageSizeMax) + r := protoio.NewDelimitedReader(s, maxMsgSize) w := protoio.NewDelimitedWriter(s) var req pb.Message
p2p/host/basic/basic_host.go+7 −2 modified@@ -405,7 +405,12 @@ func (h *BasicHost) newStreamHandler(s network.Stream) { } } - s.SetProtocol(protocol.ID(protoID)) + if err := s.SetProtocol(protocol.ID(protoID)); err != nil { + log.Debugf("error setting stream protocol: %s", err) + s.Reset() + return + } + log.Debugf("protocol negotiation took %s", took) go handle(protoID, s) @@ -1009,7 +1014,7 @@ func (h *BasicHost) SetAutoNat(a autonat.AutoNAT) { } } -// Return the host's AutoNAT service, if AutoNAT is enabled. +// GetAutoNat returns the host's AutoNAT service, if AutoNAT is enabled. func (h *BasicHost) GetAutoNat() autonat.AutoNAT { h.addrMu.Lock() defer h.addrMu.Unlock()
p2p/net/connmgr/connmgr_test.go+1 −0 modified@@ -795,6 +795,7 @@ func (m mockConn) Stat() network.ConnStats { retur func (m mockConn) ID() string { panic("implement me") } func (m mockConn) NewStream(ctx context.Context) (network.Stream, error) { panic("implement me") } func (m mockConn) GetStreams() []network.Stream { panic("implement me") } +func (m mockConn) Scope() network.ConnScope { panic("implement me") } func TestPeerInfoSorting(t *testing.T) { t.Run("starts with temporary connections", func(t *testing.T) {
p2p/net/mock/mock_conn.go+4 −0 modified@@ -195,3 +195,7 @@ func (c *conn) RemotePublicKey() ic.PubKey { func (c *conn) Stat() network.ConnStats { return c.stat } + +func (c *conn) Scope() network.ConnScope { + return network.NullScope +}
p2p/net/mock/mock_peernet.go+4 −0 modified@@ -368,3 +368,7 @@ func (pn *peernet) notifyAll(notification func(f network.Notifiee)) { pn.notifmu.Unlock() wg.Wait() } + +func (pn *peernet) ResourceManager() network.ResourceManager { + return network.NullResourceManager +}
p2p/net/mock/mock_stream.go+11 −7 modified@@ -10,7 +10,6 @@ import ( "sync/atomic" "time" - "github.com/libp2p/go-libp2p-core/mux" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/protocol" ) @@ -105,8 +104,9 @@ func (s *stream) Stat() network.Stats { return s.stat } -func (s *stream) SetProtocol(proto protocol.ID) { +func (s *stream) SetProtocol(proto protocol.ID) error { s.protocol.Store(proto) + return nil } func (s *stream) CloseWrite() error { @@ -132,8 +132,8 @@ func (s *stream) Close() error { func (s *stream) Reset() error { // Cancel any pending reads/writes with an error. - s.write.CloseWithError(mux.ErrReset) - s.read.CloseWithError(mux.ErrReset) + s.write.CloseWithError(network.ErrReset) + s.read.CloseWithError(network.ErrReset) select { case s.reset <- struct{}{}: @@ -236,7 +236,7 @@ func (s *stream) transport() { case s.reset <- struct{}{}: default: } - return mux.ErrReset + return network.ErrReset } if err := drainBuf(); err != nil { return err @@ -256,14 +256,14 @@ func (s *stream) transport() { // Reset takes precedent. select { case <-s.reset: - s.writeErr = mux.ErrReset + s.writeErr = network.ErrReset return default: } select { case <-s.reset: - s.writeErr = mux.ErrReset + s.writeErr = network.ErrReset return case <-s.close: if err := drainBuf(); err != nil { @@ -289,6 +289,10 @@ func (s *stream) transport() { } } +func (s *stream) Scope() network.StreamScope { + return network.NullScope +} + func (s *stream) cancelWrite(err error) { s.write.CloseWithError(err) s.writeErr = err
p2p/protocol/circuitv1/relay/relay.go+84 −25 modified@@ -25,6 +25,8 @@ var log = logging.Logger("relay") const ( ProtoID = "/libp2p/circuit/relay/0.1.0" + ServiceName = "libp2p.relay/v1" + StreamTimeout = time.Minute ConnectTimeout = 30 * time.Second HandshakeTimeout = time.Minute @@ -40,9 +42,10 @@ type Relay struct { ctx context.Context cancel context.CancelFunc - host host.Host - rc Resources - acl ACLFilter + host host.Host + rc Resources + acl ACLFilter + scope network.ResourceScopeSpan mx sync.Mutex conns map[peer.ID]int @@ -64,6 +67,17 @@ func NewRelay(h host.Host, opts ...Option) (*Relay, error) { } } + // get a scope for memory reservations at service level + err := h.Network().ResourceManager().ViewService(ServiceName, + func(s network.ServiceScope) error { + var err error + r.scope, err = s.BeginSpan() + return err + }) + if err != nil { + return nil, err + } + h.SetStreamHandler(ProtoID, r.handleStream) return r, nil @@ -72,19 +86,33 @@ func NewRelay(h host.Host, opts ...Option) (*Relay, error) { func (r *Relay) Close() error { if atomic.CompareAndSwapInt32(&r.closed, 0, 1) { r.host.RemoveStreamHandler(ProtoID) + r.scope.Done() r.cancel() } return nil } func (r *Relay) handleStream(s network.Stream) { - s.SetReadDeadline(time.Now().Add(StreamTimeout)) - log.Debugf("new relay stream from: %s", s.Conn().RemotePeer()) + if err := s.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to relay service: %s", err) + s.Reset() + return + } + + if err := s.Scope().ReserveMemory(maxMessageSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("error reserving memory for stream: %s", err) + s.Reset() + return + } + defer s.Scope().ReleaseMemory(maxMessageSize) + rd := util.NewDelimitedReader(s, maxMessageSize) defer rd.Close() + s.SetReadDeadline(time.Now().Add(StreamTimeout)) + var msg pb.CircuitRelay err := rd.ReadMsg(&msg) @@ -108,55 +136,74 @@ func (r *Relay) handleStream(s network.Stream) { } func (r *Relay) handleHopStream(s network.Stream, msg *pb.CircuitRelay) { + span, err := r.scope.BeginSpan() + if err != nil { + log.Debugf("failed to begin relay transaction: %s", err) + r.handleError(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) + return + } + + fail := func(code pb.CircuitRelay_Status) { + span.Done() + r.handleError(s, code) + } + + // reserve buffers for the relay + if err := span.ReserveMemory(2*r.rc.BufferSize, network.ReservationPriorityHigh); err != nil { + log.Debugf("error reserving memory for relay: %s", err) + fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) + return + } + src, err := peerToPeerInfo(msg.GetSrcPeer()) if err != nil { - r.handleError(s, pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) + fail(pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) return } if src.ID != s.Conn().RemotePeer() { - r.handleError(s, pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) + fail(pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) return } dest, err := peerToPeerInfo(msg.GetDstPeer()) if err != nil { - r.handleError(s, pb.CircuitRelay_HOP_DST_MULTIADDR_INVALID) + fail(pb.CircuitRelay_HOP_DST_MULTIADDR_INVALID) return } if dest.ID == r.host.ID() { - r.handleError(s, pb.CircuitRelay_HOP_CANT_RELAY_TO_SELF) + fail(pb.CircuitRelay_HOP_CANT_RELAY_TO_SELF) return } if r.acl != nil && !r.acl.AllowHop(src.ID, dest.ID) { log.Debugf("refusing hop from %s to %s; ACL refused", src.ID, dest.ID) - r.handleError(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) + fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) return } r.mx.Lock() if r.active >= r.rc.MaxCircuits { r.mx.Unlock() log.Debugf("refusing connection from %s to %s; too many active circuits", src.ID, dest.ID) - r.handleError(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) + fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) return } srcConns := r.conns[src.ID] if srcConns >= r.rc.MaxCircuitsPerPeer { r.mx.Unlock() log.Debugf("refusing connection from %s to %s; too many connections from %s", src.ID, dest.ID, src) - r.handleError(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) + fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) return } destConns := r.conns[dest.ID] if destConns >= r.rc.MaxCircuitsPerPeer { r.mx.Unlock() log.Debugf("refusing connection from %s to %s; too many connecitons to %s", src.ID, dest.ID, dest.ID) - r.handleError(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) + fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) return } @@ -166,6 +213,7 @@ func (r *Relay) handleHopStream(s network.Stream, msg *pb.CircuitRelay) { r.mx.Unlock() cleanup := func() { + span.Done() r.mx.Lock() r.active-- r.rmConn(src.ID) @@ -190,7 +238,26 @@ func (r *Relay) handleHopStream(s network.Stream, msg *pb.CircuitRelay) { return } + fail = func(code pb.CircuitRelay_Status) { + bs.Reset() + cleanup() + r.handleError(s, code) + } + + if err := bs.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to relay service: %s", err) + fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) + return + } + // stop handshake + if err := bs.Scope().ReserveMemory(maxMessageSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("failed to reserve memory for stream: %s", err) + fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) + return + } + defer bs.Scope().ReleaseMemory(maxMessageSize) + rd := util.NewDelimitedReader(bs, maxMessageSize) wr := util.NewDelimitedWriter(bs) defer rd.Close() @@ -203,9 +270,7 @@ func (r *Relay) handleHopStream(s network.Stream, msg *pb.CircuitRelay) { err = wr.WriteMsg(msg) if err != nil { log.Debugf("error writing stop handshake: %s", err.Error()) - bs.Reset() - r.handleError(s, pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) - cleanup() + fail(pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) return } @@ -214,25 +279,19 @@ func (r *Relay) handleHopStream(s network.Stream, msg *pb.CircuitRelay) { err = rd.ReadMsg(msg) if err != nil { log.Debugf("error reading stop response: %s", err.Error()) - bs.Reset() - r.handleError(s, pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) - cleanup() + fail(pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) return } if msg.GetType() != pb.CircuitRelay_STATUS { log.Debugf("unexpected relay stop response: not a status message (%d)", msg.GetType()) - bs.Reset() - r.handleError(s, pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) - cleanup() + fail(pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) return } if msg.GetCode() != pb.CircuitRelay_SUCCESS { log.Debugf("relay stop failure: %d", msg.GetCode()) - bs.Reset() - r.handleError(s, msg.GetCode()) - cleanup() + fail(msg.GetCode()) return }
p2p/protocol/circuitv2/client/dial.go+12 −0 modified@@ -144,6 +144,12 @@ func (c *Client) dialPeer(ctx context.Context, relay, dest peer.AddrInfo) (*Conn } func (c *Client) connectV2(s network.Stream, dest peer.AddrInfo) (*Conn, error) { + if err := s.Scope().ReserveMemory(maxMessageSize, network.ReservationPriorityAlways); err != nil { + s.Reset() + return nil, err + } + defer s.Scope().ReleaseMemory(maxMessageSize) + rd := util.NewDelimitedReader(s, maxMessageSize) wr := util.NewDelimitedWriter(s) defer rd.Close() @@ -196,6 +202,12 @@ func (c *Client) connectV2(s network.Stream, dest peer.AddrInfo) (*Conn, error) } func (c *Client) connectV1(s network.Stream, dest peer.AddrInfo) (*Conn, error) { + if err := s.Scope().ReserveMemory(maxMessageSize, network.ReservationPriorityAlways); err != nil { + s.Reset() + return nil, err + } + defer s.Scope().ReleaseMemory(maxMessageSize) + rd := util.NewDelimitedReader(s, maxMessageSize) wr := util.NewDelimitedWriter(s) defer rd.Close()
p2p/protocol/circuitv2/client/transport.go+10 −3 modified@@ -50,14 +50,21 @@ var _ transport.Transport = (*Client)(nil) var _ io.Closer = (*Client)(nil) func (c *Client) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (transport.CapableConn, error) { + connScope, err := c.host.Network().ResourceManager().OpenConnection(network.DirOutbound, false) + if err != nil { + return nil, err + } + if err := connScope.SetPeer(p); err != nil { + connScope.Done() + return nil, err + } conn, err := c.dial(ctx, a, p) if err != nil { + connScope.Done() return nil, err } - conn.tagHop() - - return c.upgrader.Upgrade(ctx, c, conn, network.DirOutbound, p) + return c.upgrader.Upgrade(ctx, c, conn, network.DirOutbound, p, connScope) } func (c *Client) CanDial(addr ma.Multiaddr) bool {
p2p/protocol/circuitv2/relay/relay.go+79 −20 modified@@ -24,6 +24,8 @@ import ( ) const ( + ServiceName = "libp2p.relay/v2" + ReservationTagWeight = 10 StreamTimeout = time.Minute @@ -48,6 +50,7 @@ type Relay struct { rc Resources acl ACLFilter constraints *constraints + scope network.ResourceScopeSpan mx sync.Mutex rsvp map[peer.ID]time.Time @@ -77,6 +80,17 @@ func New(h host.Host, opts ...Option) (*Relay, error) { } } + // get a scope for memory reservations at service level + err := h.Network().ResourceManager().ViewService(ServiceName, + func(s network.ServiceScope) error { + var err error + r.scope, err = s.BeginSpan() + return err + }) + if err != nil { + return nil, err + } + r.constraints = newConstraints(&r.rc) r.selfAddr = ma.StringCast(fmt.Sprintf("/p2p/%s", h.ID())) @@ -93,6 +107,7 @@ func New(h host.Host, opts ...Option) (*Relay, error) { func (r *Relay) Close() error { if atomic.CompareAndSwapUint32(&r.closed, 0, 1) { r.host.RemoveStreamHandler(proto.ProtoIDv2Hop) + r.scope.Done() r.cancel() r.mx.Lock() for p := range r.rsvp { @@ -104,13 +119,26 @@ func (r *Relay) Close() error { } func (r *Relay) handleStream(s network.Stream) { - s.SetReadDeadline(time.Now().Add(StreamTimeout)) - log.Infof("new relay stream from: %s", s.Conn().RemotePeer()) + if err := s.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to relay service: %s", err) + s.Reset() + return + } + + if err := s.Scope().ReserveMemory(maxMessageSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("error reserving memory for stream: %s", err) + s.Reset() + return + } + defer s.Scope().ReleaseMemory(maxMessageSize) + rd := util.NewDelimitedReader(s, maxMessageSize) defer rd.Close() + s.SetReadDeadline(time.Now().Add(StreamTimeout)) + var msg pbv2.HopMessage err := rd.ReadMsg(&msg) @@ -184,21 +212,40 @@ func (r *Relay) handleConnect(s network.Stream, msg *pbv2.HopMessage) { src := s.Conn().RemotePeer() a := s.Conn().RemoteMultiaddr() + span, err := r.scope.BeginSpan() + if err != nil { + log.Debugf("failed to begin relay transaction: %s", err) + r.handleError(s, pbv2.Status_RESOURCE_LIMIT_EXCEEDED) + return + } + + fail := func(status pbv2.Status) { + span.Done() + r.handleError(s, status) + } + + // reserve buffers for the relay + if err := span.ReserveMemory(2*r.rc.BufferSize, network.ReservationPriorityHigh); err != nil { + log.Debugf("error reserving memory for relay: %s", err) + fail(pbv2.Status_RESOURCE_LIMIT_EXCEEDED) + return + } + if isRelayAddr(a) { log.Debugf("refusing connection from %s; connection attempt over relay connection") - r.handleError(s, pbv2.Status_PERMISSION_DENIED) + fail(pbv2.Status_PERMISSION_DENIED) return } dest, err := util.PeerToPeerInfoV2(msg.GetPeer()) if err != nil { - r.handleError(s, pbv2.Status_MALFORMED_MESSAGE) + fail(pbv2.Status_MALFORMED_MESSAGE) return } if r.acl != nil && !r.acl.AllowConnect(src, s.Conn().RemoteMultiaddr(), dest.ID) { log.Debugf("refusing connection from %s to %s; permission denied", src, dest.ID) - r.handleError(s, pbv2.Status_PERMISSION_DENIED) + fail(pbv2.Status_PERMISSION_DENIED) return } @@ -207,23 +254,23 @@ func (r *Relay) handleConnect(s network.Stream, msg *pbv2.HopMessage) { if !rsvp { r.mx.Unlock() log.Debugf("refusing connection from %s to %s; no reservation", src, dest.ID) - r.handleError(s, pbv2.Status_NO_RESERVATION) + fail(pbv2.Status_NO_RESERVATION) return } srcConns := r.conns[src] if srcConns >= r.rc.MaxCircuits { r.mx.Unlock() log.Debugf("refusing connection from %s to %s; too many connections from %s", src, dest.ID, src) - r.handleError(s, pbv2.Status_RESOURCE_LIMIT_EXCEEDED) + fail(pbv2.Status_RESOURCE_LIMIT_EXCEEDED) return } destConns := r.conns[dest.ID] if destConns >= r.rc.MaxCircuits { r.mx.Unlock() log.Debugf("refusing connection from %s to %s; too many connecitons to %s", src, dest.ID, dest.ID) - r.handleError(s, pbv2.Status_RESOURCE_LIMIT_EXCEEDED) + fail(pbv2.Status_RESOURCE_LIMIT_EXCEEDED) return } @@ -232,6 +279,7 @@ func (r *Relay) handleConnect(s network.Stream, msg *pbv2.HopMessage) { r.mx.Unlock() cleanup := func() { + span.Done() r.mx.Lock() r.rmConn(src) r.rmConn(dest.ID) @@ -251,7 +299,26 @@ func (r *Relay) handleConnect(s network.Stream, msg *pbv2.HopMessage) { return } + fail = func(status pbv2.Status) { + bs.Reset() + cleanup() + r.handleError(s, status) + } + + if err := bs.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to relay service: %s", err) + fail(pbv2.Status_RESOURCE_LIMIT_EXCEEDED) + return + } + // handshake + if err := bs.Scope().ReserveMemory(maxMessageSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("erro reserving memory for stream: %s", err) + fail(pbv2.Status_RESOURCE_LIMIT_EXCEEDED) + return + } + defer bs.Scope().ReleaseMemory(maxMessageSize) + rd := util.NewDelimitedReader(bs, maxMessageSize) wr := util.NewDelimitedWriter(bs) defer rd.Close() @@ -266,9 +333,7 @@ func (r *Relay) handleConnect(s network.Stream, msg *pbv2.HopMessage) { err = wr.WriteMsg(&stopmsg) if err != nil { log.Debugf("error writing stop handshake") - bs.Reset() - cleanup() - r.handleError(s, pbv2.Status_CONNECTION_FAILED) + fail(pbv2.Status_CONNECTION_FAILED) return } @@ -277,25 +342,19 @@ func (r *Relay) handleConnect(s network.Stream, msg *pbv2.HopMessage) { err = rd.ReadMsg(&stopmsg) if err != nil { log.Debugf("error reading stop response: %s", err.Error()) - bs.Reset() - cleanup() - r.handleError(s, pbv2.Status_CONNECTION_FAILED) + fail(pbv2.Status_CONNECTION_FAILED) return } if t := stopmsg.GetType(); t != pbv2.StopMessage_STATUS { log.Debugf("unexpected stop response; not a status message (%d)", t) - bs.Reset() - cleanup() - r.handleError(s, pbv2.Status_CONNECTION_FAILED) + fail(pbv2.Status_CONNECTION_FAILED) return } if status := stopmsg.GetStatus(); status != pbv2.Status_OK { log.Debugf("relay stop failure: %d", status) - bs.Reset() - cleanup() - r.handleError(s, pbv2.Status_CONNECTION_FAILED) + fail(pbv2.Status_CONNECTION_FAILED) return }
p2p/protocol/circuitv2/relay/relay_test.go+4 −5 modified@@ -18,7 +18,6 @@ import ( "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/host" - "github.com/libp2p/go-libp2p-core/mux" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" @@ -60,7 +59,7 @@ func getNetHosts(t *testing.T, ctx context.Context, n int) (hosts []host.Host, u upgrader := swarmt.GenUpgrader(t, netw) upgraders = append(upgraders, upgrader) - tpt, err := tcp.NewTCPTransport(upgrader) + tpt, err := tcp.NewTCPTransport(upgrader, nil) if err != nil { t.Fatal(err) } @@ -246,12 +245,12 @@ func TestRelayLimitTime(t *testing.T) { if n > 0 { t.Fatalf("expected to write 0 bytes, wrote %d", n) } - if err != mux.ErrReset { + if err != network.ErrReset { t.Fatalf("expected reset, but got %s", err) } err = <-rch - if err != mux.ErrReset { + if err != network.ErrReset { t.Fatalf("expected reset, but got %s", err) } } @@ -279,7 +278,7 @@ func TestRelayLimitData(t *testing.T) { } n, err := s.Read(buf) - if err != mux.ErrReset { + if err != network.ErrReset { t.Fatalf("expected reset but got %s", err) } rch <- n
p2p/protocol/holepunch/coordination.go+34 −3 modified@@ -28,6 +28,8 @@ var StreamTimeout = 1 * time.Minute // TODO Should we have options for these ? const ( + ServiceName = "libp2p.holepunch" + maxMsgSize = 4 * 1024 // 4K dialTimeout = 5 * time.Second maxRetries = 3 @@ -146,15 +148,30 @@ func (hs *Service) Close() error { func (hs *Service) initiateHolePunch(rp peer.ID) ([]ma.Multiaddr, time.Duration, error) { hpCtx := network.WithUseTransient(hs.ctx, "hole-punch") sCtx := network.WithNoDial(hpCtx, "hole-punch") + str, err := hs.host.NewStream(sCtx, rp, Protocol) if err != nil { return nil, 0, fmt.Errorf("failed to open hole-punching stream: %w", err) } defer str.Close() - str.SetDeadline(time.Now().Add(StreamTimeout)) + + if err := str.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to holepunch service: %s", err) + str.Reset() + return nil, 0, err + } + + if err := str.Scope().ReserveMemory(maxMsgSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("error reserving memory for stream: %s, err") + str.Reset() + return nil, 0, err + } + defer str.Scope().ReleaseMemory(maxMsgSize) w := protoio.NewDelimitedWriter(str) + rd := protoio.NewDelimitedReader(str, maxMsgSize) + str.SetDeadline(time.Now().Add(StreamTimeout)) // send a CONNECT and start RTT measurement. msg := &pb.HolePunch{ Type: pb.HolePunch_CONNECT.Enum(), @@ -168,7 +185,6 @@ func (hs *Service) initiateHolePunch(rp peer.ID) ([]ma.Multiaddr, time.Duration, } // wait for a CONNECT message from the remote peer - rd := protoio.NewDelimitedReader(str, maxMsgSize) msg.Reset() if err := rd.ReadMsg(msg); err != nil { str.Reset() @@ -318,12 +334,20 @@ func (hs *Service) incomingHolePunch(s network.Stream) (rtt time.Duration, addrs return 0, nil, errors.New("rejecting hole punch request, as we don't have any public addresses") } - s.SetDeadline(time.Now().Add(StreamTimeout)) + if err := s.Scope().ReserveMemory(maxMsgSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("error reserving memory for stream: %s, err") + return 0, nil, err + } + defer s.Scope().ReleaseMemory(maxMsgSize) + wr := protoio.NewDelimitedWriter(s) rd := protoio.NewDelimitedReader(s, maxMsgSize) // Read Connect message msg := new(pb.HolePunch) + + s.SetDeadline(time.Now().Add(StreamTimeout)) + if err := rd.ReadMsg(msg); err != nil { return 0, nil, fmt.Errorf("failed to read message from initator: %w", err) } @@ -366,6 +390,13 @@ func (hs *Service) handleNewStream(s network.Stream) { s.Reset() return } + + if err := s.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to holepunch service: %s", err) + s.Reset() + return + } + rp := s.Conn().RemotePeer() rtt, addrs, err := hs.incomingHolePunch(s) if err != nil {
p2p/protocol/identify/id_delta.go+16 −1 modified@@ -15,13 +15,28 @@ import ( const IDDelta = "/p2p/id/delta/1.0.0" +const deltaMsgSize = 2048 + // deltaHandler handles incoming delta updates from peers. func (ids *idService) deltaHandler(s network.Stream) { + if err := s.Scope().SetService(ServiceName); err != nil { + log.Warnf("error attaching stream to identify service: %s", err) + s.Reset() + return + } + + if err := s.Scope().ReserveMemory(deltaMsgSize, network.ReservationPriorityAlways); err != nil { + log.Warnf("error reserving memory for identify stream: %s", err) + s.Reset() + return + } + defer s.Scope().ReleaseMemory(deltaMsgSize) + _ = s.SetReadDeadline(time.Now().Add(StreamReadTimeout)) c := s.Conn() - r := protoio.NewDelimitedReader(s, 2048) + r := protoio.NewDelimitedReader(s, deltaMsgSize) mes := pb.Identify{} if err := r.ReadMsg(&mes); err != nil { log.Warn("error reading identify message: ", err)
p2p/protocol/identify/id.go+26 −1 modified@@ -41,6 +41,8 @@ const ID = "/ipfs/id/1.0.0" // 0.4.17 which asserted an exact version match. const LibP2PVersion = "ipfs/0.1.0" +const ServiceName = "libp2p.identify" + // StreamReadTimeout is the read timeout on all incoming Identify family streams. var StreamReadTimeout = 60 * time.Second @@ -357,7 +359,11 @@ func (ids *idService) identifyConn(c network.Conn) error { ids.removeConn(c) return err } - s.SetProtocol(ID) + + if err := s.SetProtocol(ID); err != nil { + log.Warnf("error setting identify protocol for stream: %s", err) + s.Reset() + } // ok give the response to our handler. if err := msmux.SelectProtoOrFail(ID, s); err != nil { @@ -370,6 +376,12 @@ func (ids *idService) identifyConn(c network.Conn) error { } func (ids *idService) sendIdentifyResp(s network.Stream) { + if err := s.Scope().SetService(ServiceName); err != nil { + log.Warnf("error attaching stream to identify service: %s", err) + s.Reset() + return + } + defer s.Close() c := s.Conn() @@ -402,6 +414,19 @@ func (ids *idService) sendIdentifyResp(s network.Stream) { } func (ids *idService) handleIdentifyResponse(s network.Stream) error { + if err := s.Scope().SetService(ServiceName); err != nil { + log.Warnf("error attaching stream to identify service: %s", err) + s.Reset() + return err + } + + if err := s.Scope().ReserveMemory(signedIDSize, network.ReservationPriorityAlways); err != nil { + log.Warnf("error reserving memory for identify stream: %s", err) + s.Reset() + return err + } + defer s.Scope().ReleaseMemory(signedIDSize) + _ = s.SetReadDeadline(time.Now().Add(StreamReadTimeout)) c := s.Conn()
p2p/protocol/ping/ping.go+49 −10 modified@@ -9,18 +9,22 @@ import ( u "github.com/ipfs/go-ipfs-util" logging "github.com/ipfs/go-log/v2" + pool "github.com/libp2p/go-buffer-pool" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" ) var log = logging.Logger("ping") -const PingSize = 32 +const ( + PingSize = 32 + pingTimeout = time.Second * 60 -const ID = "/ipfs/ping/1.0.0" + ID = "/ipfs/ping/1.0.0" -const pingTimeout = time.Second * 60 + ServiceName = "libp2p.ping" +) type PingService struct { Host host.Host @@ -33,7 +37,21 @@ func NewPingService(h host.Host) *PingService { } func (p *PingService) PingHandler(s network.Stream) { - buf := make([]byte, PingSize) + if err := s.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to ping service: %s", err) + s.Reset() + return + } + + if err := s.Scope().ReserveMemory(PingSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("error reserving memory for ping stream: %s", err) + s.Reset() + return + } + defer s.Scope().ReleaseMemory(PingSize) + + buf := pool.Get(PingSize) + defer pool.Put(buf) errCh := make(chan error, 1) defer close(errCh) @@ -81,15 +99,25 @@ func (ps *PingService) Ping(ctx context.Context, p peer.ID) <-chan Result { return Ping(ctx, ps.Host, p) } +func pingError(err error) chan Result { + ch := make(chan Result, 1) + ch <- Result{Error: err} + close(ch) + return ch +} + // Ping pings the remote peer until the context is canceled, returning a stream // of RTTs or errors. func Ping(ctx context.Context, h host.Host, p peer.ID) <-chan Result { s, err := h.NewStream(network.WithUseTransient(ctx, "ping"), p, ID) if err != nil { - ch := make(chan Result, 1) - ch <- Result{Error: err} - close(ch) - return ch + return pingError(err) + } + + if err := s.Scope().SetService(ServiceName); err != nil { + log.Debugf("error attaching stream to ping service: %s", err) + s.Reset() + return pingError(err) } ctx, cancel := context.WithCancel(ctx) @@ -130,7 +158,16 @@ func Ping(ctx context.Context, h host.Host, p peer.ID) <-chan Result { } func ping(s network.Stream) (time.Duration, error) { - buf := make([]byte, PingSize) + if err := s.Scope().ReserveMemory(2*PingSize, network.ReservationPriorityAlways); err != nil { + log.Debugf("error reserving memory for ping stream: %s", err) + s.Reset() + return 0, err + } + defer s.Scope().ReleaseMemory(2 * PingSize) + + buf := pool.Get(PingSize) + defer pool.Put(buf) + u.NewTimeSeededRand().Read(buf) before := time.Now() @@ -139,7 +176,9 @@ func ping(s network.Stream) (time.Duration, error) { return 0, err } - rbuf := make([]byte, PingSize) + rbuf := pool.Get(PingSize) + defer pool.Put(rbuf) + _, err = io.ReadFull(s, rbuf) if err != nil { return 0, err
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-j7qp-mfxf-8xjwghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-23492ghsaADVISORY
- docs.libp2p.io/reference/dos-mitigationghsaWEB
- docs.libp2p.io/reference/dos-mitigation/mitrex_refsource_MISC
- github.com/libp2p/go-libp2p/commit/15d7dfbf54264ead8e6f49ca658d79c90635e2deghsax_refsource_MISCWEB
- github.com/libp2p/go-libp2p/security/advisories/GHSA-j7qp-mfxf-8xjwghsax_refsource_CONFIRMWEB
- github.com/libp2p/js-libp2p/security/advisories/GHSA-f44q-634c-jvwvghsaWEB
- github.com/libp2p/rust-libp2p/security/advisories/GHSA-jvgw-gccv-q5p8ghsaWEB
- pkg.go.dev/vuln/GO-2022-1148ghsaWEB
News mentions
0No linked articles in our index yet.