github.com/decred/dcrlnd@v0.7.6/tor/net.go (about)

     1  package tor
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net"
     7  	"time"
     8  )
     9  
    10  // TODO: this interface and its implementations should ideally be moved
    11  // elsewhere as they are not Tor-specific.
    12  
    13  const (
    14  	// DefaultConnTimeout is the maximum amount of time a dial will wait for
    15  	// a connect to complete.
    16  	DefaultConnTimeout time.Duration = time.Second * 120
    17  )
    18  
    19  // DialFunc is a type defines the signature of a dialer used by our Net
    20  // interface.
    21  type DialFunc func(net, addr string, timeout time.Duration) (net.Conn, error)
    22  
    23  // Net is an interface housing a Dial function and several DNS functions that
    24  // allows us to abstract the implementations of these functions over different
    25  // networks, e.g. clearnet, Tor net, etc.
    26  type Net interface {
    27  	// Dial connects to the address on the named network.
    28  	Dial(network, address string, timeout time.Duration) (net.Conn, error)
    29  
    30  	// LookupHost performs DNS resolution on a given host and returns its
    31  	// addresses.
    32  	LookupHost(host string) ([]string, error)
    33  
    34  	// LookupSRV tries to resolve an SRV query of the given service,
    35  	// protocol, and domain name.
    36  	LookupSRV(service, proto, name string,
    37  		timeout time.Duration) (string, []*net.SRV, error)
    38  
    39  	// ResolveTCPAddr resolves TCP addresses.
    40  	ResolveTCPAddr(network, address string) (*net.TCPAddr, error)
    41  }
    42  
    43  // ClearNet is an implementation of the Net interface that defines behaviour
    44  // for regular network connections.
    45  type ClearNet struct{}
    46  
    47  // Dial on the regular network uses net.Dial
    48  func (r *ClearNet) Dial(
    49  	network, address string, timeout time.Duration) (net.Conn, error) {
    50  
    51  	return net.DialTimeout(network, address, timeout)
    52  }
    53  
    54  // LookupHost for regular network uses the net.LookupHost function
    55  func (r *ClearNet) LookupHost(host string) ([]string, error) {
    56  	return net.LookupHost(host)
    57  }
    58  
    59  // LookupSRV for regular network uses net.LookupSRV function
    60  func (r *ClearNet) LookupSRV(service, proto, name string,
    61  	timeout time.Duration) (string, []*net.SRV, error) {
    62  
    63  	// Create a context with a timeout value.
    64  	ctxt, cancel := context.WithTimeout(context.Background(), timeout)
    65  	defer cancel()
    66  
    67  	return net.DefaultResolver.LookupSRV(ctxt, service, proto, name)
    68  }
    69  
    70  // ResolveTCPAddr for regular network uses net.ResolveTCPAddr function
    71  func (r *ClearNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) {
    72  	return net.ResolveTCPAddr(network, address)
    73  }
    74  
    75  // ProxyNet is an implementation of the Net interface that defines behavior
    76  // for Tor network connections.
    77  type ProxyNet struct {
    78  	// SOCKS is the host:port which Tor's exposed SOCKS5 proxy is listening
    79  	// on.
    80  	SOCKS string
    81  
    82  	// DNS is the host:port of the DNS server for Tor to use for SRV
    83  	// queries.
    84  	DNS string
    85  
    86  	// StreamIsolation is a bool that determines if we should force the
    87  	// creation of a new circuit for this connection. If true, then this
    88  	// means that our traffic may be harder to correlate as each connection
    89  	// will now use a distinct circuit.
    90  	StreamIsolation bool
    91  
    92  	// SkipProxyForClearNetTargets allows the proxy network to use direct
    93  	// connections to non-onion service targets. If enabled, the node IP
    94  	// address will be revealed while communicating with such targets.
    95  	SkipProxyForClearNetTargets bool
    96  }
    97  
    98  // Dial uses the Tor Dial function in order to establish connections through
    99  // Tor. Since Tor only supports TCP connections, only TCP networks are allowed.
   100  func (p *ProxyNet) Dial(network, address string,
   101  	timeout time.Duration) (net.Conn, error) {
   102  
   103  	switch network {
   104  	case "tcp", "tcp4", "tcp6":
   105  	default:
   106  		return nil, errors.New("cannot dial non-tcp network via Tor")
   107  	}
   108  	return Dial(
   109  		address, p.SOCKS, p.StreamIsolation,
   110  		p.SkipProxyForClearNetTargets, timeout,
   111  	)
   112  }
   113  
   114  // LookupHost uses the Tor LookupHost function in order to resolve hosts over
   115  // Tor.
   116  func (p *ProxyNet) LookupHost(host string) ([]string, error) {
   117  	return LookupHost(host, p.SOCKS)
   118  }
   119  
   120  // LookupSRV uses the Tor LookupSRV function in order to resolve SRV DNS queries
   121  // over Tor.
   122  func (p *ProxyNet) LookupSRV(service, proto,
   123  	name string, timeout time.Duration) (string, []*net.SRV, error) {
   124  
   125  	return LookupSRV(
   126  		service, proto, name, p.SOCKS, p.DNS, p.StreamIsolation,
   127  		p.SkipProxyForClearNetTargets, timeout,
   128  	)
   129  }
   130  
   131  // ResolveTCPAddr uses the Tor ResolveTCPAddr function in order to resolve TCP
   132  // addresses over Tor.
   133  func (p *ProxyNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) {
   134  	switch network {
   135  	case "tcp", "tcp4", "tcp6":
   136  	default:
   137  		return nil, errors.New("cannot dial non-tcp network via Tor")
   138  	}
   139  	return ResolveTCPAddr(address, p.SOCKS)
   140  }