diff --git a/CHANGELOG.md b/CHANGELOG.md index decf8506f..d528c95eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,7 @@ IMPROVEMENTS: release after this one) FEATURES: -- [config] added the `--p2p.private_peers` flag and `PrivatePeers` config variable (see config for description) +- [config] added the `--p2p.private_peer_ids` flag and `PrivatePeerIDs` config variable (see config for description) ## 0.16.0 (February 20th, 2017) diff --git a/cmd/tendermint/commands/run_node.go b/cmd/tendermint/commands/run_node.go index 45a502c39..0fcab3e39 100644 --- a/cmd/tendermint/commands/run_node.go +++ b/cmd/tendermint/commands/run_node.go @@ -31,12 +31,12 @@ func AddNodeFlags(cmd *cobra.Command) { // p2p flags cmd.Flags().String("p2p.laddr", config.P2P.ListenAddress, "Node listen address. (0.0.0.0:0 means any interface, any port)") - cmd.Flags().String("p2p.seeds", config.P2P.Seeds, "Comma-delimited host:port seed nodes") - cmd.Flags().String("p2p.persistent_peers", config.P2P.PersistentPeers, "Comma-delimited host:port persistent peers") + cmd.Flags().String("p2p.seeds", config.P2P.Seeds, "Comma-delimited ID@host:port seed nodes") + cmd.Flags().String("p2p.persistent_peers", config.P2P.PersistentPeers, "Comma-delimited ID@host:port persistent peers") cmd.Flags().Bool("p2p.skip_upnp", config.P2P.SkipUPNP, "Skip UPNP configuration") cmd.Flags().Bool("p2p.pex", config.P2P.PexReactor, "Enable/disable Peer-Exchange") cmd.Flags().Bool("p2p.seed_mode", config.P2P.SeedMode, "Enable/disable seed mode") - cmd.Flags().String("p2p.private_peers", config.P2P.PrivatePeers, "Comma-delimited host:port private peers") + cmd.Flags().String("p2p.private_peer_ids", config.P2P.PrivatePeerIDs, "Comma-delimited private peer IDs") // consensus flags cmd.Flags().Bool("consensus.create_empty_blocks", config.Consensus.CreateEmptyBlocks, "Set this to false to only produce blocks when there are txs or when the AppHash changes") diff --git a/config/config.go b/config/config.go index fd77a9db4..64da6373f 100644 --- a/config/config.go +++ b/config/config.go @@ -289,8 +289,8 @@ type P2PConfig struct { // Authenticated encryption AuthEnc bool `mapstructure:"auth_enc"` - // Comma separated list of nodes to keep private (will not be gossiped to other peers) connections to - PrivatePeers string `mapstructure:"private_peers"` + // Comma separated list of peer IDs to keep private (will not be gossiped to other peers) + PrivatePeerIDs string `mapstructure:"private_peer_ids"` } // DefaultP2PConfig returns a default configuration for the peer-to-peer layer diff --git a/config/toml.go b/config/toml.go index 38c5a3335..e40fe8fd5 100644 --- a/config/toml.go +++ b/config/toml.go @@ -162,8 +162,8 @@ seed_mode = {{ .P2P.SeedMode }} # Authenticated encryption auth_enc = {{ .P2P.AuthEnc }} -# Comma separated list of nodes to keep private (will not be gossiped to other peers) connections to -private_peers = {{ .P2P.PrivatePeers }} +# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) +private_peer_ids = {{ .P2P.PrivatePeerIDs }} ##### mempool configuration options ##### [mempool] diff --git a/docs/specification/configuration.rst b/docs/specification/configuration.rst index 33f9657f8..314905077 100644 --- a/docs/specification/configuration.rst +++ b/docs/specification/configuration.rst @@ -124,8 +124,8 @@ like the file below, however, double check by inspecting the # Authenticated encryption auth_enc = true - # Comma separated list of nodes to keep private (will not be gossiped to other peers) connections to - private_peers = "" + # Comma separated list of peer IDs to keep private (will not be gossiped to other peers) + private_peer_ids = "" ##### mempool configuration options ##### [mempool] diff --git a/node/node.go b/node/node.go index 13a60c441..94616b0c7 100644 --- a/node/node.go +++ b/node/node.go @@ -281,8 +281,15 @@ func NewNode(config *cfg.Config, if config.P2P.Seeds != "" { seeds = strings.Split(config.P2P.Seeds, ",") } + var privatePeerIDs []string + if config.P2P.PrivatePeerIDs != "" { + privatePeerIDs = strings.Split(config.P2P.PrivatePeerIDs, ",") + } pexReactor := pex.NewPEXReactor(addrBook, - &pex.PEXReactorConfig{Seeds: seeds, SeedMode: config.P2P.SeedMode}) + &pex.PEXReactorConfig{ + Seeds: seeds, + SeedMode: config.P2P.SeedMode, + PrivatePeerIDs: privatePeerIDs}) pexReactor.SetLogger(p2pLogger) sw.AddReactor("PEX", pexReactor) } @@ -415,18 +422,39 @@ func (n *Node) OnStart() error { // Always connect to persistent peers if n.config.P2P.PersistentPeers != "" { - err = n.sw.DialPeersAsync(n.addrBook, strings.Split(n.config.P2P.PersistentPeers, ","), true) - if err != nil { - return err + // are any of the persistent peers private? + persistentPeers := []string{} + persistentAndPrivatePeers := []string{} + var privatePeerIDs []string + if n.config.P2P.PrivatePeerIDs != "" { + privatePeerIDs = strings.Split(n.config.P2P.PrivatePeerIDs, ",") + } + PP_LOOP: + for _, peer := range strings.Split(n.config.P2P.PersistentPeers, ",") { + spl := strings.Split(peer, "@") + if len(spl) == 2 { + for _, ppID := range privatePeerIDs { + if spl[0] == ppID { + persistentAndPrivatePeers = append(persistentAndPrivatePeers, peer) + continue PP_LOOP + } + } + } + persistentPeers = append(persistentPeers, peer) } - } - // Always connect to private peers, but do not add them to addrbook - if n.config.P2P.PrivatePeers != "" { - err = n.sw.DialPeersAsync(nil, strings.Split(n.config.P2P.PrivatePeers, ","), true) + err = n.sw.DialPeersAsync(n.addrBook, persistentPeers, true) if err != nil { return err } + + // if any of the persistent peers are private, do not add them to addrbook + if len(persistentAndPrivatePeers) > 0 { + err = n.sw.DialPeersAsync(nil, persistentAndPrivatePeers, true) + if err != nil { + return err + } + } } // start tx indexer diff --git a/p2p/pex/pex_reactor.go b/p2p/pex/pex_reactor.go index 193efc88d..cb9e62bfd 100644 --- a/p2p/pex/pex_reactor.go +++ b/p2p/pex/pex_reactor.go @@ -74,6 +74,10 @@ type PEXReactorConfig struct { // Seeds is a list of addresses reactor may use // if it can't connect to peers in the addrbook. Seeds []string + + // PrivatePeerIDs is a list of peer IDs, which must not be gossiped to other + // peers. + PrivatePeerIDs []string } type _attemptsToDial struct { @@ -152,7 +156,9 @@ func (r *PEXReactor) AddPeer(p Peer) { // Let the ensurePeersRoutine handle asking for more // peers when we need - we don't trust inbound peers as much. addr := p.NodeInfo().NetAddress() - r.book.AddAddress(addr, addr) + if !isAddrPrivate(addr, r.config.PrivatePeerIDs) { + r.book.AddAddress(addr, addr) + } } } @@ -251,7 +257,10 @@ func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error { srcAddr := src.NodeInfo().NetAddress() for _, netAddr := range addrs { - if netAddr != nil { + if netAddr == nil { + continue + } + if !isAddrPrivate(netAddr, r.config.PrivatePeerIDs) { r.book.AddAddress(netAddr, srcAddr) } } @@ -579,6 +588,16 @@ func (r *PEXReactor) attemptDisconnects() { } } +// isAddrPrivate returns true if addr is private. +func isAddrPrivate(addr *p2p.NetAddress, privatePeerIDs []string) bool { + for _, id := range privatePeerIDs { + if string(addr.ID) == id { + return true + } + } + return false +} + //----------------------------------------------------------------------------- // Messages