mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-13 21:31:23 +00:00
Add private peer ID tracking to AddrBook (#1989)
* Add private peer ID tracking to AddrBook * Remove private peer tracking/blocking from pex * debug level msg when we fail to add private address
This commit is contained in:
committed by
Anton Kaliaev
parent
449846ccb2
commit
6c4ca140ed
@ -284,7 +284,6 @@ type P2PConfig struct {
|
|||||||
Seeds string `mapstructure:"seeds"`
|
Seeds string `mapstructure:"seeds"`
|
||||||
|
|
||||||
// Comma separated list of nodes to keep persistent connections to
|
// Comma separated list of nodes to keep persistent connections to
|
||||||
// Do not add private peers to this list if you don't want them advertised
|
|
||||||
PersistentPeers string `mapstructure:"persistent_peers"`
|
PersistentPeers string `mapstructure:"persistent_peers"`
|
||||||
|
|
||||||
// UPNP port forwarding
|
// UPNP port forwarding
|
||||||
|
@ -152,7 +152,6 @@ external_address = "{{ .P2P.ExternalAddress }}"
|
|||||||
seeds = "{{ .P2P.Seeds }}"
|
seeds = "{{ .P2P.Seeds }}"
|
||||||
|
|
||||||
# Comma separated list of nodes to keep persistent connections to
|
# Comma separated list of nodes to keep persistent connections to
|
||||||
# Do not add private peers to this list if you don't want them advertised
|
|
||||||
persistent_peers = "{{ .P2P.PersistentPeers }}"
|
persistent_peers = "{{ .P2P.PersistentPeers }}"
|
||||||
|
|
||||||
# UPNP port forwarding
|
# UPNP port forwarding
|
||||||
|
@ -99,7 +99,6 @@ laddr = "tcp://0.0.0.0:26656"
|
|||||||
seeds = ""
|
seeds = ""
|
||||||
|
|
||||||
# Comma separated list of nodes to keep persistent connections to
|
# Comma separated list of nodes to keep persistent connections to
|
||||||
# Do not add private peers to this list if you don't want them advertised
|
|
||||||
persistent_peers = ""
|
persistent_peers = ""
|
||||||
|
|
||||||
# UPNP port forwarding
|
# UPNP port forwarding
|
||||||
|
@ -322,9 +322,9 @@ func NewNode(config *cfg.Config,
|
|||||||
// TODO persistent peers ? so we can have their DNS addrs saved
|
// TODO persistent peers ? so we can have their DNS addrs saved
|
||||||
pexReactor := pex.NewPEXReactor(addrBook,
|
pexReactor := pex.NewPEXReactor(addrBook,
|
||||||
&pex.PEXReactorConfig{
|
&pex.PEXReactorConfig{
|
||||||
Seeds: cmn.SplitAndTrim(config.P2P.Seeds, ",", " "),
|
Seeds: cmn.SplitAndTrim(config.P2P.Seeds, ",", " "),
|
||||||
SeedMode: config.P2P.SeedMode,
|
SeedMode: config.P2P.SeedMode,
|
||||||
PrivatePeerIDs: cmn.SplitAndTrim(config.P2P.PrivatePeerIDs, ",", " ")})
|
})
|
||||||
pexReactor.SetLogger(p2pLogger)
|
pexReactor.SetLogger(p2pLogger)
|
||||||
sw.AddReactor("PEX", pexReactor)
|
sw.AddReactor("PEX", pexReactor)
|
||||||
}
|
}
|
||||||
@ -449,6 +449,9 @@ func (n *Node) OnStart() error {
|
|||||||
// Add ourselves to addrbook to prevent dialing ourselves
|
// Add ourselves to addrbook to prevent dialing ourselves
|
||||||
n.addrBook.AddOurAddress(nodeInfo.NetAddress())
|
n.addrBook.AddOurAddress(nodeInfo.NetAddress())
|
||||||
|
|
||||||
|
// Add private IDs to addrbook to block those peers being added
|
||||||
|
n.addrBook.AddPrivateIDs(cmn.SplitAndTrim(n.config.P2P.PrivatePeerIDs, ",", " "))
|
||||||
|
|
||||||
// Start the RPC server before the P2P server
|
// Start the RPC server before the P2P server
|
||||||
// so we can eg. receive txs for the first block
|
// so we can eg. receive txs for the first block
|
||||||
if n.config.RPC.ListenAddress != "" {
|
if n.config.RPC.ListenAddress != "" {
|
||||||
|
@ -13,8 +13,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
crypto "github.com/tendermint/tendermint/crypto"
|
crypto "github.com/tendermint/tendermint/crypto"
|
||||||
"github.com/tendermint/tendermint/p2p"
|
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
|
"github.com/tendermint/tendermint/p2p"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -34,6 +34,8 @@ type AddrBook interface {
|
|||||||
// Check if it is our address
|
// Check if it is our address
|
||||||
OurAddress(*p2p.NetAddress) bool
|
OurAddress(*p2p.NetAddress) bool
|
||||||
|
|
||||||
|
AddPrivateIDs([]string)
|
||||||
|
|
||||||
// Add and remove an address
|
// Add and remove an address
|
||||||
AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error
|
AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error
|
||||||
RemoveAddress(*p2p.NetAddress)
|
RemoveAddress(*p2p.NetAddress)
|
||||||
@ -82,6 +84,7 @@ type addrBook struct {
|
|||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
rand *cmn.Rand
|
rand *cmn.Rand
|
||||||
ourAddrs map[string]struct{}
|
ourAddrs map[string]struct{}
|
||||||
|
privateIDs map[p2p.ID]struct{}
|
||||||
addrLookup map[p2p.ID]*knownAddress // new & old
|
addrLookup map[p2p.ID]*knownAddress // new & old
|
||||||
bucketsOld []map[string]*knownAddress
|
bucketsOld []map[string]*knownAddress
|
||||||
bucketsNew []map[string]*knownAddress
|
bucketsNew []map[string]*knownAddress
|
||||||
@ -97,6 +100,7 @@ func NewAddrBook(filePath string, routabilityStrict bool) *addrBook {
|
|||||||
am := &addrBook{
|
am := &addrBook{
|
||||||
rand: cmn.NewRand(),
|
rand: cmn.NewRand(),
|
||||||
ourAddrs: make(map[string]struct{}),
|
ourAddrs: make(map[string]struct{}),
|
||||||
|
privateIDs: make(map[p2p.ID]struct{}),
|
||||||
addrLookup: make(map[p2p.ID]*knownAddress),
|
addrLookup: make(map[p2p.ID]*knownAddress),
|
||||||
filePath: filePath,
|
filePath: filePath,
|
||||||
routabilityStrict: routabilityStrict,
|
routabilityStrict: routabilityStrict,
|
||||||
@ -168,6 +172,14 @@ func (a *addrBook) OurAddress(addr *p2p.NetAddress) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *addrBook) AddPrivateIDs(IDs []string) {
|
||||||
|
a.mtx.Lock()
|
||||||
|
defer a.mtx.Unlock()
|
||||||
|
for _, id := range IDs {
|
||||||
|
a.privateIDs[p2p.ID(id)] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AddAddress implements AddrBook
|
// AddAddress implements AddrBook
|
||||||
// Add address to a "new" bucket. If it's already in one, only add it probabilistically.
|
// Add address to a "new" bucket. If it's already in one, only add it probabilistically.
|
||||||
// Returns error if the addr is non-routable. Does not add self.
|
// Returns error if the addr is non-routable. Does not add self.
|
||||||
@ -631,6 +643,10 @@ func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error {
|
|||||||
return ErrAddrBookSelf{addr}
|
return ErrAddrBookSelf{addr}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, ok := a.privateIDs[addr.ID]; ok {
|
||||||
|
return ErrAddrBookPrivate{addr}
|
||||||
|
}
|
||||||
|
|
||||||
ka := a.addrLookup[addr.ID]
|
ka := a.addrLookup[addr.ID]
|
||||||
if ka != nil {
|
if ka != nil {
|
||||||
// If its already old and the addr is the same, ignore it.
|
// If its already old and the addr is the same, ignore it.
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
cmn "github.com/tendermint/tendermint/libs/common"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
"github.com/tendermint/tendermint/p2p"
|
"github.com/tendermint/tendermint/p2p"
|
||||||
@ -353,3 +355,29 @@ func TestAddrBookHasAddress(t *testing.T) {
|
|||||||
|
|
||||||
assert.False(t, book.HasAddress(addr))
|
assert.False(t, book.HasAddress(addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrivatePeers(t *testing.T) {
|
||||||
|
fname := createTempFileName("addrbook_test")
|
||||||
|
defer deleteTempFile(fname)
|
||||||
|
|
||||||
|
book := NewAddrBook(fname, true)
|
||||||
|
book.SetLogger(log.TestingLogger())
|
||||||
|
|
||||||
|
addrs := make([]*p2p.NetAddress, 10)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
addrs[i] = randIPv4Address(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
private := make([]string, 10)
|
||||||
|
for i, addr := range addrs {
|
||||||
|
private[i] = string(addr.ID)
|
||||||
|
}
|
||||||
|
book.AddPrivateIDs(private)
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
err := book.AddAddress(addr, addr)
|
||||||
|
require.Error(t, err, "AddAddress should have failed with private peer %s", addr)
|
||||||
|
_, ok := err.(ErrAddrBookPrivate)
|
||||||
|
require.True(t, ok, "Wrong error type, wanted ErrAddrBookPrivate, got error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,6 +22,14 @@ func (err ErrAddrBookSelf) Error() string {
|
|||||||
return fmt.Sprintf("Cannot add ourselves with address %v", err.Addr)
|
return fmt.Sprintf("Cannot add ourselves with address %v", err.Addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ErrAddrBookPrivate struct {
|
||||||
|
Addr *p2p.NetAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrAddrBookPrivate) Error() string {
|
||||||
|
return fmt.Sprintf("Cannot add private peer with address %v", err.Addr)
|
||||||
|
}
|
||||||
|
|
||||||
type ErrAddrBookNilAddr struct {
|
type ErrAddrBookNilAddr struct {
|
||||||
Addr *p2p.NetAddress
|
Addr *p2p.NetAddress
|
||||||
Src *p2p.NetAddress
|
Src *p2p.NetAddress
|
||||||
|
@ -91,10 +91,6 @@ type PEXReactorConfig struct {
|
|||||||
// Seeds is a list of addresses reactor may use
|
// Seeds is a list of addresses reactor may use
|
||||||
// if it can't connect to peers in the addrbook.
|
// if it can't connect to peers in the addrbook.
|
||||||
Seeds []string
|
Seeds []string
|
||||||
|
|
||||||
// PrivatePeerIDs is a list of peer IDs, which must not be gossiped to other
|
|
||||||
// peers.
|
|
||||||
PrivatePeerIDs []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type _attemptsToDial struct {
|
type _attemptsToDial struct {
|
||||||
@ -173,11 +169,6 @@ func (r *PEXReactor) AddPeer(p Peer) {
|
|||||||
addr := p.NodeInfo().NetAddress()
|
addr := p.NodeInfo().NetAddress()
|
||||||
src := addr
|
src := addr
|
||||||
|
|
||||||
// ignore private addrs
|
|
||||||
if isAddrPrivate(addr, r.config.PrivatePeerIDs) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// add to book. dont RequestAddrs right away because
|
// add to book. dont RequestAddrs right away because
|
||||||
// we don't trust inbound as much - let ensurePeersRoutine handle it.
|
// we don't trust inbound as much - let ensurePeersRoutine handle it.
|
||||||
err := r.book.AddAddress(addr, src)
|
err := r.book.AddAddress(addr, src)
|
||||||
@ -191,7 +182,7 @@ func (r *PEXReactor) logErrAddrBook(err error) {
|
|||||||
case ErrAddrBookNilAddr:
|
case ErrAddrBookNilAddr:
|
||||||
r.Logger.Error("Failed to add new address", "err", err)
|
r.Logger.Error("Failed to add new address", "err", err)
|
||||||
default:
|
default:
|
||||||
// non-routable, self, full book, etc.
|
// non-routable, self, full book, private, etc.
|
||||||
r.Logger.Debug("Failed to add new address", "err", err)
|
r.Logger.Debug("Failed to add new address", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,14 +299,6 @@ func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error {
|
|||||||
return cmn.NewError("received nil addr")
|
return cmn.NewError("received nil addr")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore private peers
|
|
||||||
// TODO: give private peers to AddrBook so it can enforce this on AddAddress.
|
|
||||||
// We'd then have to check for ErrPrivatePeer on AddAddress here, which is
|
|
||||||
// an error we just ignore (maybe peer is probing us for our private peers :P)
|
|
||||||
if isAddrPrivate(netAddr, r.config.PrivatePeerIDs) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err := r.book.AddAddress(netAddr, srcAddr)
|
err := r.book.AddAddress(netAddr, srcAddr)
|
||||||
r.logErrAddrBook(err)
|
r.logErrAddrBook(err)
|
||||||
}
|
}
|
||||||
@ -647,16 +630,6 @@ func (r *PEXReactor) attemptDisconnects() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// isAddrPrivate returns true if addr.ID is a private ID.
|
|
||||||
func isAddrPrivate(addr *p2p.NetAddress, privatePeerIDs []string) bool {
|
|
||||||
for _, id := range privatePeerIDs {
|
|
||||||
if string(addr.ID) == id {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Messages
|
// Messages
|
||||||
|
|
||||||
|
@ -295,7 +295,8 @@ func TestPEXReactorCrawlStatus(t *testing.T) {
|
|||||||
func TestPEXReactorDoesNotAddPrivatePeersToAddrBook(t *testing.T) {
|
func TestPEXReactorDoesNotAddPrivatePeersToAddrBook(t *testing.T) {
|
||||||
peer := p2p.CreateRandomPeer(false)
|
peer := p2p.CreateRandomPeer(false)
|
||||||
|
|
||||||
pexR, book := createReactor(&PEXReactorConfig{PrivatePeerIDs: []string{string(peer.NodeInfo().ID)}})
|
pexR, book := createReactor(&PEXReactorConfig{})
|
||||||
|
book.AddPrivateIDs([]string{string(peer.NodeInfo().ID)})
|
||||||
defer teardownReactor(book)
|
defer teardownReactor(book)
|
||||||
|
|
||||||
// we have to send a request to receive responses
|
// we have to send a request to receive responses
|
||||||
|
Reference in New Issue
Block a user