diff --git a/config.go b/config.go index d07e6c22b..6e836ea64 100644 --- a/config.go +++ b/config.go @@ -906,10 +906,10 @@ func ValidateConfig(cfg Config, usageMessage string, // our real information. if cfg.Tor.Active { cfg.net = &tor.ProxyNet{ - SOCKS: cfg.Tor.SOCKS, - DNS: cfg.Tor.DNS, - StreamIsolation: cfg.Tor.StreamIsolation, - DirectConnections: cfg.Tor.DirectConnections, + SOCKS: cfg.Tor.SOCKS, + DNS: cfg.Tor.DNS, + StreamIsolation: cfg.Tor.StreamIsolation, + SkipProxyForClearNetTargets: cfg.Tor.SkipProxyForClearNetTargets, } } @@ -1317,7 +1317,7 @@ func ValidateConfig(cfg Config, usageMessage string, // connections. if len(cfg.RawListeners) == 0 { addr := fmt.Sprintf(":%d", defaultPeerPort) - if cfg.Tor.Active && !cfg.Tor.DirectConnections { + if cfg.Tor.Active && !cfg.Tor.SkipProxyForClearNetTargets { addr = fmt.Sprintf("localhost:%d", defaultPeerPort) } cfg.RawListeners = append(cfg.RawListeners, addr) diff --git a/lncfg/tor.go b/lncfg/tor.go index 8051e399f..be58e7ea5 100644 --- a/lncfg/tor.go +++ b/lncfg/tor.go @@ -2,16 +2,16 @@ package lncfg // Tor holds the configuration options for the daemon's connection to tor. type Tor struct { - Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"` - SOCKS string `long:"socks" description:"The host:port that Tor's exposed SOCKS5 proxy is listening on"` - DNS string `long:"dns" description:"The DNS server as host:port that Tor will use for SRV queries - NOTE must have TCP resolution enabled"` - StreamIsolation bool `long:"streamisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` - DirectConnections bool `long:"directconnections" description:"Allow the node to establish direct connections to services not running behind Tor."` - Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"` - TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"` - Password string `long:"password" description:"The password used to arrive at the HashedControlPassword for the control port. If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."` - V2 bool `long:"v2" description:"Automatically set up a v2 onion service to listen for inbound connections"` - V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"` - PrivateKeyPath string `long:"privatekeypath" description:"The path to the private key of the onion service being created"` - WatchtowerKeyPath string `long:"watchtowerkeypath" description:"The path to the private key of the watchtower onion service being created"` + Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"` + SOCKS string `long:"socks" description:"The host:port that Tor's exposed SOCKS5 proxy is listening on"` + DNS string `long:"dns" description:"The DNS server as host:port that Tor will use for SRV queries - NOTE must have TCP resolution enabled"` + StreamIsolation bool `long:"streamisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` + SkipProxyForClearNetTargets bool `long:"skip-proxy-for-clearnet-targets" description:"Allow the node to establish direct connections to services not running behind Tor."` + Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"` + TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"` + Password string `long:"password" description:"The password used to arrive at the HashedControlPassword for the control port. If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."` + V2 bool `long:"v2" description:"Automatically set up a v2 onion service to listen for inbound connections"` + V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"` + PrivateKeyPath string `long:"privatekeypath" description:"The path to the private key of the onion service being created"` + WatchtowerKeyPath string `long:"watchtowerkeypath" description:"The path to the private key of the watchtower onion service being created"` } diff --git a/lnd.go b/lnd.go index a00dc9ca1..9a8f89d56 100644 --- a/lnd.go +++ b/lnd.go @@ -169,8 +169,8 @@ type ListenerCfg struct { ExternalRestRegistrar RestRegistrar } -var errStreamIsolationWithDirectConnections = errors.New( - "direct connections cannot be used while stream isolation is enabled", +var errStreamIsolationWithProxySkip = errors.New( + "while stream isolation is enabled, the TOR proxy may not be skipped", ) // Main is the true entry point for lnd. It accepts a fully populated and @@ -757,12 +757,12 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error return err } - if cfg.Tor.StreamIsolation && cfg.Tor.DirectConnections { - return errStreamIsolationWithDirectConnections + if cfg.Tor.StreamIsolation && cfg.Tor.SkipProxyForClearNetTargets { + return errStreamIsolationWithProxySkip } if cfg.Tor.Active { - if cfg.Tor.DirectConnections { + if cfg.Tor.SkipProxyForClearNetTargets { srvrLog.Info("Onion services are accessible via Tor! NOTE: " + "Traffic to clearnet services is not routed via Tor.") } else { diff --git a/sample-lnd.conf b/sample-lnd.conf index 235347047..030c1fc24 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -832,7 +832,7 @@ litecoin.node=ltcd ; Tor, thus allowing lower latency and better connection stability. ; WARNING: This option will reveal the source IP address of the node, and should ; be used only if privacy is not a concern. -; tor.directconnections=true +; tor.skip-proxy-for-clearnet-targets=true ; The port that Tor's exposed SOCKS5 proxy is listening on. Using Tor allows ; outbound-only connections (listening will be disabled) -- NOTE port must be diff --git a/tor/net.go b/tor/net.go index 26990edf0..e96c79acd 100644 --- a/tor/net.go +++ b/tor/net.go @@ -89,10 +89,10 @@ type ProxyNet struct { // will now use a distinct circuit. StreamIsolation bool - // DirectConnections allows the proxy network to use direct connections - // to non-onion service targets. If enabled, the node IP address will be - // revealed while communicating with such targets. - DirectConnections bool + // SkipProxyForClearNetTargets allows the proxy network to use direct + // connections to non-onion service targets. If enabled, the node IP + // address will be revealed while communicating with such targets. + SkipProxyForClearNetTargets bool } // Dial uses the Tor Dial function in order to establish connections through @@ -106,7 +106,8 @@ func (p *ProxyNet) Dial(network, address string, return nil, errors.New("cannot dial non-tcp network via Tor") } return Dial( - address, p.SOCKS, p.StreamIsolation, p.DirectConnections, timeout, + address, p.SOCKS, p.StreamIsolation, + p.SkipProxyForClearNetTargets, timeout, ) } @@ -122,8 +123,8 @@ func (p *ProxyNet) LookupSRV(service, proto, name string, timeout time.Duration) (string, []*net.SRV, error) { return LookupSRV( - service, proto, name, p.SOCKS, p.DNS, - p.StreamIsolation, p.DirectConnections, timeout, + service, proto, name, p.SOCKS, p.DNS, p.StreamIsolation, + p.SkipProxyForClearNetTargets, timeout, ) } diff --git a/tor/tor.go b/tor/tor.go index 9db879195..c373a250e 100644 --- a/tor/tor.go +++ b/tor/tor.go @@ -66,10 +66,11 @@ func (c *proxyConn) RemoteAddr() net.Addr { // around net.Conn in order to expose the actual remote address we're dialing, // rather than the proxy's address. func Dial(address, socksAddr string, streamIsolation bool, - directConnections bool, timeout time.Duration) (net.Conn, error) { + skipProxyForClearNetTargets bool, timeout time.Duration) (net.Conn, error) { conn, err := dial( - address, socksAddr, streamIsolation, directConnections, timeout, + address, socksAddr, streamIsolation, + skipProxyForClearNetTargets, timeout, ) if err != nil { return nil, err @@ -96,11 +97,11 @@ func Dial(address, socksAddr string, streamIsolation bool, // connection. If enabled, new connections will use a fresh circuit, rather than // possibly re-using an existing circuit. // -// directConnections argument allows the dialer to directly connect to the -// provided address if it does not represent an union service, skipping the -// SOCKS proxy. +// skipProxyForClearNetTargets argument allows the dialer to directly connect +// to the provided address if it does not represent an union service, skipping +// the SOCKS proxy. func dial(address, socksAddr string, streamIsolation bool, - directConnections bool, timeout time.Duration) (net.Conn, error) { + skipProxyForClearNetTargets bool, timeout time.Duration) (net.Conn, error) { // If we were requested to force stream isolation for this connection, // we'll populate the authentication credentials with random data as @@ -119,7 +120,7 @@ func dial(address, socksAddr string, streamIsolation bool, } clearDialer := &net.Dialer{Timeout: timeout} - if directConnections { + if skipProxyForClearNetTargets { host, _, err := net.SplitHostPort(address) if err != nil { return nil, err @@ -158,12 +159,13 @@ func LookupHost(host, socksAddr string) ([]string, error) { // proxy by connecting directly to a DNS server and querying it. The DNS server // must have TCP resolution enabled for the given port. func LookupSRV(service, proto, name, socksAddr, - dnsServer string, streamIsolation bool, - directConnections bool, timeout time.Duration) (string, []*net.SRV, error) { + dnsServer string, streamIsolation bool, skipProxyForClearNetTargets bool, + timeout time.Duration) (string, []*net.SRV, error) { // Connect to the DNS server we'll be using to query SRV records. conn, err := dial( - dnsServer, socksAddr, streamIsolation, directConnections, timeout, + dnsServer, socksAddr, streamIsolation, + skipProxyForClearNetTargets, timeout, ) if err != nil { return "", nil, err