Skip to content

Commit 18d4c02

Browse files
committed
Respect proxy config for SPV and seeder connections
Remove the address of the local peer from the handshake. This is to prevent leaking internal network details and if a proxy is in use. Peers are also no longer informed of their external address if the address is loopback or a private or shared address.
1 parent 3b3e9e0 commit 18d4c02

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

dcrwallet.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ func spvLoop(ctx context.Context, w *wallet.Wallet) {
523523
amgrDir := filepath.Join(cfg.AppDataDir.Value, w.ChainParams().Name)
524524
amgr := addrmgr.New(amgrDir, cfg.lookup)
525525
lp := p2p.NewLocalPeer(w.ChainParams(), addr, amgr)
526+
lp.SetDialFunc(cfg.dial)
526527
syncer := spv.NewSyncer(w, lp)
527528
if len(cfg.SPVConnect) > 0 {
528529
syncer.SetPersistentPeers(cfg.SPVConnect)

p2p/peering.go

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/decred/dcrd/gcs/v3"
2828
blockcf "github.com/decred/dcrd/gcs/v3/blockcf2"
2929
"github.com/decred/dcrd/wire"
30+
"github.com/decred/go-socks/socks"
3031
"golang.org/x/sync/errgroup"
3132
)
3233

@@ -125,7 +126,7 @@ type LocalPeer struct {
125126
atomicPeerIDCounter uint64
126127
atomicRequireHeight int32
127128

128-
dialer net.Dialer
129+
dial DialFunc
129130

130131
receivedGetData chan *inMsg
131132
receivedHeaders chan *inMsg
@@ -143,7 +144,9 @@ type LocalPeer struct {
143144
// NewLocalPeer creates a LocalPeer that is externally reachable to remote peers
144145
// through extaddr.
145146
func NewLocalPeer(params *chaincfg.Params, extaddr *net.TCPAddr, amgr *addrmgr.AddrManager) *LocalPeer {
147+
var dialer net.Dialer
146148
lp := &LocalPeer{
149+
dial: dialer.DialContext,
147150
receivedGetData: make(chan *inMsg),
148151
receivedHeaders: make(chan *inMsg),
149152
receivedInv: make(chan *inMsg),
@@ -156,12 +159,46 @@ func NewLocalPeer(params *chaincfg.Params, extaddr *net.TCPAddr, amgr *addrmgr.A
156159
return lp
157160
}
158161

159-
func (lp *LocalPeer) newMsgVersion(pver uint32, extaddr net.Addr, c net.Conn) (*wire.MsgVersion, error) {
160-
la, err := wire.NewNetAddress(c.LocalAddr(), 0) // We provide no services
161-
if err != nil {
162-
return nil, err
162+
// DialFunc provides a method to dial a network connection.
163+
type DialFunc func(ctx context.Context, net, addr string) (net.Conn, error)
164+
165+
// SetDialFunc sets the function used to dial peer and seeder connections.
166+
func (lp *LocalPeer) SetDialFunc(dial DialFunc) {
167+
lp.dial = dial
168+
}
169+
170+
func isCGNAT(ip net.IP) bool {
171+
if ip4 := ip.To4(); ip4 != nil {
172+
return ip4[0] == 100 && ip4[1]&0xc0 == 64 // 100.64.0.0/10
173+
}
174+
return false
175+
}
176+
177+
func newNetAddress(addr net.Addr, services wire.ServiceFlag) (*wire.NetAddress, error) {
178+
var ip net.IP
179+
var port uint16
180+
switch a := addr.(type) {
181+
case *net.TCPAddr:
182+
ip = a.IP
183+
port = uint16(a.Port)
184+
case *socks.ProxiedAddr:
185+
ip = net.ParseIP(a.Host)
186+
port = uint16(a.Port)
187+
default:
188+
return nil, fmt.Errorf("newNetAddress: unsupported address "+
189+
"type %T", addr)
163190
}
164-
ra, err := wire.NewNetAddress(c.RemoteAddr(), 0)
191+
switch {
192+
case ip.IsLoopback(), ip.IsPrivate(), !ip.IsGlobalUnicast(), isCGNAT(ip):
193+
ip = nil
194+
port = 0
195+
}
196+
return wire.NewNetAddressIPPort(ip, port, services), nil
197+
}
198+
199+
func (lp *LocalPeer) newMsgVersion(pver uint32, c net.Conn) (*wire.MsgVersion, error) {
200+
la := new(wire.NetAddress)
201+
ra, err := newNetAddress(c.RemoteAddr(), 0)
165202
if err != nil {
166203
return nil, err
167204
}
@@ -302,7 +339,7 @@ func (lp *LocalPeer) SeedPeers(ctx context.Context, services wire.ServiceFlag) {
302339
resps := make(chan *http.Response)
303340
client := http.Client{
304341
Transport: &http.Transport{
305-
DialContext: lp.dialer.DialContext,
342+
DialContext: lp.dial,
306343
},
307344
}
308345
cancels := make([]func(), 0, len(seeders))
@@ -479,7 +516,7 @@ func handshake(ctx context.Context, lp *LocalPeer, id uint64, na *addrmgr.NetAdd
479516
mw := msgWriter{c, lp.chainParams.Net}
480517

481518
// The first message sent must be the version message.
482-
lversion, err := lp.newMsgVersion(rp.pver, lp.extaddr, c)
519+
lversion, err := lp.newMsgVersion(rp.pver, c)
483520
if err != nil {
484521
return nil, errors.E(op, err)
485522
}
@@ -539,7 +576,7 @@ func (lp *LocalPeer) connectOutbound(ctx context.Context, id uint64, addr string
539576

540577
// Dial with a timeout of 10 seconds.
541578
dialCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
542-
c, err = lp.dialer.DialContext(dialCtx, "tcp", addr)
579+
c, err = lp.dial(dialCtx, "tcp", addr)
543580
cancel()
544581
if err == nil {
545582
break

0 commit comments

Comments
 (0)