Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

swarm/network: Use actual remote peer ip in underlay #1224

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions swarm/network/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"net"
"regexp"
"sync"
"time"

Expand All @@ -39,6 +40,8 @@ const (
bzzHandshakeTimeout = 3000 * time.Millisecond
)

var regexpEnodeIP = regexp.MustCompile("@(.+):([0-9]+)")

// BzzSpec is the spec of the generic swarm handshake
var BzzSpec = &protocols.Spec{
Name: "bzz",
Expand Down Expand Up @@ -213,11 +216,26 @@ func (b *Bzz) performHandshake(p *protocols.Peer, handshake *HandshakeMsg) error
handshake.err = err
return err
}
handshake.peerAddr = rsh.(*HandshakeMsg).Addr
handshake.peerAddr = sanitizeEnodeRemote(p.RemoteAddr(), rsh.(*HandshakeMsg).Addr)
handshake.LightNode = rsh.(*HandshakeMsg).LightNode
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why return pointer then?

func sanitizeEnodeRemote(paddr net.Addr, baddr *BzzAddr) *BzzAddr {
hsSubmatch := regexpEnodeIP.FindSubmatch(baddr.UAddr)
ip, _, err := net.SplitHostPort(paddr.String())
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))
}
return baddr
}

// runBzz is the p2p protocol run function for the bzz base protocol
// that negotiates the bzz handshake
func (b *Bzz) runBzz(p *p2p.Peer, rw p2p.MsgReadWriter) error {
Expand Down Expand Up @@ -324,7 +342,7 @@ func (b *Bzz) GetOrCreateHandshake(peerID enode.ID) (*HandshakeMsg, bool) {
init: make(chan bool, 1),
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
handshake.init <- true
b.handshakes[peerID] = handshake
Expand Down
26 changes: 26 additions & 0 deletions swarm/network/protocol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
package network

import (
"bytes"
"flag"
"fmt"
"net"
"os"
"testing"
"time"

"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
Expand Down Expand Up @@ -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
newUAddr := sanitizeEnodeRemote(&remoteAddr, baddr).UAddr
if !bytes.Equal(newUAddr, []byte(nodRemote.String())) {
t.Fatalf("insane address. expected %v, got %v", nodRemote.String(), string(newUAddr))
}
}