From 288870f043289282f8858775f350a6ee835583e7 Mon Sep 17 00:00:00 2001 From: Alex Akselrod Date: Wed, 16 Jan 2019 22:04:11 -0700 Subject: [PATCH 1/2] tor: add support for NULL authentication to controller This change allows the Tor controller to request hidden service configuration over unauthenticated Tor control ports, such as used in Whonix. --- tor/controller.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tor/controller.go b/tor/controller.go index 9b11bde66a4..aa8f74d5c9a 100644 --- a/tor/controller.go +++ b/tor/controller.go @@ -163,7 +163,7 @@ func parseTorReply(reply string) map[string]string { } // authenticate authenticates the connection between the controller and the -// Tor server using the SAFECOOKIE authentication method. +// Tor server using the SAFECOOKIE or NULL authentication method. func (c *Controller) authenticate() error { // Before proceeding to authenticate the connection, we'll retrieve // the authentication cookie of the Tor server. This will be used @@ -176,6 +176,13 @@ func (c *Controller) authenticate() error { "%v", err) } + // If cookie is empty and there's no error, we have a NULL + // authentication method that we should use instead. + if len(cookie) == 0 { + _, _, err := c.sendCommand("AUTHENTICATE") + return err + } + // Authenticating using the SAFECOOKIE authentication method is a two // step process. We'll kick off the authentication routine by sending // the AUTHCHALLENGE command followed by a hex-encoded 32-byte nonce. @@ -274,17 +281,21 @@ func (c *Controller) getAuthCookie() ([]byte, error) { c.version = version // Ensure that the Tor server supports the SAFECOOKIE authentication - // method. + // method or the NULL method. If NULL, we don't need the cookie info + // below this loop, so we just return. safeCookieSupport := false for _, authMethod := range authMethods { if authMethod == "SAFECOOKIE" { safeCookieSupport = true } + if authMethod == "NULL" { + return nil, nil + } } if !safeCookieSupport { return nil, errors.New("the Tor server is currently not " + - "configured for cookie authentication") + "configured for cookie or null authentication") } // Read the cookie from the file and ensure it has the correct length. @@ -374,7 +385,7 @@ func (c *Controller) ProtocolInfo() ([]string, string, string, error) { } cookieFile, ok := info["COOKIEFILE"] - if !ok { + if !ok && !strings.Contains(methods, "NULL") { return nil, "", "", errors.New("cookie file path not found " + "in reply") } From 66a150297a803d8ed85381a3b53397c80358100f Mon Sep 17 00:00:00 2001 From: Alex Akselrod Date: Wed, 16 Jan 2019 22:11:27 -0700 Subject: [PATCH 2/2] config: default to listening for p2p on localhost when tor enabled When Tor is enabled, this change allows manual hidden service configuration by defaulting to listening for p2p connections on the loopback address. It also allows overriding this manually for situations where the Tor daemon is running on another machine, such as when using Whonix or OnionPi-like systems. --- config.go | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/config.go b/config.go index 2441f11042d..78e7825d072 100644 --- a/config.go +++ b/config.go @@ -502,12 +502,6 @@ func loadConfig() (*config, error) { case cfg.DisableListen && (cfg.Tor.V2 || cfg.Tor.V3): return nil, errors.New("listening must be enabled when " + "enabling inbound connections over Tor") - case cfg.Tor.Active && (!cfg.Tor.V2 && !cfg.Tor.V3): - // If an onion service version wasn't selected, we'll assume the - // user is only interested in outbound connections over Tor. - // Therefore, we'll disable listening in order to avoid - // inadvertent leaks. - cfg.DisableListen = true } if cfg.Tor.PrivateKeyPath == "" { @@ -866,9 +860,14 @@ func loadConfig() (*config, error) { // Listen on the default interface/port if no listeners were specified. // An empty address string means default interface/address, which on - // most unix systems is the same as 0.0.0.0. + // most unix systems is the same as 0.0.0.0. If Tor is active, we + // default to only listening on localhost for hidden service + // connections. if len(cfg.RawListeners) == 0 { addr := fmt.Sprintf(":%d", defaultPeerPort) + if cfg.Tor.Active { + addr = fmt.Sprintf("localhost:%d", defaultPeerPort) + } cfg.RawListeners = append(cfg.RawListeners, addr) } @@ -948,20 +947,6 @@ func loadConfig() (*config, error) { } } - // Ensure that we are only listening on localhost if Tor inbound support - // is enabled. - if cfg.Tor.V2 || cfg.Tor.V3 { - for _, addr := range cfg.Listeners { - if lncfg.IsLoopback(addr.String()) { - continue - } - - return nil, errors.New("lnd must *only* be listening " + - "on localhost when running with Tor inbound " + - "support enabled") - } - } - // Ensure that the specified minimum backoff is below or equal to the // maximum backoff. if cfg.MinBackoff > cfg.MaxBackoff {