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 }