]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Don't expose Peer network through RemoteAddr
authorMatt Joiner <anacrolix@gmail.com>
Mon, 25 Jan 2021 03:22:24 +0000 (14:22 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Mon, 25 Jan 2021 04:49:48 +0000 (15:49 +1100)
client.go
ipport.go
peer_info.go
peerconn.go
peerconn_test.go
pex.go

index 2e8c5575a6db308ef6c90235065f85fd9b60e505..bda89c6f695cbddd027712720e7e829cc6afa905 100644 (file)
--- a/client.go
+++ b/client.go
@@ -677,7 +677,7 @@ func (cl *Client) initiateProtocolHandshakes(
        nc net.Conn,
        t *Torrent,
        outgoing, encryptHeader bool,
-       remoteAddr net.Addr,
+       remoteAddr PeerRemoteAddr,
        network, connString string,
 ) (
        c *PeerConn, err error,
@@ -699,7 +699,7 @@ func (cl *Client) initiateProtocolHandshakes(
 }
 
 // Returns nil connection and nil error if no connection could be established for valid reasons.
-func (cl *Client) establishOutgoingConnEx(t *Torrent, addr net.Addr, obfuscatedHeader bool) (*PeerConn, error) {
+func (cl *Client) establishOutgoingConnEx(t *Torrent, addr PeerRemoteAddr, obfuscatedHeader bool) (*PeerConn, error) {
        dialCtx, cancel := context.WithTimeout(context.Background(), func() time.Duration {
                cl.rLock()
                defer cl.rUnlock()
@@ -723,7 +723,7 @@ func (cl *Client) establishOutgoingConnEx(t *Torrent, addr net.Addr, obfuscatedH
 
 // Returns nil connection and nil error if no connection could be established
 // for valid reasons.
-func (cl *Client) establishOutgoingConn(t *Torrent, addr net.Addr) (c *PeerConn, err error) {
+func (cl *Client) establishOutgoingConn(t *Torrent, addr PeerRemoteAddr) (c *PeerConn, err error) {
        torrent.Add("establish outgoing connection", 1)
        obfuscatedHeaderFirst := cl.config.HeaderObfuscationPolicy.Preferred
        c, err = cl.establishOutgoingConnEx(t, addr, obfuscatedHeaderFirst)
@@ -748,7 +748,7 @@ func (cl *Client) establishOutgoingConn(t *Torrent, addr net.Addr) (c *PeerConn,
 
 // Called to dial out and run a connection. The addr we're given is already
 // considered half-open.
-func (cl *Client) outgoingConnection(t *Torrent, addr net.Addr, ps PeerSource, trusted bool) {
+func (cl *Client) outgoingConnection(t *Torrent, addr PeerRemoteAddr, ps PeerSource, trusted bool) {
        cl.dialRateLimiter.Wait(context.Background())
        c, err := cl.establishOutgoingConn(t, addr)
        cl.lock()
@@ -967,7 +967,7 @@ func (cl *Client) sendInitialMessages(conn *PeerConn, torrent *Torrent) {
                                        // that might be used to cache pending writes. Assuming 512KiB cached for
                                        // sending, for 16KiB chunks.
                                        Reqq:         1 << 5,
-                                       YourIp:       pp.CompactIp(addrIpOrNil(conn.RemoteAddr)),
+                                       YourIp:       pp.CompactIp(conn.remoteIp()),
                                        Encryption:   cl.config.HeaderObfuscationPolicy.Preferred || !cl.config.HeaderObfuscationPolicy.RequirePreferred,
                                        Port:         cl.incomingPeerPort(),
                                        MetadataSize: torrent.metadataSize(),
@@ -1062,7 +1062,7 @@ func (cl *Client) gotMetadataExtensionMsg(payload []byte, t *Torrent, c *PeerCon
        }
 }
 
-func (cl *Client) badPeerAddr(addr net.Addr) bool {
+func (cl *Client) badPeerAddr(addr PeerRemoteAddr) bool {
        if ipa, ok := tryIpPortFromNetAddr(addr); ok {
                return cl.badPeerIPPort(ipa.IP, ipa.Port)
        }
@@ -1099,7 +1099,8 @@ func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (
                peers: prioritizedPeers{
                        om: btree.New(32),
                        getPrio: func(p PeerInfo) peerPriority {
-                               return bep40PriorityIgnoreError(cl.publicAddr(addrIpOrNil(p.Addr)), p.addr())
+                               ipPort := p.addr()
+                               return bep40PriorityIgnoreError(cl.publicAddr(ipPort.IP), ipPort)
                        },
                },
                conns: make(map[*PeerConn]struct{}, 2*cl.config.EstablishedConnsPerTorrent),
@@ -1366,7 +1367,7 @@ func (cl *Client) banPeerIP(ip net.IP) {
        cl.badPeerIPs[ip.String()] = struct{}{}
 }
 
-func (cl *Client) newConnection(nc net.Conn, outgoing bool, remoteAddr net.Addr, network, connString string) (c *PeerConn) {
+func (cl *Client) newConnection(nc net.Conn, outgoing bool, remoteAddr PeerRemoteAddr, network, connString string) (c *PeerConn) {
        c = &PeerConn{
                Peer: Peer{
                        outgoing:        outgoing,
@@ -1483,7 +1484,7 @@ func (cl *Client) ListenAddrs() (ret []net.Addr) {
        return
 }
 
-func (cl *Client) onBadAccept(addr net.Addr) {
+func (cl *Client) onBadAccept(addr PeerRemoteAddr) {
        ipa, ok := tryIpPortFromNetAddr(addr)
        if !ok {
                return
index d65624c34d139b6c760f59adab4c7c840dc285d8..f710354a938362c2ce30c4c6dca465abb8763399 100644 (file)
--- a/ipport.go
+++ b/ipport.go
@@ -56,12 +56,15 @@ func (me ipPortAddr) String() string {
        return net.JoinHostPort(me.IP.String(), strconv.FormatInt(int64(me.Port), 10))
 }
 
-func tryIpPortFromNetAddr(na net.Addr) (ret ipPortAddr, ok bool) {
-       ret.IP = addrIpOrNil(na)
-       if ret.IP == nil {
-               return
+func tryIpPortFromNetAddr(addr PeerRemoteAddr) (ipPortAddr, bool) {
+       ok := true
+       host, port, err := net.SplitHostPort(addr.String())
+       if err != nil {
+               ok = false
        }
-       ret.Port = addrPortOrZero(na)
-       ok = true
-       return
+       portI64, err := strconv.ParseInt(port, 10, 0)
+       if err != nil {
+               ok = false
+       }
+       return ipPortAddr{net.ParseIP(host), int(portI64)}, ok
 }
index fdd74c52b284e30ad6a9bd8074840dc84204339c..e7b1b7c8053c1297403e4818e9c4b7b592f26789 100644 (file)
@@ -1,8 +1,6 @@
 package torrent
 
 import (
-       "net"
-
        "github.com/anacrolix/dht/v2/krpc"
 
        "github.com/anacrolix/torrent/peer_protocol"
@@ -11,7 +9,7 @@ import (
 // Peer connection info, handed about publicly.
 type PeerInfo struct {
        Id     [20]byte
-       Addr   net.Addr
+       Addr   PeerRemoteAddr
        Source PeerSource
        // Peer is known to support encryption.
        SupportsEncryption bool
@@ -41,5 +39,6 @@ func (me *PeerInfo) FromPex(na krpc.NodeAddr, fs peer_protocol.PexPeerFlags) {
 }
 
 func (me PeerInfo) addr() IpPort {
-       return IpPort{IP: addrIpOrNil(me.Addr), Port: uint16(addrPortOrZero(me.Addr))}
+       ipPort, _ := tryIpPortFromNetAddr(me.Addr)
+       return IpPort{ipPort.IP, uint16(ipPort.Port)}
 }
index 25d29b340469fefce107d99ef68c46640b615860..73ac8de63df6bdf973e83e979163146c4c658b69 100644 (file)
@@ -42,6 +42,10 @@ type peerRequestState struct {
        data []byte
 }
 
+type PeerRemoteAddr interface {
+       String() string
+}
+
 type Peer struct {
        // First to ensure 64-bit alignment for atomics. See #262.
        _stats ConnStats
@@ -52,7 +56,7 @@ type Peer struct {
 
        outgoing   bool
        network    string
-       RemoteAddr net.Addr
+       RemoteAddr PeerRemoteAddr
        // True if the connection is operating over MSE obfuscation.
        headerEncrypted bool
        cryptoMethod    mse.CryptoMethod
@@ -169,7 +173,7 @@ func (cn *Peer) expectingChunks() bool {
 
 // Returns true if the connection is over IPv6.
 func (cn *PeerConn) ipv6() bool {
-       ip := addrIpOrNil(cn.RemoteAddr)
+       ip := cn.remoteIp()
        if ip.To4() != nil {
                return false
        }
@@ -1626,7 +1630,8 @@ func (c *Peer) peerPriority() (peerPriority, error) {
 }
 
 func (c *Peer) remoteIp() net.IP {
-       return addrIpOrNil(c.RemoteAddr)
+       host, _, _ := net.SplitHostPort(c.RemoteAddr.String())
+       return net.ParseIP(host)
 }
 
 func (c *Peer) remoteIpPort() IpPort {
@@ -1642,7 +1647,7 @@ func (c *PeerConn) pexPeerFlags() pp.PexPeerFlags {
        if c.outgoing {
                f |= pp.PexOutgoingConn
        }
-       if c.RemoteAddr != nil && strings.Contains(c.RemoteAddr.Network(), "udp") {
+       if c.utp() {
                f |= pp.PexSupportsUtp
        }
        return f
@@ -1650,7 +1655,7 @@ func (c *PeerConn) pexPeerFlags() pp.PexPeerFlags {
 
 // This returns the address to use if we want to dial the peer again. It incorporates the peer's
 // advertised listen port.
-func (c *PeerConn) dialAddr() net.Addr {
+func (c *PeerConn) dialAddr() PeerRemoteAddr {
        if !c.outgoing && c.PeerListenPort != 0 {
                switch addr := c.RemoteAddr.(type) {
                case *net.TCPAddr:
index e56114d6b03245fe5afe02b4ad90954367d1115f..a65710894eb38992a67ca1b4aee41008cc30b5b7 100644 (file)
@@ -159,10 +159,10 @@ func TestConnPexPeerFlags(t *testing.T) {
                {&PeerConn{Peer: Peer{outgoing: false, PeerPrefersEncryption: true}}, pp.PexPrefersEncryption},
                {&PeerConn{Peer: Peer{outgoing: true, PeerPrefersEncryption: false}}, pp.PexOutgoingConn},
                {&PeerConn{Peer: Peer{outgoing: true, PeerPrefersEncryption: true}}, pp.PexOutgoingConn | pp.PexPrefersEncryption},
-               {&PeerConn{Peer: Peer{RemoteAddr: udpAddr}}, pp.PexSupportsUtp},
-               {&PeerConn{Peer: Peer{RemoteAddr: udpAddr, outgoing: true}}, pp.PexOutgoingConn | pp.PexSupportsUtp},
-               {&PeerConn{Peer: Peer{RemoteAddr: tcpAddr, outgoing: true}}, pp.PexOutgoingConn},
-               {&PeerConn{Peer: Peer{RemoteAddr: tcpAddr}}, 0},
+               {&PeerConn{Peer: Peer{RemoteAddr: udpAddr, network: udpAddr.Network()}}, pp.PexSupportsUtp},
+               {&PeerConn{Peer: Peer{RemoteAddr: udpAddr, network: udpAddr.Network(), outgoing: true}}, pp.PexOutgoingConn | pp.PexSupportsUtp},
+               {&PeerConn{Peer: Peer{RemoteAddr: tcpAddr, network: tcpAddr.Network(), outgoing: true}}, pp.PexOutgoingConn},
+               {&PeerConn{Peer: Peer{RemoteAddr: tcpAddr, network: tcpAddr.Network()}}, 0},
        }
        for i, tc := range testcases {
                f := tc.conn.pexPeerFlags()
@@ -184,22 +184,22 @@ func TestConnPexEvent(t *testing.T) {
        }{
                {
                        pexAdd,
-                       &PeerConn{Peer: Peer{RemoteAddr: udpAddr}},
+                       &PeerConn{Peer: Peer{RemoteAddr: udpAddr, network: udpAddr.Network()}},
                        pexEvent{pexAdd, udpAddr, pp.PexSupportsUtp},
                },
                {
                        pexDrop,
-                       &PeerConn{Peer: Peer{RemoteAddr: tcpAddr, outgoing: true, PeerListenPort: dialTcpAddr.Port}},
+                       &PeerConn{Peer: Peer{RemoteAddr: tcpAddr, network: tcpAddr.Network(), outgoing: true, PeerListenPort: dialTcpAddr.Port}},
                        pexEvent{pexDrop, tcpAddr, pp.PexOutgoingConn},
                },
                {
                        pexAdd,
-                       &PeerConn{Peer: Peer{RemoteAddr: tcpAddr, PeerListenPort: dialTcpAddr.Port}},
+                       &PeerConn{Peer: Peer{RemoteAddr: tcpAddr, network: tcpAddr.Network(), PeerListenPort: dialTcpAddr.Port}},
                        pexEvent{pexAdd, dialTcpAddr, 0},
                },
                {
                        pexDrop,
-                       &PeerConn{Peer: Peer{RemoteAddr: udpAddr, PeerListenPort: dialUdpAddr.Port}},
+                       &PeerConn{Peer: Peer{RemoteAddr: udpAddr, network: udpAddr.Network(), PeerListenPort: dialUdpAddr.Port}},
                        pexEvent{pexDrop, dialUdpAddr, pp.PexSupportsUtp},
                },
        }
diff --git a/pex.go b/pex.go
index 4771e70000efc721d9dabb295a044278e2003f25..83376d481c16b30b4d342c0322d90fc7742f84c5 100644 (file)
--- a/pex.go
+++ b/pex.go
@@ -25,7 +25,7 @@ const (
 // represents a single connection (t=pexAdd) or disconnection (t=pexDrop) event
 type pexEvent struct {
        t    pexEventType
-       addr net.Addr
+       addr PeerRemoteAddr
        f    pp.PexPeerFlags
 }
 
@@ -45,7 +45,7 @@ func (me *pexMsgFactory) DeltaLen() int {
 type addrKey string
 
 // Returns the key to use to identify a given addr in the factory.
-func (me *pexMsgFactory) addrKey(addr net.Addr) addrKey {
+func (me *pexMsgFactory) addrKey(addr PeerRemoteAddr) addrKey {
        return addrKey(addr.String())
 }
 
@@ -161,12 +161,10 @@ func (me *pexMsgFactory) PexMsg() pp.PexMsg {
 
 // Convert an arbitrary torrent peer Addr into one that can be represented by the compact addr
 // format.
-func nodeAddr(addr net.Addr) (_ krpc.NodeAddr, ok bool) {
-       ipport, ok := tryIpPortFromNetAddr(addr)
-       if !ok {
-               return
-       }
-       return krpc.NodeAddr{IP: shortestIP(ipport.IP), Port: ipport.Port}, true
+func nodeAddr(addr PeerRemoteAddr) (krpc.NodeAddr, bool) {
+       ipport, _ := tryIpPortFromNetAddr(addr)
+       ok := ipport.IP != nil
+       return krpc.NodeAddr{IP: shortestIP(ipport.IP), Port: ipport.Port}, ok
 }
 
 // mainly for the krpc marshallers