swarm/network: Use actual remote peer ip in underlay (#19137)

* swarm/network: Logline to see handshake addr

* swarm/network: Replace remote ip in handshake uaddr

* swarm/network: Add test for enode uaddr rewrite method

* swarm/network: Remove redundance pointer return from sanitize

* swarm/network: Obeying the linting machine

* swarm/network: Add panic comment

(travis trigger take 1)
This commit is contained in:
lash 2019-02-20 14:46:00 +01:00 committed by Viktor Trón
parent ba2dfa5ce4
commit 460d206f30
2 changed files with 46 additions and 1 deletions

View File

@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"regexp"
"sync" "sync"
"time" "time"
@ -39,6 +40,8 @@ const (
bzzHandshakeTimeout = 3000 * time.Millisecond bzzHandshakeTimeout = 3000 * time.Millisecond
) )
var regexpEnodeIP = regexp.MustCompile("@(.+):([0-9]+)")
// BzzSpec is the spec of the generic swarm handshake // BzzSpec is the spec of the generic swarm handshake
var BzzSpec = &protocols.Spec{ var BzzSpec = &protocols.Spec{
Name: "bzz", Name: "bzz",
@ -214,10 +217,26 @@ func (b *Bzz) performHandshake(p *protocols.Peer, handshake *HandshakeMsg) error
return err return err
} }
handshake.peerAddr = rsh.(*HandshakeMsg).Addr handshake.peerAddr = rsh.(*HandshakeMsg).Addr
sanitizeEnodeRemote(p.RemoteAddr(), handshake.peerAddr)
handshake.LightNode = rsh.(*HandshakeMsg).LightNode handshake.LightNode = rsh.(*HandshakeMsg).LightNode
return nil return nil
} }
// the remote enode string may advertise arbitrary host information (e.g. localhost)
// this method ensures that the addr of the peer will be the one
// applicable on the interface the connection came in on
// it modifies the passed bzzaddr in place, and returns the same pointer
func sanitizeEnodeRemote(paddr net.Addr, baddr *BzzAddr) {
hsSubmatch := regexpEnodeIP.FindSubmatch(baddr.UAddr)
ip, _, err := net.SplitHostPort(paddr.String())
// since we expect nothing else than ipv4 here, a panic on missing submatch is desired
if err == nil && string(hsSubmatch[1]) != ip {
remoteStr := fmt.Sprintf("@%s:%s", ip, string(hsSubmatch[2]))
log.Debug("rewrote peer uaddr host/port", "addr", baddr)
baddr.UAddr = regexpEnodeIP.ReplaceAll(baddr.UAddr, []byte(remoteStr))
}
}
// runBzz is the p2p protocol run function for the bzz base protocol // runBzz is the p2p protocol run function for the bzz base protocol
// that negotiates the bzz handshake // that negotiates the bzz handshake
func (b *Bzz) runBzz(p *p2p.Peer, rw p2p.MsgReadWriter) error { func (b *Bzz) runBzz(p *p2p.Peer, rw p2p.MsgReadWriter) error {
@ -324,7 +343,7 @@ func (b *Bzz) GetOrCreateHandshake(peerID enode.ID) (*HandshakeMsg, bool) {
init: make(chan bool, 1), init: make(chan bool, 1),
done: make(chan struct{}), done: make(chan struct{}),
} }
// when handhsake is first created for a remote peer // when handshake is first created for a remote peer
// it is initialised with the init // it is initialised with the init
handshake.init <- true handshake.init <- true
b.handshakes[peerID] = handshake b.handshakes[peerID] = handshake

View File

@ -17,12 +17,15 @@
package network package network
import ( import (
"bytes"
"flag" "flag"
"fmt" "fmt"
"net"
"os" "os"
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
@ -251,3 +254,26 @@ func TestBzzHandshakeLightNode(t *testing.T) {
}) })
} }
} }
// Tests the overwriting of localhost enode in handshake if actual remote ip is known
// (swarm.network/protocol.go:sanitizeEnodeRemote)
func TestSanitizeEnodeRemote(t *testing.T) {
pk, err := crypto.GenerateKey()
if err != nil {
t.Fatal(err)
}
remoteIP := net.IPv4(0x80, 0x40, 0x20, 0x10)
remoteAddr := net.TCPAddr{
IP: remoteIP,
Port: 30399,
}
nodLocal := enode.NewV4(&pk.PublicKey, net.IPv4(0x7f, 0x00, 0x00, 0x01), 30341, 30341)
nodRemote := enode.NewV4(&pk.PublicKey, remoteIP, 30341, 30341)
baddr := RandomAddr()
oldUAddr := []byte(nodLocal.String())
baddr.UAddr = oldUAddr
sanitizeEnodeRemote(&remoteAddr, baddr)
if !bytes.Equal(baddr.UAddr, []byte(nodRemote.String())) {
t.Fatalf("insane address. expected %v, got %v", nodRemote.String(), string(baddr.UAddr))
}
}