Browse Source

Merge pull request #1843 from tendermint/bucky/external_address

Bucky/external address
pull/1606/head
Ethan Buchman 6 years ago
committed by GitHub
parent
commit
72475c800b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 23 deletions
  1. +2
    -0
      CHANGELOG.md
  2. +4
    -0
      config/config.go
  3. +6
    -0
      config/toml.go
  4. +5
    -2
      node/node.go
  5. +30
    -13
      p2p/listener.go
  6. +33
    -1
      p2p/listener_test.go
  7. +2
    -7
      p2p/pex/pex_reactor_test.go

+ 2
- 0
CHANGELOG.md View File

@ -22,6 +22,8 @@ FEATURES
[metrics](https://tendermint.readthedocs.io/projects/tools/en/develop/metrics.html) [metrics](https://tendermint.readthedocs.io/projects/tools/en/develop/metrics.html)
guide. guide.
- [p2p] Add IPv6 support to peering. - [p2p] Add IPv6 support to peering.
- [p2p] Add `external_address` to config to allow specifying the address for
peers to dial
IMPROVEMENT IMPROVEMENT
- [rpc/client] Supports https and wss now. - [rpc/client] Supports https and wss now.


+ 4
- 0
config/config.go View File

@ -276,6 +276,9 @@ type P2PConfig struct {
// Address to listen for incoming connections // Address to listen for incoming connections
ListenAddress string `mapstructure:"laddr"` ListenAddress string `mapstructure:"laddr"`
// Address to advertise to peers for them to dial
ExternalAddress string `mapstructure:"external_address"`
// Comma separated list of seed nodes to connect to // Comma separated list of seed nodes to connect to
// We only use these if we can’t connect to peers in the addrbook // We only use these if we can’t connect to peers in the addrbook
Seeds string `mapstructure:"seeds"` Seeds string `mapstructure:"seeds"`
@ -340,6 +343,7 @@ type P2PConfig struct {
func DefaultP2PConfig() *P2PConfig { func DefaultP2PConfig() *P2PConfig {
return &P2PConfig{ return &P2PConfig{
ListenAddress: "tcp://0.0.0.0:26656", ListenAddress: "tcp://0.0.0.0:26656",
ExternalAddress: "",
UPNP: false, UPNP: false,
AddrBook: defaultAddrBookPath, AddrBook: defaultAddrBookPath,
AddrBookStrict: true, AddrBookStrict: true,


+ 6
- 0
config/toml.go View File

@ -142,6 +142,12 @@ max_open_connections = {{ .RPC.MaxOpenConnections }}
# Address to listen for incoming connections # Address to listen for incoming connections
laddr = "{{ .P2P.ListenAddress }}" laddr = "{{ .P2P.ListenAddress }}"
# Address to advertise to peers for them to dial
# If empty, will use the same port as the laddr,
# and will introspect on the listener or use UPnP
# to figure out the address.
external_address = "{{ .P2P.ExternalAddress }}"
# Comma separated list of seed nodes to connect to # Comma separated list of seed nodes to connect to
seeds = "{{ .P2P.Seeds }}" seeds = "{{ .P2P.Seeds }}"


+ 5
- 2
node/node.go View File

@ -426,8 +426,11 @@ func (n *Node) OnStart() error {
} }
// Create & add listener // Create & add listener
protocol, address := cmn.ProtocolAndAddress(n.config.P2P.ListenAddress)
l := p2p.NewDefaultListener(protocol, address, n.config.P2P.UPNP, n.Logger.With("module", "p2p"))
l := p2p.NewDefaultListener(
n.config.P2P.ListenAddress,
n.config.P2P.ExternalAddress,
n.config.P2P.UPNP,
n.Logger.With("module", "p2p"))
n.sw.AddListener(l) n.sw.AddListener(l)
// Generate node PrivKey // Generate node PrivKey


+ 30
- 13
p2p/listener.go View File

@ -7,9 +7,9 @@ import (
"strings" "strings"
"time" "time"
"github.com/tendermint/tendermint/p2p/upnp"
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/upnp"
) )
// Listener is a network listener for stream-oriented protocols, providing // Listener is a network listener for stream-oriented protocols, providing
@ -59,8 +59,14 @@ func splitHostPort(addr string) (host string, port int) {
// NewDefaultListener creates a new DefaultListener on lAddr, optionally trying // NewDefaultListener creates a new DefaultListener on lAddr, optionally trying
// to determine external address using UPnP. // to determine external address using UPnP.
func NewDefaultListener(protocol string, lAddr string, UPNP bool, logger log.Logger) Listener {
// Local listen IP & port
func NewDefaultListener(
fullListenAddrString string,
externalAddrString string,
useUPnP bool,
logger log.Logger) Listener {
// Split protocol, address, and port.
protocol, lAddr := cmn.ProtocolAndAddress(fullListenAddrString)
lAddrIP, lAddrPort := splitHostPort(lAddr) lAddrIP, lAddrPort := splitHostPort(lAddr)
// Create listener // Create listener
@ -88,17 +94,28 @@ func NewDefaultListener(protocol string, lAddr string, UPNP bool, logger log.Log
panic(err) panic(err)
} }
// Determine external address...
inAddrAny := lAddrIP == "" || lAddrIP == "0.0.0.0"
// Determine external address.
var extAddr *NetAddress var extAddr *NetAddress
if UPNP {
// If the lAddrIP is INADDR_ANY, try UPnP
if lAddrIP == "" || lAddrIP == "0.0.0.0" {
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort, logger)
if externalAddrString != "" {
var err error
extAddr, err = NewNetAddressStringWithOptionalID(externalAddrString)
if err != nil {
panic(fmt.Sprintf("Error in ExternalAddress: %v", err))
} }
} }
// Otherwise just use the local address...
// If the lAddrIP is INADDR_ANY, try UPnP.
if extAddr == nil && useUPnP && inAddrAny {
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort, logger)
}
// Otherwise just use the local address.
if extAddr == nil { if extAddr == nil {
extAddr = getNaiveExternalAddress(listenerPort, false, logger)
defaultToIPv4 := inAddrAny
extAddr = getNaiveExternalAddress(defaultToIPv4, listenerPort, false, logger)
} }
if extAddr == nil { if extAddr == nil {
panic("Could not determine external address!") panic("Could not determine external address!")
@ -237,7 +254,7 @@ func isIpv6(ip net.IP) bool {
} }
// TODO: use syscalls: see issue #712 // TODO: use syscalls: see issue #712
func getNaiveExternalAddress(port int, settleForLocal bool, logger log.Logger) *NetAddress {
func getNaiveExternalAddress(defaultToIPv4 bool, port int, settleForLocal bool, logger log.Logger) *NetAddress {
addrs, err := net.InterfaceAddrs() addrs, err := net.InterfaceAddrs()
if err != nil { if err != nil {
panic(cmn.Fmt("Could not fetch interface addresses: %v", err)) panic(cmn.Fmt("Could not fetch interface addresses: %v", err))
@ -248,7 +265,7 @@ func getNaiveExternalAddress(port int, settleForLocal bool, logger log.Logger) *
if !ok { if !ok {
continue continue
} }
if !isIpv6(ipnet.IP) {
if defaultToIPv4 || !isIpv6(ipnet.IP) {
v4 := ipnet.IP.To4() v4 := ipnet.IP.To4()
if v4 == nil || (!settleForLocal && v4[0] == 127) { if v4 == nil || (!settleForLocal && v4[0] == 127) {
// loopback // loopback
@ -263,5 +280,5 @@ func getNaiveExternalAddress(port int, settleForLocal bool, logger log.Logger) *
// try again, but settle for local // try again, but settle for local
logger.Info("Node may not be connected to internet. Settling for local address") logger.Info("Node may not be connected to internet. Settling for local address")
return getNaiveExternalAddress(port, true, logger)
return getNaiveExternalAddress(defaultToIPv4, port, true, logger)
} }

+ 33
- 1
p2p/listener_test.go View File

@ -2,14 +2,17 @@ package p2p
import ( import (
"bytes" "bytes"
"net"
"strings"
"testing" "testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
) )
func TestListener(t *testing.T) { func TestListener(t *testing.T) {
// Create a listener // Create a listener
l := NewDefaultListener("tcp", ":8001", false, log.TestingLogger())
l := NewDefaultListener("tcp://:8001", "", false, log.TestingLogger())
// Dial the listener // Dial the listener
lAddr := l.ExternalAddress() lAddr := l.ExternalAddress()
@ -45,3 +48,32 @@ func TestListener(t *testing.T) {
// Close the server, no longer needed. // Close the server, no longer needed.
l.Stop() l.Stop()
} }
func TestExternalAddress(t *testing.T) {
{
// Create a listener with no external addr. Should default
// to local ipv4.
l := NewDefaultListener("tcp://:8001", "", false, log.TestingLogger())
lAddr := l.ExternalAddress().String()
_, _, err := net.SplitHostPort(lAddr)
require.Nil(t, err)
spl := strings.Split(lAddr, ".")
require.Equal(t, len(spl), 4)
l.Stop()
}
{
// Create a listener with set external ipv4 addr.
setExAddr := "8.8.8.8:8080"
l := NewDefaultListener("tcp://:8001", setExAddr, false, log.TestingLogger())
lAddr := l.ExternalAddress().String()
require.Equal(t, lAddr, setExAddr)
l.Stop()
}
{
// Invalid external addr causes panic
setExAddr := "awrlsckjnal:8080"
require.Panics(t, func() { NewDefaultListener("tcp://:8001", setExAddr, false, log.TestingLogger()) })
}
}

+ 2
- 7
p2p/pex/pex_reactor_test.go View File

@ -109,7 +109,7 @@ func TestPEXReactorRunning(t *testing.T) {
addOtherNodeAddrToAddrBook(2, 1) addOtherNodeAddrToAddrBook(2, 1)
for i, sw := range switches { for i, sw := range switches {
sw.AddListener(p2p.NewDefaultListener("tcp", sw.NodeInfo().ListenAddr, false, logger.With("pex", i)))
sw.AddListener(p2p.NewDefaultListener("tcp://"+sw.NodeInfo().ListenAddr, "", false, logger.With("pex", i)))
err := sw.Start() // start switch and reactors err := sw.Start() // start switch and reactors
require.Nil(t, err) require.Nil(t, err)
@ -229,12 +229,7 @@ func TestPEXReactorUsesSeedsIfNeeded(t *testing.T) {
}, },
) )
seed.AddListener( seed.AddListener(
p2p.NewDefaultListener(
"tcp",
seed.NodeInfo().ListenAddr,
false,
log.TestingLogger(),
),
p2p.NewDefaultListener("tcp://"+seed.NodeInfo().ListenAddr, "", false, log.TestingLogger()),
) )
require.Nil(t, seed.Start()) require.Nil(t, seed.Start())
defer seed.Stop() defer seed.Stop()


Loading…
Cancel
Save