diff --git a/components/p2p/component.go b/components/p2p/component.go
index f9fb9c791..54a6cf7a2 100644
--- a/components/p2p/component.go
+++ b/components/p2p/component.go
@@ -8,11 +8,9 @@ import (
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
- p2pbhost "github.com/libp2p/go-libp2p/p2p/host/basic"
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
"github.com/multiformats/go-multiaddr"
- mamask "github.com/whyrusleeping/multiaddr-filter"
"go.uber.org/dig"
"github.com/iotaledger/hive.go/app"
@@ -21,7 +19,6 @@ import (
"github.com/iotaledger/hive.go/db"
"github.com/iotaledger/hive.go/ierrors"
"github.com/iotaledger/hive.go/kvstore"
- "github.com/iotaledger/hive.go/lo"
"github.com/iotaledger/iota-core/pkg/daemon"
"github.com/iotaledger/iota-core/pkg/network"
"github.com/iotaledger/iota-core/pkg/network/p2p"
@@ -218,7 +215,7 @@ func provide(c *dig.Container) error {
libp2p.NATPortMap(),
libp2p.DisableRelay(),
// Define a custom address factory to inject external addresses to the DHT advertisements.
- libp2p.AddrsFactory(publicOnlyAddresses(ParamsP2P.Autopeering.ExternalMultiAddresses)),
+ libp2p.AddrsFactory(externalAddresses(ParamsP2P.Autopeering.ExternalMultiAddresses, ParamsP2P.Autopeering.AllowLocalIPs)),
)
if err != nil {
Component.LogFatalf("unable to initialize libp2p host: %s", err)
@@ -246,27 +243,11 @@ func provide(c *dig.Container) error {
}
return c.Provide(func(inDeps p2pManagerDeps) network.Manager {
- peersMultiAddresses, err := getMultiAddrsFromString(ParamsPeers.BootstrapPeers)
- if err != nil {
- Component.LogFatalf("Failed to parse bootstrapPeers param: %s", err)
- }
-
- for _, multiAddr := range peersMultiAddresses {
- bootstrapPeer, err := network.NewPeerFromMultiAddr(multiAddr)
- if err != nil {
- Component.LogFatalf("Failed to parse bootstrap peer multiaddress: %s", err)
- }
-
- if err := inDeps.PeerDB.UpdatePeer(bootstrapPeer); err != nil {
- Component.LogErrorf("Failed to update bootstrap peer: %s", err)
- }
- }
-
onBlockSentCallback := func() {
inDeps.P2PMetrics.OutgoingBlocks.Add(1)
}
- return p2p.NewManager(Component.Logger, inDeps.Host, inDeps.PeerDB, ParamsP2P.Autopeering.MaxPeers, onBlockSentCallback)
+ return p2p.NewManager(Component.Logger, inDeps.Host, inDeps.PeerDB, ParamsP2P.Autopeering.MaxPeers, ParamsP2P.Autopeering.AllowLocalIPs, onBlockSentCallback)
})
}
@@ -307,7 +288,7 @@ func run() error {
if err := Component.Daemon().BackgroundWorker(Component.Name, func(ctx context.Context) {
defer deps.NetworkManager.Shutdown()
- if err := deps.NetworkManager.Start(ctx, deps.Protocol.LatestAPI().ProtocolParameters().NetworkName()); err != nil {
+ if err := deps.NetworkManager.Start(ctx, deps.Protocol.LatestAPI().ProtocolParameters().NetworkName(), bootstrapPeers()); err != nil {
Component.LogFatalf("Failed to start p2p manager: %s", err)
}
@@ -322,6 +303,24 @@ func run() error {
return nil
}
+func bootstrapPeers() []peer.AddrInfo {
+ peersMultiAddresses, err := getMultiAddrsFromString(ParamsP2P.Autopeering.BootstrapPeers)
+ if err != nil {
+ Component.LogFatalf("Failed to parse bootstrapPeers param: %s", err)
+ }
+
+ addrInfos := make([]peer.AddrInfo, 0, len(peersMultiAddresses))
+ for _, multiAddr := range peersMultiAddresses {
+ addrInfo, err := peer.AddrInfoFromP2pAddr(multiAddr)
+ if err != nil {
+ Component.LogFatalf("Failed to parse bootstrap peer multiaddress: %s", err)
+ }
+ addrInfos = append(addrInfos, *addrInfo)
+ }
+
+ return addrInfos
+}
+
func getMultiAddrsFromString(peers []string) ([]multiaddr.Multiaddr, error) {
peersMultiAddresses := make([]multiaddr.Multiaddr, 0, len(peers))
@@ -356,36 +355,7 @@ func connectConfigKnownPeers() {
}
}
-// Based on https://github.com/ipfs/kubo/blob/master/config/profile.go
-// defaultServerFilters has is a list of IPv4 and IPv6 prefixes that are private, local only, or unrouteable.
-// according to https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
-// and https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
-var reservedFilters = []string{
- "/ip4/0.0.0.0/ipcidr/32",
- "/ip4/10.0.0.0/ipcidr/8",
- "/ip4/100.64.0.0/ipcidr/10",
- "/ip4/127.0.0.0/ipcidr/8",
- "/ip4/169.254.0.0/ipcidr/16",
- "/ip4/172.16.0.0/ipcidr/12",
- "/ip4/192.0.0.0/ipcidr/24",
- "/ip4/192.0.2.0/ipcidr/24",
- "/ip4/192.168.0.0/ipcidr/16",
- "/ip4/192.31.196.0/ipcidr/24",
- "/ip4/192.52.193.0/ipcidr/24",
- "/ip4/198.18.0.0/ipcidr/15",
- "/ip4/198.51.100.0/ipcidr/24",
- "/ip4/203.0.113.0/ipcidr/24",
- "/ip4/240.0.0.0/ipcidr/4",
-
- "/ip6/::1/ipcidr/64",
- "/ip6/100::/ipcidr/64",
- "/ip6/2001:2::/ipcidr/48",
- "/ip6/2001:db8::/ipcidr/32",
- "/ip6/fc00::/ipcidr/7",
- "/ip6/fe80::/ipcidr/10",
-}
-
-func publicOnlyAddresses(additionalMultiaddresses []string) p2pbhost.AddrsFactory {
+func externalAddresses(additionalMultiaddresses []string, allowLocalNetworks bool) network.AddressFilter {
var externalMultiAddrs []multiaddr.Multiaddr
// Add the external multi addresses to the list of addresses to be announced.
@@ -400,27 +370,9 @@ func publicOnlyAddresses(additionalMultiaddresses []string) p2pbhost.AddrsFactor
}
}
- // Create a filter that blocks localhost and reserved addresses.
- filters := multiaddr.NewFilters()
- for _, addr := range reservedFilters {
- f, err := mamask.NewMask(addr)
- if err != nil {
- Component.LogPanicf("unable to parse ip mask filter %s: %s", addr, err)
- }
- filters.AddFilter(*f, multiaddr.ActionDeny)
- }
+ publicFilter := network.PublicOnlyAddressesFilter(allowLocalNetworks)
return func(addresses []multiaddr.Multiaddr) []multiaddr.Multiaddr {
- filteredAddresses := lo.Filter(append(addresses, externalMultiAddrs...), func(m multiaddr.Multiaddr) bool {
- blocked := filters.AddrBlocked(m)
- if blocked {
- Component.LogTracef("Filtered out address %s", m)
- }
- return !blocked
- })
-
- Component.LogTracef("Announcing addresses: %v", filteredAddresses)
-
- return filteredAddresses
+ return publicFilter(append(addresses, externalMultiAddrs...))
}
}
diff --git a/components/p2p/params.go b/components/p2p/params.go
index f34cf3d1f..907df3678 100644
--- a/components/p2p/params.go
+++ b/components/p2p/params.go
@@ -29,6 +29,12 @@ type ParametersP2P struct {
// MaxPeers defines the max number of auto-peer connections. Set to 0 to disable auto-peering.
MaxPeers int `default:"5" usage:"the max number of auto-peer connections. Set to 0 to disable auto-peering."`
+ // Defines the peers to be used as discovery for other peers (CLI).
+ BootstrapPeers []string `default:"" usage:"peers to be used as discovery for other peers"`
+
+ // AllowLocalIPs defines if local IPs are allowed to be used for autopeering.
+ AllowLocalIPs bool `default:"false" usage:"allow local IPs to be used for autopeering"`
+
// ExternalMultiAddress defines additional p2p multiaddresses to be advertised via DHT.
ExternalMultiAddresses []string `default:"" usage:"external reacheable multi addresses advertised to the network"`
}
@@ -45,8 +51,6 @@ type ParametersPeers struct {
Peers []string `default:"" usage:"the static peers this node should retain a connection to (CLI)"`
// Defines the aliases of the static peers (must be the same length like CfgP2PPeers) (CLI).
PeerAliases []string `default:"" usage:"the aliases of the static peers (must be the same amount like \"p2p.peers\""`
- // Defines the peers to be used as discovery for other peers (CLI).
- BootstrapPeers []string `default:"" usage:"peers to be used as discovery for other peers (CLI)"`
}
var (
diff --git a/config_defaults.json b/config_defaults.json
index 643c36554..f514d7c6f 100644
--- a/config_defaults.json
+++ b/config_defaults.json
@@ -29,6 +29,8 @@
"identityPrivateKey": "",
"autopeering": {
"maxPeers": 5,
+ "bootstrapPeers": [],
+ "allowLocalIPs": false,
"externalMultiAddresses": []
},
"db": {
diff --git a/documentation/configuration.md b/documentation/configuration.md
index 1b642ae86..b8230dbb2 100644
--- a/documentation/configuration.md
+++ b/documentation/configuration.md
@@ -110,10 +110,12 @@ Example:
### Autopeering
-| Name | Description | Type | Default value |
-| ---------------------- | -------------------------------------------------------------------------- | ----- | ------------- |
-| maxPeers | The max number of auto-peer connections. Set to 0 to disable auto-peering. | int | 5 |
-| externalMultiAddresses | External reacheable multi addresses advertised to the network | array | |
+| Name | Description | Type | Default value |
+| ---------------------- | -------------------------------------------------------------------------- | ------- | ------------- |
+| maxPeers | The max number of auto-peer connections. Set to 0 to disable auto-peering. | int | 5 |
+| bootstrapPeers | Peers to be used as discovery for other peers | array | |
+| allowLocalIPs | Allow local IPs to be used for autopeering | boolean | false |
+| externalMultiAddresses | External reacheable multi addresses advertised to the network | array | |
### Database
@@ -137,6 +139,8 @@ Example:
"identityPrivateKey": "",
"autopeering": {
"maxPeers": 5,
+ "bootstrapPeers": [],
+ "allowLocalIPs": false,
"externalMultiAddresses": []
},
"db": {
diff --git a/pkg/network/filter.go b/pkg/network/filter.go
new file mode 100644
index 000000000..edb8210bb
--- /dev/null
+++ b/pkg/network/filter.go
@@ -0,0 +1,70 @@
+package network
+
+import (
+ "fmt"
+
+ "github.com/multiformats/go-multiaddr"
+ mamask "github.com/whyrusleeping/multiaddr-filter"
+
+ "github.com/iotaledger/hive.go/lo"
+)
+
+// Based on https://github.com/ipfs/kubo/blob/master/config/profile.go
+// defaultServerFilters has is a list of IPv4 and IPv6 prefixes that are private, local only, or unrouteable.
+// according to https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+// and https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
+var reservedFilters = []string{
+ "/ip4/0.0.0.0/ipcidr/32",
+ "/ip4/100.64.0.0/ipcidr/10",
+ "/ip4/127.0.0.0/ipcidr/8",
+ "/ip4/169.254.0.0/ipcidr/16",
+ "/ip4/192.0.0.0/ipcidr/24",
+ "/ip4/192.0.2.0/ipcidr/24",
+ "/ip4/192.31.196.0/ipcidr/24",
+ "/ip4/192.52.193.0/ipcidr/24",
+ "/ip4/198.18.0.0/ipcidr/15",
+ "/ip4/198.51.100.0/ipcidr/24",
+ "/ip4/203.0.113.0/ipcidr/24",
+ "/ip4/240.0.0.0/ipcidr/4",
+
+ "/ip6/::/ipcidr/128",
+ "/ip6/::1/ipcidr/128",
+ "/ip6/100::/ipcidr/64",
+ "/ip6/2001:2::/ipcidr/48",
+ "/ip6/2001:db8::/ipcidr/32",
+}
+
+var localNetworks = []string{
+ "/ip4/10.0.0.0/ipcidr/8",
+ "/ip4/172.16.0.0/ipcidr/12",
+ "/ip4/192.168.0.0/ipcidr/16",
+
+ "/ip6/fc00::/ipcidr/7",
+ "/ip6/fe80::/ipcidr/10",
+}
+
+type AddressFilter = func([]multiaddr.Multiaddr) []multiaddr.Multiaddr
+
+func PublicOnlyAddressesFilter(allowLocalNetworks bool) AddressFilter {
+ // Create a filter that blocks localhost and reserved addresses.
+ filters := multiaddr.NewFilters()
+
+ filtersToApply := reservedFilters
+ if !allowLocalNetworks {
+ filtersToApply = append(filtersToApply, localNetworks...)
+ }
+
+ for _, addr := range filtersToApply {
+ f, err := mamask.NewMask(addr)
+ if err != nil {
+ panic(fmt.Sprintf("unable to parse ip mask filter %s: %s", addr, err))
+ }
+ filters.AddFilter(*f, multiaddr.ActionDeny)
+ }
+
+ return func(addresses []multiaddr.Multiaddr) []multiaddr.Multiaddr {
+ return lo.Filter(addresses, func(m multiaddr.Multiaddr) bool {
+ return !filters.AddrBlocked(m)
+ })
+ }
+}
diff --git a/pkg/network/manager.go b/pkg/network/manager.go
index 648cdfd9e..36c99cd29 100644
--- a/pkg/network/manager.go
+++ b/pkg/network/manager.go
@@ -47,6 +47,6 @@ type Manager interface {
P2PHost() host.Host
- Start(ctx context.Context, networkID string) error
+ Start(ctx context.Context, networkID string, bootstrapPeers []peer.AddrInfo) error
Shutdown()
}
diff --git a/pkg/network/p2p/autopeering/autopeering.go b/pkg/network/p2p/autopeering/autopeering.go
index 41976e1c2..33af4c9a9 100644
--- a/pkg/network/p2p/autopeering/autopeering.go
+++ b/pkg/network/p2p/autopeering/autopeering.go
@@ -11,6 +11,7 @@ import (
dht "github.com/libp2p/go-libp2p-kad-dht"
"github.com/libp2p/go-libp2p/core/discovery"
"github.com/libp2p/go-libp2p/core/host"
+ "github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
"github.com/libp2p/go-libp2p/p2p/discovery/routing"
"github.com/libp2p/go-libp2p/p2p/discovery/util"
@@ -33,6 +34,7 @@ type Manager struct {
ctx context.Context
stopFunc context.CancelFunc
routingDiscovery *routing.RoutingDiscovery
+ addrFilter network.AddressFilter
advertiseLock sync.Mutex
advertiseCtx context.Context
@@ -40,13 +42,14 @@ type Manager struct {
}
// NewManager creates a new autopeering manager.
-func NewManager(maxPeers int, networkManager network.Manager, host host.Host, peerDB *network.DB, logger log.Logger) *Manager {
+func NewManager(maxPeers int, networkManager network.Manager, host host.Host, peerDB *network.DB, addressFilter network.AddressFilter, logger log.Logger) *Manager {
return &Manager{
maxPeers: maxPeers,
networkManager: networkManager,
host: host,
peerDB: peerDB,
logger: logger.NewChildLogger("Autopeering"),
+ addrFilter: addressFilter,
}
}
@@ -55,7 +58,7 @@ func (m *Manager) MaxNeighbors() int {
}
// Start starts the autopeering manager.
-func (m *Manager) Start(ctx context.Context, networkID string) (err error) {
+func (m *Manager) Start(ctx context.Context, networkID string, bootstrapPeers []peer.AddrInfo) (err error) {
//nolint:contextcheck
m.startOnce.Do(func() {
// We will use /iota/networkID/kad/1.0.0 for the DHT protocol.
@@ -64,7 +67,15 @@ func (m *Manager) Start(ctx context.Context, networkID string) (err error) {
extension := protocol.ID(fmt.Sprintf("/%s", networkID))
m.namespace = fmt.Sprintf("%s%s/%s", prefix, extension, network.CoreProtocolID)
dhtCtx, dhtCancel := context.WithCancel(ctx)
- kademliaDHT, innerErr := dht.New(dhtCtx, m.host, dht.Mode(dht.ModeServer), dht.ProtocolPrefix(prefix), dht.ProtocolExtension(extension))
+ kademliaDHT, innerErr := dht.New(
+ dhtCtx,
+ m.host,
+ dht.Mode(dht.ModeServer),
+ dht.ProtocolPrefix(prefix),
+ dht.ProtocolExtension(extension),
+ dht.AddressFilter(m.addrFilter),
+ dht.BootstrapPeers(bootstrapPeers...),
+ )
if innerErr != nil {
err = innerErr
dhtCancel()
@@ -105,7 +116,8 @@ func (m *Manager) Start(ctx context.Context, networkID string) (err error) {
onGossipNeighborRemovedHook := m.networkManager.OnNeighborRemoved(func(_ network.Neighbor) {
m.startAdvertisingIfNeeded()
})
- onGossipNeighborAddedHook := m.networkManager.OnNeighborAdded(func(_ network.Neighbor) {
+ onGossipNeighborAddedHook := m.networkManager.OnNeighborAdded(func(neighbor network.Neighbor) {
+ m.logger.LogInfof("Gossip layer successfully connected with the peer %s", neighbor.Peer())
m.stopAdvertisingItNotNeeded()
})
@@ -253,13 +265,26 @@ func (m *Manager) discoverAndDialPeers() {
continue
}
- m.logger.LogDebugf("Found peer: %s", peerAddrInfo)
+ peerInfo := m.filteredPeerAddrInfo(&peerAddrInfo)
+ if len(peerInfo.Addrs) == 0 {
+ m.logger.LogWarnf("Filtered out peer %s because it has no public reachable addresses", peerAddrInfo)
+ continue
+ }
+
+ m.logger.LogInfof("Found peer: %s", peerInfo)
- peer := network.NewPeerFromAddrInfo(&peerAddrInfo)
- if err := m.networkManager.DialPeer(m.ctx, peer); err != nil {
+ p := network.NewPeerFromAddrInfo(peerInfo)
+ if err := m.networkManager.DialPeer(m.ctx, p); err != nil {
m.logger.LogWarnf("Failed to dial peer %s: %s", peerAddrInfo, err)
} else {
peersToFind--
}
}
}
+
+func (m *Manager) filteredPeerAddrInfo(peerAddrInfo *peer.AddrInfo) *peer.AddrInfo {
+ return &peer.AddrInfo{
+ ID: peerAddrInfo.ID,
+ Addrs: m.addrFilter(peerAddrInfo.Addrs),
+ }
+}
diff --git a/pkg/network/p2p/manager.go b/pkg/network/p2p/manager.go
index 0e0813772..26bc27f46 100644
--- a/pkg/network/p2p/manager.go
+++ b/pkg/network/p2p/manager.go
@@ -50,6 +50,7 @@ type Manager struct {
protocolHandlerMutex syncutils.RWMutex
onBlockSentCallback func()
+ addrFilter network.AddressFilter
autoPeering *autopeering.Manager
manualPeering *manualpeering.Manager
}
@@ -57,7 +58,7 @@ type Manager struct {
var _ network.Manager = (*Manager)(nil)
// NewManager creates a new Manager.
-func NewManager(logger log.Logger, libp2pHost host.Host, peerDB *network.DB, maxAutopeeringPeers int, onBlockSentCallback func()) *Manager {
+func NewManager(logger log.Logger, libp2pHost host.Host, peerDB *network.DB, maxAutopeeringPeers int, allowLocalAutopeering bool, onBlockSentCallback func()) *Manager {
m := &Manager{
logger: logger,
libp2pHost: libp2pHost,
@@ -66,9 +67,10 @@ func NewManager(logger log.Logger, libp2pHost host.Host, peerDB *network.DB, max
neighborRemoved: event.New1[network.Neighbor](),
neighbors: shrinkingmap.New[peer.ID, *neighbor](),
onBlockSentCallback: onBlockSentCallback,
+ addrFilter: network.PublicOnlyAddressesFilter(allowLocalAutopeering),
}
- m.autoPeering = autopeering.NewManager(maxAutopeeringPeers, m, libp2pHost, peerDB, logger)
+ m.autoPeering = autopeering.NewManager(maxAutopeeringPeers, m, libp2pHost, peerDB, m.addrFilter, logger)
m.manualPeering = manualpeering.NewManager(m, logger)
return m
@@ -123,7 +125,7 @@ func (m *Manager) DialPeer(ctx context.Context, peer *network.Peer) error {
}
// Adds the peer's multiaddresses to the peerstore, so that they can be used for dialing.
- m.libp2pHost.Peerstore().AddAddrs(peer.ID, peer.PeerAddresses, peerstore.ConnectedAddrTTL)
+ m.libp2pHost.Peerstore().AddAddrs(peer.ID, m.addrFilter(peer.PeerAddresses), peerstore.ConnectedAddrTTL)
cancelCtx := ctx
stream, err := m.P2PHost().NewStream(cancelCtx, peer.ID, network.CoreProtocolID)
@@ -156,13 +158,13 @@ func (m *Manager) DialPeer(ctx context.Context, peer *network.Peer) error {
}
// Start starts the manager and initiates manual- and autopeering.
-func (m *Manager) Start(ctx context.Context, networkID string) error {
+func (m *Manager) Start(ctx context.Context, networkID string, bootstrapPeers []peer.AddrInfo) error {
m.ctx = ctx
m.manualPeering.Start()
if m.autoPeering.MaxNeighbors() > 0 {
- return m.autoPeering.Start(ctx, networkID)
+ return m.autoPeering.Start(ctx, networkID, bootstrapPeers)
}
return nil
diff --git a/pkg/network/p2p/manualpeering/manualpeering.go b/pkg/network/p2p/manualpeering/manualpeering.go
index 5e6f281a6..6280d8fdb 100644
--- a/pkg/network/p2p/manualpeering/manualpeering.go
+++ b/pkg/network/p2p/manualpeering/manualpeering.go
@@ -236,7 +236,6 @@ func (m *Manager) onGossipNeighborRemoved(neighbor network.Neighbor) {
func (m *Manager) onGossipNeighborAdded(neighbor network.Neighbor) {
m.changeNeighborStatus(neighbor)
- m.logger.LogInfof("Gossip layer successfully connected with the peer %s", neighbor.Peer())
}
func (m *Manager) changeNeighborStatus(neighbor network.Neighbor) {
diff --git a/tools/docker-network/.env b/tools/docker-network/.env
index 2fb926159..e965fe92e 100644
--- a/tools/docker-network/.env
+++ b/tools/docker-network/.env
@@ -10,10 +10,11 @@ COMMON_CONFIG="
--protocol.snapshot.path=/app/data/snapshot.bin
--restAPI.publicRoutes=/health,/api/routes,/api/core/v3/info,/api/core/v3/network*,/api/core/v3/blocks*,/api/core/v3/transactions*,/api/core/v3/commitments*,/api/core/v3/outputs*,/api/core/v3/accounts*,/api/core/v3/validators*,/api/core/v3/rewards*,/api/core/v3/committee*,/api/debug/v2/*,/api/indexer/v2/*,/api/mqtt/v2,/api/blockissuer/v1/*,/api/management/v1/*
--debugAPI.enabled=false
+--p2p.autopeering.allowLocalIPs=true
"
AUTOPEERING_CONFIG="
---p2p.bootstrapPeers=/dns/node-1-validator/tcp/15600/p2p/12D3KooWRVt4Engu27jHnF2RjfX48EqiAqJbgLfFdHNt3Vn6BtJK
+--p2p.autopeering.bootstrapPeers=/dns/node-1-validator/tcp/15600/p2p/12D3KooWRVt4Engu27jHnF2RjfX48EqiAqJbgLfFdHNt3Vn6BtJK
--p2p.autopeering.maxPeers=3
"