Skip to content

Commit 7e1b304

Browse files
committed
Allow allowlisted peers to bypass gater blocks
1 parent e8e8946 commit 7e1b304

File tree

5 files changed

+122
-2
lines changed

5 files changed

+122
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- Decrease MaxBytesSize to `5MB` to increase compatibility with public nodes. ([#3030](https://github.com/evstack/ev-node/pull/3030))
1818
- Proper counting of `DASubmitterPendingBlobs` metrics. [#3038](https://github.com/evstack/ev-node/pull/3038)
1919
- Replace `go-header` store by `ev-node` store. This avoid duplication of all blocks in `go-header` and `ev-node` store. Thanks to the cached store from #3030, this should improve p2p performance as well.
20+
- Allow explicitly configured peers to bypass libp2p gater blocks caused by go-header peer scoring.
2021

2122
## v1.0.0-rc.1
2223

pkg/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ type P2PConfig struct {
275275
ListenAddress string `mapstructure:"listen_address" yaml:"listen_address" comment:"Address to listen for incoming connections (host:port)"`
276276
Peers string `mapstructure:"peers" yaml:"peers" comment:"Comma-separated list of peers to connect to"`
277277
BlockedPeers string `mapstructure:"blocked_peers" yaml:"blocked_peers" comment:"Comma-separated list of peer IDs to block from connecting"`
278-
AllowedPeers string `mapstructure:"allowed_peers" yaml:"allowed_peers" comment:"Comma-separated list of peer IDs to allow connections from"`
278+
AllowedPeers string `mapstructure:"allowed_peers" yaml:"allowed_peers" comment:"Comma-separated list of peer multiaddrs to always allow (overrides peer ID blocks)"`
279279
}
280280

281281
// SignerConfig contains all signer configuration parameters

pkg/p2p/allowlist_gater.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package p2p
2+
3+
import (
4+
"github.com/libp2p/go-libp2p/core/control"
5+
"github.com/libp2p/go-libp2p/core/network"
6+
"github.com/libp2p/go-libp2p/core/peer"
7+
"github.com/libp2p/go-libp2p/p2p/net/conngater"
8+
ma "github.com/multiformats/go-multiaddr"
9+
)
10+
11+
// allowlistGater wraps a BasicConnectionGater and permits specific peers even if blocked.
12+
type allowlistGater struct {
13+
allowlist map[peer.ID]struct{}
14+
base *conngater.BasicConnectionGater
15+
}
16+
17+
func newAllowlistGater(base *conngater.BasicConnectionGater, allowlist map[peer.ID]struct{}) *allowlistGater {
18+
return &allowlistGater{
19+
allowlist: allowlist,
20+
base: base,
21+
}
22+
}
23+
24+
func (g *allowlistGater) isAllowed(id peer.ID) bool {
25+
_, ok := g.allowlist[id]
26+
return ok
27+
}
28+
29+
func (g *allowlistGater) InterceptPeerDial(p peer.ID) (allow bool) {
30+
if g.isAllowed(p) {
31+
return true
32+
}
33+
return g.base.InterceptPeerDial(p)
34+
}
35+
36+
func (g *allowlistGater) InterceptAddrDial(p peer.ID, a ma.Multiaddr) (allow bool) {
37+
return g.base.InterceptAddrDial(p, a)
38+
}
39+
40+
func (g *allowlistGater) InterceptAccept(cma network.ConnMultiaddrs) (allow bool) {
41+
return g.base.InterceptAccept(cma)
42+
}
43+
44+
func (g *allowlistGater) InterceptSecured(dir network.Direction, p peer.ID, cma network.ConnMultiaddrs) (allow bool) {
45+
if g.isAllowed(p) {
46+
return true
47+
}
48+
return g.base.InterceptSecured(dir, p, cma)
49+
}
50+
51+
func (g *allowlistGater) InterceptUpgraded(conn network.Conn) (allow bool, reason control.DisconnectReason) {
52+
return g.base.InterceptUpgraded(conn)
53+
}

pkg/p2p/allowlist_gater_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package p2p
2+
3+
import (
4+
"testing"
5+
6+
"github.com/ipfs/go-datastore"
7+
dssync "github.com/ipfs/go-datastore/sync"
8+
"github.com/libp2p/go-libp2p/core/network"
9+
"github.com/libp2p/go-libp2p/core/peer"
10+
"github.com/libp2p/go-libp2p/p2p/net/conngater"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestAllowlistGaterOverridesPeerBlock(t *testing.T) {
15+
ds := dssync.MutexWrap(datastore.NewMapDatastore())
16+
base, err := conngater.NewBasicConnectionGater(ds)
17+
require.NoError(t, err)
18+
19+
allowedID, err := peer.Decode("12D3KooWBY6qMG2KAcDdgH7ED2Pg4UzhuwnSy8CSZdCKDG911iyP")
20+
require.NoError(t, err)
21+
blockedID, err := peer.Decode("12D3KooWM1NFkZozoatQi3JvFE57eBaX56mNgBA68Lk5MTPxBE4U")
22+
require.NoError(t, err)
23+
24+
require.NoError(t, base.BlockPeer(allowedID))
25+
require.NoError(t, base.BlockPeer(blockedID))
26+
27+
gater := newAllowlistGater(base, map[peer.ID]struct{}{allowedID: {}})
28+
require.True(t, gater.InterceptPeerDial(allowedID))
29+
require.False(t, gater.InterceptPeerDial(blockedID))
30+
require.True(t, gater.InterceptSecured(network.DirInbound, allowedID, nil))
31+
require.False(t, gater.InterceptSecured(network.DirInbound, blockedID, nil))
32+
}

pkg/p2p/client.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/ipfs/go-datastore"
1212
libp2p "github.com/libp2p/go-libp2p"
13+
"github.com/libp2p/go-libp2p/core/connmgr"
1314
dht "github.com/libp2p/go-libp2p-kad-dht"
1415
pubsub "github.com/libp2p/go-libp2p-pubsub"
1516
"github.com/libp2p/go-libp2p/core/crypto"
@@ -53,6 +54,8 @@ type Client struct {
5354
dht *dht.IpfsDHT
5455
disc *discovery.RoutingDiscovery
5556
gater *conngater.BasicConnectionGater
57+
// hostGater controls libp2p connection gating for the host.
58+
hostGater connmgr.ConnectionGater
5659
ps *pubsub.PubSub
5760

5861
metrics *Metrics
@@ -127,6 +130,7 @@ func (c *Client) Start(ctx context.Context) error {
127130
return c.startWithHost(ctx, c.host)
128131
}
129132

133+
c.configureHostGater()
130134
h, err := c.listen()
131135
if err != nil {
132136
return err
@@ -245,7 +249,15 @@ func (c *Client) listen() (host.Host, error) {
245249
return nil, err
246250
}
247251

248-
return libp2p.New(libp2p.ListenAddrs(maddr), libp2p.Identity(c.privKey), libp2p.ConnectionGater(c.gater))
252+
hostGater := c.hostGater
253+
if hostGater == nil {
254+
hostGater = c.gater
255+
}
256+
return libp2p.New(
257+
libp2p.ListenAddrs(maddr),
258+
libp2p.Identity(c.privKey),
259+
libp2p.ConnectionGater(hostGater),
260+
)
249261
}
250262

251263
func (c *Client) setupDHT(ctx context.Context) error {
@@ -384,6 +396,28 @@ func (c *Client) parseAddrInfoList(addrInfoStr string) []peer.AddrInfo {
384396
return addrs
385397
}
386398

399+
func (c *Client) configureHostGater() {
400+
allowed := c.allowedPeerIDs()
401+
if len(allowed) == 0 {
402+
c.hostGater = c.gater
403+
return
404+
}
405+
c.hostGater = newAllowlistGater(c.gater, allowed)
406+
}
407+
408+
func (c *Client) allowedPeerIDs() map[peer.ID]struct{} {
409+
allowedAddrs := c.parseAddrInfoList(c.conf.AllowedPeers)
410+
if len(allowedAddrs) == 0 {
411+
return nil
412+
}
413+
414+
allowed := make(map[peer.ID]struct{}, len(allowedAddrs))
415+
for _, addr := range allowedAddrs {
416+
allowed[addr.ID] = struct{}{}
417+
}
418+
return allowed
419+
}
420+
387421
// getNamespace returns unique string identifying ORU network.
388422
//
389423
// It is used to advertise/find peers in libp2p DHT.

0 commit comments

Comments
 (0)