From 91b7f5c1c8e05d76bb9d110aa2029c1d705ed8f1 Mon Sep 17 00:00:00 2001 From: Javed Khan Date: Tue, 6 Dec 2016 23:05:55 +0530 Subject: [PATCH] config: Refactor tor config options. * Remove unnecessary onionlookup func. * Disallow --noonion and --onion flag combination. * Tor isolation flag - prefer onion proxy. * Proper argument names in cfg.oniondial closure. * btcdLookup - error on onion address. * Bridge mode - use onion for lookup --- config.go | 82 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/config.go b/config.go index 2d451015..1c9b2522 100644 --- a/config.go +++ b/config.go @@ -147,7 +147,6 @@ type config struct { DropAddrIndex bool `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up and then exits."` RelayNonStd bool `long:"relaynonstd" description:"Relay non-standard transactions regardless of the default settings for the active network."` RejectNonStd bool `long:"rejectnonstd" description:"Reject non-standard transactions regardless of the default settings for the active network."` - onionlookup func(string) ([]net.IP, error) lookup func(string) ([]net.IP, error) oniondial func(string, string, time.Duration) (net.Conn, error) dial func(string, string, time.Duration) (net.Conn, error) @@ -796,6 +795,15 @@ func loadConfig() (*config, []string, error) { cfg.ConnectPeers = normalizeAddresses(cfg.ConnectPeers, activeNetParams.DefaultPort) + // --noonion and --onion do not mix. + if cfg.NoOnion && cfg.OnionProxy != "" { + err := fmt.Errorf("%s: the --noonion and --onion options may "+ + "not be activated at the same time", funcName) + fmt.Fprintln(os.Stderr, err) + fmt.Fprintln(os.Stderr, usageMessage) + return nil, nil, err + } + // Tor stream isolation requires either proxy or onion proxy to be set. if cfg.TorIsolation && cfg.Proxy == "" && cfg.OnionProxy == "" { str := "%s: Tor stream isolation requires either proxy or " + @@ -824,8 +832,14 @@ func loadConfig() (*config, []string, error) { return nil, nil, err } - if cfg.TorIsolation && + // Tor isolation flag means proxy credentials will be overridden + // unless there is also an onion proxy configured in which case + // that one will be overridden. + torIsolation := false + if cfg.TorIsolation && cfg.OnionProxy == "" && (cfg.ProxyUser != "" || cfg.ProxyPass != "") { + + torIsolation = true fmt.Fprintln(os.Stderr, "Tor isolation set -- "+ "overriding specified proxy user credentials") } @@ -834,24 +848,26 @@ func loadConfig() (*config, []string, error) { Addr: cfg.Proxy, Username: cfg.ProxyUser, Password: cfg.ProxyPass, - TorIsolation: cfg.TorIsolation, + TorIsolation: torIsolation, } cfg.dial = proxy.DialTimeout - if !cfg.NoOnion { + + // Treat the proxy as tor and perform DNS resolution through it + // unless the --noonion flag is set or there is an + // onion-specific proxy configured. + if !cfg.NoOnion && cfg.OnionProxy == "" { cfg.lookup = func(host string) ([]net.IP, error) { return connmgr.TorLookupIP(host, cfg.Proxy) } } } - // Setup onion address dial and DNS resolution (lookup) functions - // depending on the specified options. The default is to use the - // same dial and lookup functions selected above. However, when an - // onion-specific proxy is specified, the onion address dial and - // lookup functions are set to use the onion-specific proxy while - // leaving the normal dial and lookup functions as selected above. - // This allows .onion address traffic to be routed through a different - // proxy than normal traffic. + // Setup onion address dial function depending on the specified options. + // The default is to use the same dial function selected above. However, + // when an onion-specific proxy is specified, the onion address dial + // function is set to use the onion-specific proxy while leaving the + // normal dial function as selected above. This allows .onion address + // traffic to be routed through a different proxy than normal traffic. if cfg.OnionProxy != "" { _, _, err := net.SplitHostPort(cfg.OnionProxy) if err != nil { @@ -862,6 +878,8 @@ func loadConfig() (*config, []string, error) { return nil, nil, err } + // Tor isolation flag means onion proxy credentials will be + // overridden. if cfg.TorIsolation && (cfg.OnionProxyUser != "" || cfg.OnionProxyPass != "") { fmt.Fprintln(os.Stderr, "Tor isolation set -- "+ @@ -869,32 +887,35 @@ func loadConfig() (*config, []string, error) { "credentials ") } - cfg.oniondial = func(a, b string, t time.Duration) (net.Conn, error) { + cfg.oniondial = func(network, addr string, timeout time.Duration) (net.Conn, error) { proxy := &socks.Proxy{ Addr: cfg.OnionProxy, Username: cfg.OnionProxyUser, Password: cfg.OnionProxyPass, TorIsolation: cfg.TorIsolation, } - return proxy.DialTimeout(a, b, t) + return proxy.DialTimeout(network, addr, timeout) } - cfg.onionlookup = func(host string) ([]net.IP, error) { - return connmgr.TorLookupIP(host, cfg.OnionProxy) + + // When configured in bridge mode (both --onion and --proxy are + // configured), it means that the proxy configured by --proxy is + // not a tor proxy, so override the DNS resolution to use the + // onion-specific proxy. + if cfg.Proxy != "" { + cfg.lookup = func(host string) ([]net.IP, error) { + return connmgr.TorLookupIP(host, cfg.OnionProxy) + } } } else { cfg.oniondial = cfg.dial - cfg.onionlookup = cfg.lookup } - // Specifying --noonion means the onion address dial and DNS resolution - // (lookup) functions result in an error. + // Specifying --noonion means the onion address dial function results in + // an error. if cfg.NoOnion { cfg.oniondial = func(a, b string, t time.Duration) (net.Conn, error) { return nil, errors.New("tor has been disabled") } - cfg.onionlookup = func(a string) ([]net.IP, error) { - return nil, errors.New("tor has been disabled") - } } // Warn about missing config file only after all other configuration is @@ -987,16 +1008,17 @@ func btcdDial(addr net.Addr) (net.Conn, error) { return cfg.dial(addr.Network(), addr.String(), defaultConnectTimeout) } -// btcdLookup returns the correct DNS lookup function to use depending on the -// passed host and configuration options. For example, .onion addresses will be -// resolved using the onion specific proxy if one was specified, but will -// otherwise treat the normal proxy as tor unless --noonion was specified in -// which case the lookup will fail. Meanwhile, normal IP addresses will be -// resolved using tor if a proxy was specified unless --noonion was also -// specified in which case the normal system DNS resolver will be used. +// btcdLookup resolves the IP of the given host using the correct DNS lookup +// function depending on the configuration options. For example, addresses will +// be resolved using tor when the --proxy flag was specified unless --noonion +// was also specified in which case the normal system DNS resolver will be used. +// +// Any attempt to resolve a tor address (.onion) will return an error since they +// are not intended to be resolved outside of the tor proxy. func btcdLookup(host string) ([]net.IP, error) { if strings.HasSuffix(host, ".onion") { - return cfg.onionlookup(host) + return nil, fmt.Errorf("attempt to resolve tor address %s", host) } + return cfg.lookup(host) }