From 5baece5697ee52489dcbca1b55106a3b4cab0da8 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 02:12:09 +0000 Subject: [PATCH 01/15] tor: Refactor net function parameters to pass struct --- tor/net.go | 29 +++++++++++++++++++++-------- tor/tor.go | 50 +++++++++----------------------------------------- 2 files changed, 30 insertions(+), 49 deletions(-) diff --git a/tor/net.go b/tor/net.go index 8664cefc631..401411de239 100644 --- a/tor/net.go +++ b/tor/net.go @@ -3,6 +3,7 @@ package tor import ( "context" "errors" + "fmt" "net" "time" ) @@ -105,10 +106,25 @@ func (p *ProxyNet) Dial(network, address string, default: return nil, errors.New("cannot dial non-tcp network via Tor") } - return Dial( - address, p.SOCKS, p.StreamIsolation, - p.SkipProxyForClearNetTargets, timeout, - ) + + conn, err := dialProxy(address, p, timeout) + if err != nil { + return nil, fmt.Errorf("dial proxy failed: %w", err) + } + + // Now that the connection is established, we'll create our internal + // proxyConn that will serve in populating the correct remote address + // of the connection, rather than using the proxy's address. + remoteAddr, err := ParseAddr(address, p.SOCKS) + if err != nil { + return nil, err + } + + return &proxyConn{ + Conn: conn, + remoteAddr: remoteAddr, + }, nil + } // LookupHost uses the Tor LookupHost function in order to resolve hosts over @@ -122,10 +138,7 @@ func (p *ProxyNet) LookupHost(host string) ([]string, error) { 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.SkipProxyForClearNetTargets, timeout, - ) + return LookupSRV(service, proto, name, p, timeout) } // ResolveTCPAddr uses the Tor ResolveTCPAddr function in order to resolve TCP diff --git a/tor/tor.go b/tor/tor.go index 37d3fc2892f..5c5b0e44391 100644 --- a/tor/tor.go +++ b/tor/tor.go @@ -62,35 +62,6 @@ func (c *proxyConn) RemoteAddr() net.Addr { return c.remoteAddr } -// Dial is a wrapper over the non-exported dial function that returns a wrapper -// 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, - skipProxyForClearNetTargets bool, - timeout time.Duration) (net.Conn, error) { - - conn, err := dialProxy( - address, socksAddr, streamIsolation, - skipProxyForClearNetTargets, timeout, - ) - if err != nil { - return nil, fmt.Errorf("dial proxy failed: %w", err) - } - - // Now that the connection is established, we'll create our internal - // proxyConn that will serve in populating the correct remote address - // of the connection, rather than using the proxy's address. - remoteAddr, err := ParseAddr(address, socksAddr) - if err != nil { - return nil, err - } - - return &proxyConn{ - Conn: conn, - remoteAddr: remoteAddr, - }, nil -} - // dialProxy establishes a connection to the address via the provided TOR SOCKS // proxy. Only TCP traffic may be routed via Tor. // @@ -101,15 +72,14 @@ func Dial(address, socksAddr string, streamIsolation bool, // 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 dialProxy(address, socksAddr string, streamIsolation bool, - skipProxyForClearNetTargets bool, +func dialProxy(address string, proxyNet *ProxyNet, 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 // Tor will create a new circuit for each set of credentials. var auth *proxy.Auth - if streamIsolation { + if proxyNet.StreamIsolation { var b [16]byte if _, err := rand.Read(b[:]); err != nil { return nil, err @@ -122,7 +92,7 @@ func dialProxy(address, socksAddr string, streamIsolation bool, } clearDialer := &net.Dialer{Timeout: timeout} - if skipProxyForClearNetTargets { + if proxyNet.SkipProxyForClearNetTargets { host, _, err := net.SplitHostPort(address) if err != nil { return nil, err @@ -136,11 +106,13 @@ func dialProxy(address, socksAddr string, streamIsolation bool, } // Establish the connection through Tor's SOCKS proxy. - dialer, err := proxy.SOCKS5("tcp", socksAddr, auth, clearDialer) + dialer, err := proxy.SOCKS5("tcp", proxyNet.SOCKS, auth, clearDialer) if err != nil { return nil, fmt.Errorf("establish sock proxy: %w", err) } + // Skip for localhost + return dialer.Dial("tcp", address) } @@ -160,15 +132,11 @@ func LookupHost(host, socksAddr string) ([]string, error) { // natively support SRV queries so we must route all SRV queries through the // 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, skipProxyForClearNetTargets bool, - timeout time.Duration) (string, []*net.SRV, error) { +func LookupSRV(service, proto, name string, + proxyNet *ProxyNet, timeout time.Duration) (string, []*net.SRV, error) { // Connect to the DNS server we'll be using to query SRV records. - conn, err := dialProxy( - dnsServer, socksAddr, streamIsolation, - skipProxyForClearNetTargets, timeout, - ) + conn, err := dialProxy(proxyNet.DNS, proxyNet, timeout) if err != nil { return "", nil, err } From 8bea915d6056d0804dc20fc7b453f4da979db598 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Sun, 22 Aug 2021 12:28:00 +0900 Subject: [PATCH 02/15] tor+lncfg: Allow bypassing tor for specific networks/domains/hosts Defaults to loopback (127.0.0.0/8, ::1/128, localhost) Routing local connections over tor is practically always unintended and a potential security risk. --- config.go | 9 ++++++--- lncfg/tor.go | 1 + sample-lnd.conf | 7 +++++++ tor/net.go | 14 ++++++++++++-- tor/tor.go | 9 +++++++-- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/config.go b/config.go index 6d5bc546a88..9ac10525513 100644 --- a/config.go +++ b/config.go @@ -82,6 +82,7 @@ const ( defaultTorControlPort = 9051 defaultTorV2PrivateKeyFilename = "v2_onion_private_key" defaultTorV3PrivateKeyFilename = "v3_onion_private_key" + defaultTorNoProxyTargets = "localhost,::1/128,127.0.0.0/8" // defaultZMQReadDeadline is the default read deadline to be used for // both the block and tx ZMQ subscriptions. @@ -655,9 +656,10 @@ func DefaultConfig() Config { NumGraphSyncPeers: defaultMinPeers, HistoricalSyncInterval: discovery.DefaultHistoricalSyncInterval, Tor: &lncfg.Tor{ - SOCKS: defaultTorSOCKS, - DNS: defaultTorDNS, - Control: defaultTorControl, + SOCKS: defaultTorSOCKS, + DNS: defaultTorDNS, + Control: defaultTorControl, + NoProxyTargets: defaultTorNoProxyTargets, }, net: &tor.ClearNet{}, Workers: &lncfg.Workers{ @@ -1201,6 +1203,7 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, DNS: cfg.Tor.DNS, StreamIsolation: cfg.Tor.StreamIsolation, SkipProxyForClearNetTargets: cfg.Tor.SkipProxyForClearNetTargets, + NoProxyTargets: cfg.Tor.NoProxyTargets, } } diff --git a/lncfg/tor.go b/lncfg/tor.go index 932d5dfc904..85599438b2c 100644 --- a/lncfg/tor.go +++ b/lncfg/tor.go @@ -9,6 +9,7 @@ type Tor struct { 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."` + NoProxyTargets string `long:"no-proxy-targets" description:"Comma-separated values specifying hosts that should bypass the proxy. Each value is either an IP address, a CIDR range, a zone (*.example.com) or a host name (localhost). A best effort is made to parse the string and errors are ignored. (default: localhost,127.0.0.0/8,::1/128)` 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."` diff --git a/sample-lnd.conf b/sample-lnd.conf index 506b99914e5..3854c22ec80 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -959,6 +959,13 @@ ; be used only if privacy is not a concern. ; tor.skip-proxy-for-clearnet-targets=false +; Comma-separated list of specific hosts that should not be routed over Tor. +; Each value is either an +; IP address, a CIDR range, a zone (*.example.com) or a host name +; (localhost). A best effort is made to parse the string and errors are +; ignored. +; tor.no-proxy-targets=localhost,127.0.0.0/8,::1/128 + ; 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 ; between 1024 and 65535. diff --git a/tor/net.go b/tor/net.go index 401411de239..05b8fe69084 100644 --- a/tor/net.go +++ b/tor/net.go @@ -90,10 +90,20 @@ type ProxyNet struct { // will now use a distinct circuit. StreamIsolation bool - // SkipProxyForClearNetTargets allows the proxy network to use direct - // connections to non-onion service targets. If enabled, the node IP + // SkipProxyForClearNetTargets forces the proxy network to use direct + // connections for all non-onion service targets. If enabled, the node IP // address will be revealed while communicating with such targets. SkipProxyForClearNetTargets bool + + // NoProxyTargets specifies a list of hosts to bypass the proxy for. + // It allows the same formats as the golang NO_PROXY environment variable. + + // NoProxyTargets is a string of comma-separated values + // specifying hosts that should bypass the proxy. Each value is either an + // IP address, a CIDR range, a zone (*.example.com) or a host name + // (localhost). A best effort is made to parse the string and errors are + // ignored. + NoProxyTargets string } // Dial uses the Tor Dial function in order to establish connections through diff --git a/tor/tor.go b/tor/tor.go index 5c5b0e44391..e1b2a6ec396 100644 --- a/tor/tor.go +++ b/tor/tor.go @@ -111,9 +111,14 @@ func dialProxy(address string, proxyNet *ProxyNet, return nil, fmt.Errorf("establish sock proxy: %w", err) } - // Skip for localhost + if len(proxyNet.NoProxyTargets) == 0 { + return dialer.Dial("tcp", address) + } + + perHostDialer := proxy.NewPerHost(dialer, clearDialer) + perHostDialer.AddFromString(proxyNet.NoProxyTargets) - return dialer.Dial("tcp", address) + return perHostDialer.Dial("tcp", address) } // LookupHost performs DNS resolution on a given host via Tor's native resolver. From a6aaa9ade3ad140b38d76a931ea9c53808455478 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Sun, 22 Aug 2021 15:51:37 +0900 Subject: [PATCH 03/15] tor+lncfg: Allow specifying separate SOCKS proxy for non-Tor connections --- config.go | 54 ++++++++++++++++++++++++++++++++------- lncfg/tor.go | 2 +- sample-lnd.conf | 10 ++++++++ tor/net.go | 48 +++++++++++++++++++++++++++++------ tor/tor.go | 67 ++++++++++++++++++++++++++++--------------------- 5 files changed, 135 insertions(+), 46 deletions(-) diff --git a/config.go b/config.go index 9ac10525513..e9c8a1a6c13 100644 --- a/config.go +++ b/config.go @@ -76,6 +76,9 @@ const ( defaultLetsEncryptDirname = "letsencrypt" defaultLetsEncryptListen = ":80" + defaultNetSOCKS = "" + defaultNetNoProxyTargets = "localhost,::1/128,127.0.0.0/8" + defaultTorSOCKSPort = 9050 defaultTorDNSHost = "soa.nodes.lightning.directory" defaultTorDNSPort = 53 @@ -357,6 +360,8 @@ type Config struct { MinBackoff time.Duration `long:"minbackoff" description:"Shortest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."` MaxBackoff time.Duration `long:"maxbackoff" description:"Longest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."` ConnectionTimeout time.Duration `long:"connectiontimeout" description:"The timeout value for network connections. Valid time units are {ms, s, m, h}."` + SOCKS string `long:"socks" description:"The host:port that SOCKS5 proxy to use for any outbound connections not going over Tor"` + NoProxyTargets string `long:"no-proxy-targets" description:"Comma-separated values specifying hosts that should bypass the clearnet proxy. Each value is either an IP address, a CIDR range, a zone (*.example.com) or a host name (localhost). A best effort is made to parse the string and errors are ignored. (default: localhost,127.0.0.0/8,::1/128)"` DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify ,=,=,... to set the log level for individual subsystems -- Use show to list available subsystems"` @@ -661,7 +666,10 @@ func DefaultConfig() Config { Control: defaultTorControl, NoProxyTargets: defaultTorNoProxyTargets, }, - net: &tor.ClearNet{}, + net: &tor.ClearNet{ + SOCKS: defaultNetSOCKS, + NoProxyTargets: defaultNetNoProxyTargets, + }, Workers: &lncfg.Workers{ Read: lncfg.DefaultReadWorkers, Write: lncfg.DefaultWriteWorkers, @@ -1115,15 +1123,26 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, cfg.MaxCommitFeeRateAnchors) } + if cfg.SOCKS != "" { + socks, err := lncfg.ParseAddressString( + cfg.SOCKS, "", + cfg.net.ResolveTCPAddr, + ) + if err != nil { + return nil, err + } + cfg.SOCKS = socks.String() + } + // Validate the Tor config parameters. - socks, err := lncfg.ParseAddressString( + torSocks, err := lncfg.ParseAddressString( cfg.Tor.SOCKS, strconv.Itoa(defaultTorSOCKSPort), cfg.net.ResolveTCPAddr, ) if err != nil { return nil, err } - cfg.Tor.SOCKS = socks.String() + cfg.Tor.SOCKS = torSocks.String() // We'll only attempt to normalize and resolve the DNS host if it hasn't // changed, as it doesn't need to be done for the default. @@ -1197,14 +1216,31 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, // default. If we should be proxying all traffic through Tor, then // we'll use the Tor proxy specific functions in order to avoid leaking // our real information. + + clearNet := &tor.ClearNet{ + SOCKS: cfg.SOCKS, + NoProxyTargets: cfg.NoProxyTargets, + } if cfg.Tor.Active { - cfg.net = &tor.ProxyNet{ - SOCKS: cfg.Tor.SOCKS, - DNS: cfg.Tor.DNS, - StreamIsolation: cfg.Tor.StreamIsolation, - SkipProxyForClearNetTargets: cfg.Tor.SkipProxyForClearNetTargets, - NoProxyTargets: cfg.Tor.NoProxyTargets, + torNet := &tor.ProxyNet{ + SOCKS: cfg.Tor.SOCKS, + DNS: cfg.Tor.DNS, + StreamIsolation: cfg.Tor.StreamIsolation, + NoProxyTargets: cfg.Tor.NoProxyTargets, + ClearNet: clearNet, } + if !cfg.Tor.SkipProxyForClearNetTargets { + torNet.ClearNet = &tor.ProxyNet{ + SOCKS: cfg.Tor.SOCKS, + DNS: cfg.Tor.DNS, + StreamIsolation: cfg.Tor.StreamIsolation, + NoProxyTargets: cfg.Tor.NoProxyTargets, + ClearNet: clearNet, + } + } + cfg.net = torNet + } else { + cfg.net = clearNet } if cfg.DisableListen && cfg.NAT { diff --git a/lncfg/tor.go b/lncfg/tor.go index 85599438b2c..8cf0f656a79 100644 --- a/lncfg/tor.go +++ b/lncfg/tor.go @@ -9,7 +9,7 @@ type Tor struct { 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."` - NoProxyTargets string `long:"no-proxy-targets" description:"Comma-separated values specifying hosts that should bypass the proxy. Each value is either an IP address, a CIDR range, a zone (*.example.com) or a host name (localhost). A best effort is made to parse the string and errors are ignored. (default: localhost,127.0.0.0/8,::1/128)` + NoProxyTargets string `long:"no-proxy-targets" description:"Comma-separated values specifying hosts that should bypass the proxy. Each value is either an IP address, a CIDR range, a zone (*.example.com) or a host name (localhost). A best effort is made to parse the string and errors are ignored. (default: localhost,127.0.0.0/8,::1/128)"` 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."` diff --git a/sample-lnd.conf b/sample-lnd.conf index 3854c22ec80..56ba9cb5dce 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -234,6 +234,16 @@ ; support devices behind multiple NATs. ; nat=false +; The host:port that SOCKS5 proxy to use for any outbound connections not +; going over Tor. +; socks=127.0.0.1:8888 + +; Comma-separated values specifying hosts that should bypass the clearnet proxy. +; Each value is either an IP address, a CIDR range, a zone (*.example.com) or a +; host name (localhost). A best effort is made to parse the string and errors +; are ignored. (default: localhost,127.0.0.0/8,::1/128) +; no-proxy-targets=localhost,127.0.0.0/8,::1/128 + ; Disable REST API. ; norest=false diff --git a/tor/net.go b/tor/net.go index 05b8fe69084..045efaa425b 100644 --- a/tor/net.go +++ b/tor/net.go @@ -6,6 +6,8 @@ import ( "fmt" "net" "time" + + "golang.org/x/net/proxy" ) // TODO: this interface and its implementations should ideally be moved @@ -21,10 +23,15 @@ const ( // interface. type DialFunc func(net, addr string, timeout time.Duration) (net.Conn, error) +type Dialer interface { + Dial(network, address string) (net.Conn, error) +} + // Net is an interface housing a Dial function and several DNS functions that // allows us to abstract the implementations of these functions over different // networks, e.g. clearnet, Tor net, etc. type Net interface { + createDialer(auth *proxy.Auth, timeout time.Duration) (Dialer, error) // Dial connects to the address on the named network. Dial(network, address string, timeout time.Duration) (net.Conn, error) @@ -43,13 +50,41 @@ type Net interface { // ClearNet is an implementation of the Net interface that defines behaviour // for regular network connections. -type ClearNet struct{} +type ClearNet struct { + // SOCKS is the host:port for SOCKS5 proxy to use for clearnet connections. + SOCKS string + + // NoProxyTargets is a string of comma-separated values + // specifying hosts that should bypass the proxy. Each value is either an + // IP address, a CIDR range, a zone (*.example.com) or a host name + // (localhost). A best effort is made to parse the string and errors are + // ignored. + NoProxyTargets string +} + +func (r *ClearNet) createDialer(auth *proxy.Auth, timeout time.Duration) (Dialer, error) { + clearDialer := &net.Dialer{Timeout: timeout} + if r.SOCKS == "" { + return clearDialer, nil + } + dialer, err := proxy.SOCKS5("tcp", r.SOCKS, auth, clearDialer) + if err != nil { + return nil, err + } + perHostDialer := proxy.NewPerHost(dialer, clearDialer) + perHostDialer.AddFromString(r.NoProxyTargets) + return perHostDialer, nil +} // Dial on the regular network uses net.Dial func (r *ClearNet) Dial( network, address string, timeout time.Duration) (net.Conn, error) { - return net.DialTimeout(network, address, timeout) + dialer, err := r.createDialer(nil, timeout) + if err != nil { + return nil, err + } + return dialer.Dial(network, address) } // LookupHost for regular network uses the net.LookupHost function @@ -76,8 +111,7 @@ func (r *ClearNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) // ProxyNet is an implementation of the Net interface that defines behavior // for Tor network connections. type ProxyNet struct { - // SOCKS is the host:port which Tor's exposed SOCKS5 proxy is listening - // on. + // SOCKS is the host:port for SOCKS5 proxy to use for clearnet connections. SOCKS string // DNS is the host:port of the DNS server for Tor to use for SRV @@ -93,10 +127,6 @@ type ProxyNet struct { // SkipProxyForClearNetTargets forces the proxy network to use direct // connections for all non-onion service targets. If enabled, the node IP // address will be revealed while communicating with such targets. - SkipProxyForClearNetTargets bool - - // NoProxyTargets specifies a list of hosts to bypass the proxy for. - // It allows the same formats as the golang NO_PROXY environment variable. // NoProxyTargets is a string of comma-separated values // specifying hosts that should bypass the proxy. Each value is either an @@ -104,6 +134,8 @@ type ProxyNet struct { // (localhost). A best effort is made to parse the string and errors are // ignored. NoProxyTargets string + // Configuration to use for clearnet connections + ClearNet Net } // Dial uses the Tor Dial function in order to establish connections through diff --git a/tor/tor.go b/tor/tor.go index e1b2a6ec396..e2dd3614406 100644 --- a/tor/tor.go +++ b/tor/tor.go @@ -62,6 +62,33 @@ func (c *proxyConn) RemoteAddr() net.Addr { return c.remoteAddr } +func (pn *ProxyNet) createDialer(auth *proxy.Auth, timeout time.Duration) (Dialer, error) { + cn := &ClearNet{} + clearDialer, err := cn.createDialer(nil, timeout) + if err != nil { + return nil, err + } + dialer, err := proxy.SOCKS5("tcp", pn.SOCKS, auth, clearDialer) + if err != nil { + return nil, err + } + perHostDialer := proxy.NewPerHost(dialer, clearDialer) + perHostDialer.AddFromString(pn.NoProxyTargets) + return perHostDialer, nil +} + +func randomAuth() (*proxy.Auth, error) { + var b [16]byte + if _, err := rand.Read(b[:]); err != nil { + return nil, err + } + + return &proxy.Auth{ + User: hex.EncodeToString(b[:8]), + Password: hex.EncodeToString(b[8:]), + }, nil +} + // dialProxy establishes a connection to the address via the provided TOR SOCKS // proxy. Only TCP traffic may be routed via Tor. // @@ -79,46 +106,30 @@ func dialProxy(address string, proxyNet *ProxyNet, // we'll populate the authentication credentials with random data as // Tor will create a new circuit for each set of credentials. var auth *proxy.Auth + var err error if proxyNet.StreamIsolation { - var b [16]byte - if _, err := rand.Read(b[:]); err != nil { - return nil, err - } - - auth = &proxy.Auth{ - User: hex.EncodeToString(b[:8]), - Password: hex.EncodeToString(b[8:]), - } - } - - clearDialer := &net.Dialer{Timeout: timeout} - if proxyNet.SkipProxyForClearNetTargets { - host, _, err := net.SplitHostPort(address) + auth, err = randomAuth() if err != nil { return nil, err } - - // The SOCKS proxy is skipped if the target - // is not an union address. - if !IsOnionHost(host) { - return clearDialer.Dial("tcp", address) - } } - // Establish the connection through Tor's SOCKS proxy. - dialer, err := proxy.SOCKS5("tcp", proxyNet.SOCKS, auth, clearDialer) + host, _, err := net.SplitHostPort(address) if err != nil { return nil, fmt.Errorf("establish sock proxy: %w", err) } - if len(proxyNet.NoProxyTargets) == 0 { - return dialer.Dial("tcp", address) + var dialer Dialer + if IsOnionHost(host) { + dialer, err = proxyNet.createDialer(auth, timeout) + } else { + dialer, err = proxyNet.ClearNet.createDialer(auth, timeout) + } + if err != nil { + return nil, err } - perHostDialer := proxy.NewPerHost(dialer, clearDialer) - perHostDialer.AddFromString(proxyNet.NoProxyTargets) - - return perHostDialer.Dial("tcp", address) + return dialer.Dial("tcp", address) } // LookupHost performs DNS resolution on a given host via Tor's native resolver. From 93e24b7195ae41f9b87b062d933fadfd0bc12243 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Sun, 22 Aug 2021 16:41:26 +0900 Subject: [PATCH 04/15] tor+lncfg: Don't error when bypassing tor under stream isolation --- lnd.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lnd.go b/lnd.go index 76b08a114a1..ec748a388f1 100644 --- a/lnd.go +++ b/lnd.go @@ -137,10 +137,6 @@ type ListenerCfg struct { RPCListeners []*ListenerWithSignal } -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 // validated main configuration struct and an optional listener config struct. // This function starts all main system components then blocks until a signal @@ -514,7 +510,9 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg, } if cfg.Tor.StreamIsolation && cfg.Tor.SkipProxyForClearNetTargets { - return errStreamIsolationWithProxySkip + srvrLog.Warn("!!! Skipping Tor while Stream Isolation is on." + + "This has high risk of leaking your IP. Make sure this is " + + "what you want.") } if cfg.Tor.Active { From c341fa44be3f014f029fcf03e262af40a2c4774e Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Mon, 23 Aug 2021 12:23:14 +0900 Subject: [PATCH 05/15] tor: Allow supplying proxy credentials --- config.go | 13 ++++++++++++- tor/net.go | 12 ++++++++---- tor/tor.go | 34 +++++++++++++++++----------------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/config.go b/config.go index e9c8a1a6c13..db28aa8f833 100644 --- a/config.go +++ b/config.go @@ -44,6 +44,7 @@ import ( "github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/signal" "github.com/lightningnetwork/lnd/tor" + "golang.org/x/net/proxy" ) const ( @@ -1123,9 +1124,18 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, cfg.MaxCommitFeeRateAnchors) } + socksAuth := &proxy.Auth{} if cfg.SOCKS != "" { + socksAddress := cfg.SOCKS + if strings.Contains(socksAddress, "@") { + parts := strings.Split(socksAddress, "@") + socksAddress = parts[1] + creds := strings.Split(parts[0], ":") + socksAuth.User = creds[0] + socksAuth.Password = creds[1] + } socks, err := lncfg.ParseAddressString( - cfg.SOCKS, "", + socksAddress, "", cfg.net.ResolveTCPAddr, ) if err != nil { @@ -1219,6 +1229,7 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, clearNet := &tor.ClearNet{ SOCKS: cfg.SOCKS, + SOCKSAuth: socksAuth, NoProxyTargets: cfg.NoProxyTargets, } if cfg.Tor.Active { diff --git a/tor/net.go b/tor/net.go index 045efaa425b..595bb5f9895 100644 --- a/tor/net.go +++ b/tor/net.go @@ -31,7 +31,7 @@ type Dialer interface { // allows us to abstract the implementations of these functions over different // networks, e.g. clearnet, Tor net, etc. type Net interface { - createDialer(auth *proxy.Auth, timeout time.Duration) (Dialer, error) + createDialer(timeout time.Duration) (Dialer, error) // Dial connects to the address on the named network. Dial(network, address string, timeout time.Duration) (net.Conn, error) @@ -54,6 +54,9 @@ type ClearNet struct { // SOCKS is the host:port for SOCKS5 proxy to use for clearnet connections. SOCKS string + // SOCKSAuth contains credentials to use for authentication to SOCKS proxy. + SOCKSAuth *proxy.Auth + // NoProxyTargets is a string of comma-separated values // specifying hosts that should bypass the proxy. Each value is either an // IP address, a CIDR range, a zone (*.example.com) or a host name @@ -62,12 +65,13 @@ type ClearNet struct { NoProxyTargets string } -func (r *ClearNet) createDialer(auth *proxy.Auth, timeout time.Duration) (Dialer, error) { +func (r *ClearNet) createDialer(timeout time.Duration) (Dialer, error) { clearDialer := &net.Dialer{Timeout: timeout} if r.SOCKS == "" { return clearDialer, nil } - dialer, err := proxy.SOCKS5("tcp", r.SOCKS, auth, clearDialer) + + dialer, err := proxy.SOCKS5("tcp", r.SOCKS, r.SOCKSAuth, clearDialer) if err != nil { return nil, err } @@ -80,7 +84,7 @@ func (r *ClearNet) createDialer(auth *proxy.Auth, timeout time.Duration) (Dialer func (r *ClearNet) Dial( network, address string, timeout time.Duration) (net.Conn, error) { - dialer, err := r.createDialer(nil, timeout) + dialer, err := r.createDialer(timeout) if err != nil { return nil, err } diff --git a/tor/tor.go b/tor/tor.go index e2dd3614406..135f0de8707 100644 --- a/tor/tor.go +++ b/tor/tor.go @@ -62,16 +62,29 @@ func (c *proxyConn) RemoteAddr() net.Addr { return c.remoteAddr } -func (pn *ProxyNet) createDialer(auth *proxy.Auth, timeout time.Duration) (Dialer, error) { +func (pn *ProxyNet) createDialer(timeout time.Duration) (Dialer, error) { cn := &ClearNet{} - clearDialer, err := cn.createDialer(nil, timeout) + clearDialer, err := cn.createDialer(timeout) if err != nil { return nil, err } + + // If we were requested to force stream isolation for this connection, + // we'll populate the authentication credentials with random data as + // Tor will create a new circuit for each set of credentials. + var auth *proxy.Auth + if pn.StreamIsolation { + auth, err = randomAuth() + if err != nil { + return nil, err + } + } + dialer, err := proxy.SOCKS5("tcp", pn.SOCKS, auth, clearDialer) if err != nil { return nil, err } + perHostDialer := proxy.NewPerHost(dialer, clearDialer) perHostDialer.AddFromString(pn.NoProxyTargets) return perHostDialer, nil @@ -101,19 +114,6 @@ func randomAuth() (*proxy.Auth, error) { // the SOCKS proxy. func dialProxy(address string, proxyNet *ProxyNet, 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 - // Tor will create a new circuit for each set of credentials. - var auth *proxy.Auth - var err error - if proxyNet.StreamIsolation { - auth, err = randomAuth() - if err != nil { - return nil, err - } - } - host, _, err := net.SplitHostPort(address) if err != nil { return nil, fmt.Errorf("establish sock proxy: %w", err) @@ -121,9 +121,9 @@ func dialProxy(address string, proxyNet *ProxyNet, var dialer Dialer if IsOnionHost(host) { - dialer, err = proxyNet.createDialer(auth, timeout) + dialer, err = proxyNet.createDialer(timeout) } else { - dialer, err = proxyNet.ClearNet.createDialer(auth, timeout) + dialer, err = proxyNet.ClearNet.createDialer(timeout) } if err != nil { return nil, err From e38d7ec2b76384c0ecc68b5b3de6827049e6b0cd Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 02:14:37 +0000 Subject: [PATCH 06/15] grpc over tor fix --- cmd/commands/main.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmd/commands/main.go b/cmd/commands/main.go index a11b63b9d33..f9addf79941 100644 --- a/cmd/commands/main.go +++ b/cmd/commands/main.go @@ -212,13 +212,14 @@ func getClientConn(ctx *cli.Context, skipMacaroons bool) *grpc.ClientConn { // to connect to the grpc server. if ctx.GlobalIsSet("socksproxy") { socksProxy := ctx.GlobalString("socksproxy") + torNet := &tor.ClearNet{ + SOCKS: socksProxy, + } + torDialer := func(_ context.Context, addr string) (net.Conn, error) { - return tor.Dial( - addr, socksProxy, false, false, - tor.DefaultConnTimeout, - ) + return torNet.Dial("tcp", addr, tor.DefaultConnTimeout) } opts = append(opts, grpc.WithContextDialer(torDialer)) } else { From 9e4a195756f6191c912c908711d74250ee04b7a3 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 02:15:06 +0000 Subject: [PATCH 07/15] use repo-local github.com/lightningnetwork/lnd/tor --- go.mod | 6 ++++++ go.sum | 38 -------------------------------------- 2 files changed, 6 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index 9898b4d7f13..d8f97ec9156 100644 --- a/go.mod +++ b/go.mod @@ -220,6 +220,12 @@ replace github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2 // allows us to specify that as an option. replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-display v1.33.0-hex-display +// Temporary replace until the next version of tor is tagged. +replace ( + github.com/lightningnetwork/lnd/tor v0.0.0-local => ./tor + github.com/lightningnetwork/lnd/tor v1.1.6 => ./tor +) + // If you change this please also update docs/INSTALL.md and GO_VERSION in // Makefile (then run `make lint` to see where else it needs to be updated as // well). diff --git a/go.sum b/go.sum index ae6f41da12e..e826d663233 100644 --- a/go.sum +++ b/go.sum @@ -2,9 +2,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= @@ -96,11 +94,9 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= @@ -115,7 +111,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -130,9 +125,7 @@ github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0 github.com/decred/dcrd/lru v1.1.2 h1:KdCzlkxppuoIDGEvCGah1fZRicrDH36IipvlB1ROkFY= github.com/decred/dcrd/lru v1.1.2/go.mod h1:gEdCVgXs1/YoBvFWt7Scgknbhwik3FgVSzlnCcXL2N8= github.com/dhui/dktest v0.4.0 h1:z05UmuXZHO/bgj/ds2bGMBu8FI4WA+Ag/m3ghL+om7M= -github.com/dhui/dktest v0.4.0/go.mod h1:v/Dbz1LgCBOi2Uki2nUqLBGa83hWBGFMu5MrgMDCc78= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v28.1.1+incompatible h1:eyUemzeI45DY7eDPuwUcmDyDj1pM98oD5MdSpiItp8k= github.com/docker/cli v28.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I= @@ -148,7 +141,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fergusstrange/embedded-postgres v1.25.0 h1:sa+k2Ycrtz40eCRPOzI7Ry7TtkWXXJ+YRsxpKMDhxK0= @@ -172,7 +164,6 @@ github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= @@ -187,7 +178,6 @@ github.com/golang-migrate/migrate/v4 v4.17.0 h1:rd40H3QXU0AA4IoLllFcEAEo9dYKRHYN github.com/golang-migrate/migrate/v4 v4.17.0/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -209,10 +199,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= -github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -316,23 +304,16 @@ github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMW github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c h1:3UvYABOQRhJAApj9MdCN+Ydv841ETSoy6xLzdmmr/9A= -github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= github.com/juju/collections v0.0.0-20200605021417-0d0ec82b7271 h1:4R626WTwa7pRYQFiIRLVPepMhm05eZMEx+wIurRnMLc= -github.com/juju/collections v0.0.0-20200605021417-0d0ec82b7271/go.mod h1:5XgO71dV1JClcOJE+4dzdn4HrI5LiyKd7PlVG6eZYhY= github.com/juju/errors v0.0.0-20220203013757-bd733f3c86b9 h1:EJHbsNpQyupmMeWTq7inn+5L/WZ7JfzCVPJ+DP9McCQ= -github.com/juju/errors v0.0.0-20220203013757-bd733f3c86b9/go.mod h1:TRm7EVGA3mQOqSVcBySRY7a9Y1/gyVhh/WTCnc5sD4U= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 h1:NO5tuyw++EGLnz56Q8KMyDZRwJwWO8jQnj285J3FOmY= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg= github.com/juju/mgo/v2 v2.0.0-20210302023703-70d5d206e208 h1:/WiCm+Vpj87e4QWuWwPD/bNE9kDrWCLvPBHOQNcG2+A= -github.com/juju/mgo/v2 v2.0.0-20210302023703-70d5d206e208/go.mod h1:0OChplkvPTZ174D2FYZXg4IB9hbEwyHkD+zT+/eK+Fg= github.com/juju/retry v0.0.0-20180821225755-9058e192b216 h1:/eQL7EJQKFHByJe3DeE8Z36yqManj9UY5zppDoQi4FU= -github.com/juju/retry v0.0.0-20180821225755-9058e192b216/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494 h1:XEDzpuZb8Ma7vLja3+5hzUqVTvAqm5Y+ygvnDs5iTMM= github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494/go.mod h1:rUquetT0ALL48LHZhyRGvjjBH8xZaZ8dFClulKK5wK4= github.com/juju/utils/v3 v3.0.0-20220130232349-cd7ecef0e94a h1:5ZWDCeCF0RaITrZGemzmDFIhjR/MVSvBUqgSyaeTMbE= -github.com/juju/utils/v3 v3.0.0-20220130232349-cd7ecef0e94a/go.mod h1:LzwbbEN7buYjySp4nqnti6c6olSqRXUk6RkbSUUP1n8= github.com/juju/version/v2 v2.0.0-20211007103408-2e8da085dc23 h1:wtEPbidt1VyHlb8RSztU6ySQj29FLsOQiI9XiJhXDM4= -github.com/juju/version/v2 v2.0.0-20211007103408-2e8da085dc23/go.mod h1:Ljlbryh9sYaUSGXucslAEDf0A2XUSGvDbHJgW8ps6nc= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -348,12 +329,10 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -384,8 +363,6 @@ github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6 github.com/lightningnetwork/lnd/ticker v1.1.1/go.mod h1:waPTRAAcwtu7Ji3+3k+u/xH5GHovTsCoSVpho0KDvdA= github.com/lightningnetwork/lnd/tlv v1.3.2 h1:MO4FCk7F4k5xPMqVZF6Nb/kOpxlwPrUQpYjmyKny5s0= github.com/lightningnetwork/lnd/tlv v1.3.2/go.mod h1:pJuiBj1ecr1WWLOtcZ+2+hu9Ey25aJWFIsjmAoPPnmc= -github.com/lightningnetwork/lnd/tor v1.1.6 h1:WHUumk7WgU6BUFsqHuqszI9P6nfhMeIG+rjJBlVE6OE= -github.com/lightningnetwork/lnd/tor v1.1.6/go.mod h1:qSRB8llhAK+a6kaTPWOLLXSZc6Hg8ZC0mq1sUQ/8JfI= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= @@ -416,7 +393,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= @@ -429,7 +405,6 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -479,7 +454,6 @@ github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= @@ -563,7 +537,6 @@ go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8= @@ -585,7 +558,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -662,7 +634,6 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= -golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -765,7 +736,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -790,7 +760,6 @@ gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v1 v1.0.1 h1:oQFRXzZ7CkBGdm1XZm/EbQYaYNNEElNBOd09M6cqNso= gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -818,18 +787,13 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= -gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= -modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= -modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= -modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= -modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= @@ -839,9 +803,7 @@ modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWP modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= -modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= modernc.org/sqlite v1.29.10 h1:3u93dz83myFnMilBGCOLbr+HjklS6+5rJLx4q86RDAg= modernc.org/sqlite v1.29.10/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= From b1173be12fb2b44b07605f7fdc8a7bcaf6d57ecd Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 07:02:14 +0000 Subject: [PATCH 08/15] tor: make CreateDialer public --- tor/net.go | 6 +++--- tor/tor.go | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tor/net.go b/tor/net.go index 595bb5f9895..7fe208c88ca 100644 --- a/tor/net.go +++ b/tor/net.go @@ -31,7 +31,7 @@ type Dialer interface { // allows us to abstract the implementations of these functions over different // networks, e.g. clearnet, Tor net, etc. type Net interface { - createDialer(timeout time.Duration) (Dialer, error) + CreateDialer(timeout time.Duration) (Dialer, error) // Dial connects to the address on the named network. Dial(network, address string, timeout time.Duration) (net.Conn, error) @@ -65,7 +65,7 @@ type ClearNet struct { NoProxyTargets string } -func (r *ClearNet) createDialer(timeout time.Duration) (Dialer, error) { +func (r *ClearNet) CreateDialer(timeout time.Duration) (Dialer, error) { clearDialer := &net.Dialer{Timeout: timeout} if r.SOCKS == "" { return clearDialer, nil @@ -84,7 +84,7 @@ func (r *ClearNet) createDialer(timeout time.Duration) (Dialer, error) { func (r *ClearNet) Dial( network, address string, timeout time.Duration) (net.Conn, error) { - dialer, err := r.createDialer(timeout) + dialer, err := r.CreateDialer(timeout) if err != nil { return nil, err } diff --git a/tor/tor.go b/tor/tor.go index 135f0de8707..475294ad02f 100644 --- a/tor/tor.go +++ b/tor/tor.go @@ -62,9 +62,9 @@ func (c *proxyConn) RemoteAddr() net.Addr { return c.remoteAddr } -func (pn *ProxyNet) createDialer(timeout time.Duration) (Dialer, error) { +func (pn *ProxyNet) CreateDialer(timeout time.Duration) (Dialer, error) { cn := &ClearNet{} - clearDialer, err := cn.createDialer(timeout) + clearDialer, err := cn.CreateDialer(timeout) if err != nil { return nil, err } @@ -121,9 +121,9 @@ func dialProxy(address string, proxyNet *ProxyNet, var dialer Dialer if IsOnionHost(host) { - dialer, err = proxyNet.createDialer(timeout) + dialer, err = proxyNet.CreateDialer(timeout) } else { - dialer, err = proxyNet.ClearNet.createDialer(timeout) + dialer, err = proxyNet.ClearNet.CreateDialer(timeout) } if err != nil { return nil, err From 01712fc6391a1da4b4309503890ce0a360202607 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 03:54:11 +0000 Subject: [PATCH 09/15] tor: add godoc --- tor/net.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tor/net.go b/tor/net.go index 7fe208c88ca..8168c48445b 100644 --- a/tor/net.go +++ b/tor/net.go @@ -23,7 +23,10 @@ const ( // interface. type DialFunc func(net, addr string, timeout time.Duration) (net.Conn, error) +// Dialer is an interface housing the underlying implementation to open network +// sockets to peers. type Dialer interface { + // Dial connects to the address on the named network. Dial(network, address string) (net.Conn, error) } From 7d36b02359168f0db4a42231b7af2a31dcafcc57 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 03:54:13 +0000 Subject: [PATCH 10/15] tor: improve logging --- lnd.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lnd.go b/lnd.go index ec748a388f1..8039a6d9ecc 100644 --- a/lnd.go +++ b/lnd.go @@ -510,16 +510,17 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg, } if cfg.Tor.StreamIsolation && cfg.Tor.SkipProxyForClearNetTargets { - srvrLog.Warn("!!! Skipping Tor while Stream Isolation is on." + + srvrLog.Warn("Danger! Skipping Tor while Stream Isolation is on." + "This has high risk of leaking your IP. Make sure this is " + "what you want.") } if cfg.Tor.Active { - if cfg.Tor.SkipProxyForClearNetTargets { - srvrLog.InfoS(ctx, "Onion services are accessible "+ - "via Tor! NOTE: Traffic to clearnet services "+ - "is not routed via Tor.") + if cfg.Tor.NoProxyTargets != defaultNetNoProxyTargets { + srvrLog.InfoS(ctx, fmt.Printf("Proxying all network traffic "+ + "via Tor, EXCEPT [%s]! NOTE: Ensure the backend node is "+ + "proxying over Tor as well"), + "stream_isolation", cfg.Tor.StreamIsolation) } else { srvrLog.InfoS(ctx, "Proxying all network traffic "+ "via Tor! NOTE: Ensure the backend node is "+ From 821c69da3cb580fd04bb3c3a6befb1bde62bdc42 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 03:54:15 +0000 Subject: [PATCH 11/15] tor: remove dead godoc --- tor/net.go | 4 ---- tor/tor.go | 4 ---- 2 files changed, 8 deletions(-) diff --git a/tor/net.go b/tor/net.go index 8168c48445b..2c1987d988c 100644 --- a/tor/net.go +++ b/tor/net.go @@ -131,10 +131,6 @@ type ProxyNet struct { // will now use a distinct circuit. StreamIsolation bool - // SkipProxyForClearNetTargets forces the proxy network to use direct - // connections for all non-onion service targets. If enabled, the node IP - // address will be revealed while communicating with such targets. - // NoProxyTargets is a string of comma-separated values // specifying hosts that should bypass the proxy. Each value is either an // IP address, a CIDR range, a zone (*.example.com) or a host name diff --git a/tor/tor.go b/tor/tor.go index 475294ad02f..a2df78d0d4c 100644 --- a/tor/tor.go +++ b/tor/tor.go @@ -108,10 +108,6 @@ func randomAuth() (*proxy.Auth, error) { // streamIsolation determines if we should force stream isolation for this new // connection. If enabled, new connections will use a fresh circuit, rather than // possibly re-using an existing circuit. -// -// 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 dialProxy(address string, proxyNet *ProxyNet, timeout time.Duration) (net.Conn, error) { host, _, err := net.SplitHostPort(address) From bd7142ee5c6012514949ce31bf005c4e46c7054e Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 03:54:17 +0000 Subject: [PATCH 12/15] tor: fmt --- lnd.go | 7 ++++--- tor/net.go | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lnd.go b/lnd.go index 8039a6d9ecc..37fc83c6ee5 100644 --- a/lnd.go +++ b/lnd.go @@ -511,14 +511,15 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg, if cfg.Tor.StreamIsolation && cfg.Tor.SkipProxyForClearNetTargets { srvrLog.Warn("Danger! Skipping Tor while Stream Isolation is on." + - "This has high risk of leaking your IP. Make sure this is " + - "what you want.") + "This has high risk of leaking your IP. " + + "Make sure this is what you want.") } if cfg.Tor.Active { if cfg.Tor.NoProxyTargets != defaultNetNoProxyTargets { srvrLog.InfoS(ctx, fmt.Printf("Proxying all network traffic "+ - "via Tor, EXCEPT [%s]! NOTE: Ensure the backend node is "+ + "via Tor, EXCEPT [%s]! "+ + "NOTE: Ensure the backend node is "+ "proxying over Tor as well"), "stream_isolation", cfg.Tor.StreamIsolation) } else { diff --git a/tor/net.go b/tor/net.go index 2c1987d988c..4518cd8340c 100644 --- a/tor/net.go +++ b/tor/net.go @@ -78,6 +78,7 @@ func (r *ClearNet) CreateDialer(timeout time.Duration) (Dialer, error) { if err != nil { return nil, err } + perHostDialer := proxy.NewPerHost(dialer, clearDialer) perHostDialer.AddFromString(r.NoProxyTargets) return perHostDialer, nil @@ -91,6 +92,7 @@ func (r *ClearNet) Dial( if err != nil { return nil, err } + return dialer.Dial(network, address) } @@ -137,6 +139,7 @@ type ProxyNet struct { // (localhost). A best effort is made to parse the string and errors are // ignored. NoProxyTargets string + // Configuration to use for clearnet connections ClearNet Net } From 1add9bbecc3c7c4269e24ef7e62e77361d52f355 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 06:07:07 +0000 Subject: [PATCH 13/15] tor: refactor no-proxy-targets to be slice instead of comma-separated list-string omit value checks in linting since multi-value defaults are not supported by linting script - tor: socks flag doc rewrite --- config.go | 12 ++++++------ lncfg/tor.go | 28 ++++++++++++++-------------- lnd.go | 18 ++++++------------ sample-lnd.conf | 27 ++++++++++++++++++++------- scripts/check-sample-lnd-conf.sh | 2 +- 5 files changed, 47 insertions(+), 40 deletions(-) diff --git a/config.go b/config.go index db28aa8f833..3783d3fa131 100644 --- a/config.go +++ b/config.go @@ -361,8 +361,8 @@ type Config struct { MinBackoff time.Duration `long:"minbackoff" description:"Shortest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."` MaxBackoff time.Duration `long:"maxbackoff" description:"Longest backoff when reconnecting to persistent peers. Valid time units are {s, m, h}."` ConnectionTimeout time.Duration `long:"connectiontimeout" description:"The timeout value for network connections. Valid time units are {ms, s, m, h}."` - SOCKS string `long:"socks" description:"The host:port that SOCKS5 proxy to use for any outbound connections not going over Tor"` - NoProxyTargets string `long:"no-proxy-targets" description:"Comma-separated values specifying hosts that should bypass the clearnet proxy. Each value is either an IP address, a CIDR range, a zone (*.example.com) or a host name (localhost). A best effort is made to parse the string and errors are ignored. (default: localhost,127.0.0.0/8,::1/128)"` + SOCKS string `long:"socks" description:"The SOCKS5 proxy to use for any outbound connections not going over Tor with format [user:pass]@host:port"` + NoProxyTargets []string `long:"no-proxy-targets" description:"Specify a target that should bypass the configured proxy. Each value is either an IP address, a CIDR range, a zone (*.example.com) or a hostname (localhost). A best effort is made to parse the string and errors are ignored. Can be specified multiple times. (default: localhost,127.0.0.0/8,::1/128)"` DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify ,=,=,... to set the log level for individual subsystems -- Use show to list available subsystems"` @@ -665,7 +665,7 @@ func DefaultConfig() Config { SOCKS: defaultTorSOCKS, DNS: defaultTorDNS, Control: defaultTorControl, - NoProxyTargets: defaultTorNoProxyTargets, + NoProxyTargets: strings.Split(defaultTorNoProxyTargets, ","), }, net: &tor.ClearNet{ SOCKS: defaultNetSOCKS, @@ -1230,14 +1230,14 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, clearNet := &tor.ClearNet{ SOCKS: cfg.SOCKS, SOCKSAuth: socksAuth, - NoProxyTargets: cfg.NoProxyTargets, + NoProxyTargets: strings.Join(cfg.NoProxyTargets, ","), } if cfg.Tor.Active { torNet := &tor.ProxyNet{ SOCKS: cfg.Tor.SOCKS, DNS: cfg.Tor.DNS, StreamIsolation: cfg.Tor.StreamIsolation, - NoProxyTargets: cfg.Tor.NoProxyTargets, + NoProxyTargets: strings.Join(cfg.Tor.NoProxyTargets, ","), ClearNet: clearNet, } if !cfg.Tor.SkipProxyForClearNetTargets { @@ -1245,7 +1245,7 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, SOCKS: cfg.Tor.SOCKS, DNS: cfg.Tor.DNS, StreamIsolation: cfg.Tor.StreamIsolation, - NoProxyTargets: cfg.Tor.NoProxyTargets, + NoProxyTargets: strings.Join(cfg.Tor.NoProxyTargets, ","), ClearNet: clearNet, } } diff --git a/lncfg/tor.go b/lncfg/tor.go index 8cf0f656a79..07adb1a7a07 100644 --- a/lncfg/tor.go +++ b/lncfg/tor.go @@ -4,18 +4,18 @@ package lncfg // //nolint:ll 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."` - SkipProxyForClearNetTargets bool `long:"skip-proxy-for-clearnet-targets" description:"Allow the node to establish direct connections to services not running behind Tor."` - NoProxyTargets string `long:"no-proxy-targets" description:"Comma-separated values specifying hosts that should bypass the proxy. Each value is either an IP address, a CIDR range, a zone (*.example.com) or a host name (localhost). A best effort is made to parse the string and errors are ignored. (default: localhost,127.0.0.0/8,::1/128)"` - 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:"DEPRECATED: Tor v2 onion services are obsolete and support will be removed in v0.21.0. Use v3 instead." hidden:"true"` - 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"` - EncryptKey bool `long:"encryptkey" description:"Encrypts the Tor private key file on disk"` - 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."` + NoProxyTargets []string `long:"no-proxy-targets" description:"Specify a target that should bypass the configured proxy. Each value is either an IP address, a CIDR range, a zone (*.example.com) or a hostname (localhost). A best effort is made to parse the string and errors are ignored. Can be specified multiple times. (default: localhost,127.0.0.0/8,::1/128)"` + 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:"DEPRECATED: Tor v2 onion services are obsolete and support will be removed in v0.21.0. Use v3 instead." hidden:"true"` + 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"` + EncryptKey bool `long:"encryptkey" description:"Encrypts the Tor private key file on disk"` + 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 37fc83c6ee5..2eeba4eebf8 100644 --- a/lnd.go +++ b/lnd.go @@ -516,18 +516,12 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg, } if cfg.Tor.Active { - if cfg.Tor.NoProxyTargets != defaultNetNoProxyTargets { - srvrLog.InfoS(ctx, fmt.Printf("Proxying all network traffic "+ - "via Tor, EXCEPT [%s]! "+ - "NOTE: Ensure the backend node is "+ - "proxying over Tor as well"), - "stream_isolation", cfg.Tor.StreamIsolation) - } else { - srvrLog.InfoS(ctx, "Proxying all network traffic "+ - "via Tor! NOTE: Ensure the backend node is "+ - "proxying over Tor as well", - "stream_isolation", cfg.Tor.StreamIsolation) - } + srvrLog.InfoS(ctx, "Proxying all network traffic "+ + "via Tor! NOTE: Ensure the backend node is "+ + "proxying over Tor as well", + "tor_no_proxy_targets", strings.Join(cfg.Tor.NoProxyTargets, ","), + "no_proxy_targets", strings.Join(cfg.NoProxyTargets, ","), + "stream_isolation", cfg.Tor.StreamIsolation) } // If tor is active and either v2 or v3 onion services have been diff --git a/sample-lnd.conf b/sample-lnd.conf index 56ba9cb5dce..92822f8478b 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -234,15 +234,23 @@ ; support devices behind multiple NATs. ; nat=false -; The host:port that SOCKS5 proxy to use for any outbound connections not +; The host:port of SOCKS5 proxy to use for any outbound connections not ; going over Tor. -; socks=127.0.0.1:8888 +; Example: +; socks=proxyuser:proxypassword@127.0.0.1:8888 +; Default: +; socks= -; Comma-separated values specifying hosts that should bypass the clearnet proxy. +; Specify a target that should bypass the clearnet proxy. ; Each value is either an IP address, a CIDR range, a zone (*.example.com) or a ; host name (localhost). A best effort is made to parse the string and errors -; are ignored. (default: localhost,127.0.0.0/8,::1/128) -; no-proxy-targets=localhost,127.0.0.0/8,::1/128 +; are ignored. +; Default: +; no-proxy-targets=localhost +; no-proxy-targets=127.0.0.0/8 +; no-proxy-targets=::1/128 +; Example (option can be specified multiple times): +; no-proxy-targets=192.168.0.0/16 ; Disable REST API. ; norest=false @@ -969,12 +977,17 @@ ; be used only if privacy is not a concern. ; tor.skip-proxy-for-clearnet-targets=false -; Comma-separated list of specific hosts that should not be routed over Tor. +; Specify a target that should not be routed over Tor. ; Each value is either an ; IP address, a CIDR range, a zone (*.example.com) or a host name ; (localhost). A best effort is made to parse the string and errors are ; ignored. -; tor.no-proxy-targets=localhost,127.0.0.0/8,::1/128 +; Default: +; tor.no-proxy-targets=localhost +; tor.no-proxy-targets=127.0.0.0/8 +; tor.no-proxy-targets=::1/128 +; Example (option can be specified multiple times): +; tor.no-proxy-targets=192.168.0.0/16 ; 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/scripts/check-sample-lnd-conf.sh b/scripts/check-sample-lnd-conf.sh index 48cbad7f60b..ede1ded0f8e 100755 --- a/scripts/check-sample-lnd-conf.sh +++ b/scripts/check-sample-lnd-conf.sh @@ -59,7 +59,7 @@ OPTIONS_NO_LND_DEFAULT_VALUE_CHECK="channel-max-fee-exposure adminmacaroonpath \ backupfilepath maxchansize bitcoin.chaindir bitcoin.defaultchanconfs \ bitcoin.defaultremotedelay bitcoin.dnsseed signrpc.signermacaroonpath \ walletrpc.walletkitmacaroonpath chainrpc.notifiermacaroonpath \ - routerrpc.routermacaroonpath" + routerrpc.routermacaroonpath no-proxy-targets tor.no-proxy-targets" # EXITCODE is returned at the end after all checks are performed and set to 1 From 468728f0b97f1db2e7eec7d34c722cc750fdc4e2 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 10:34:21 +0000 Subject: [PATCH 14/15] tor: fmt --- config.go | 10 ++++++---- lnd.go | 7 ++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/config.go b/config.go index 3783d3fa131..fe5f382b647 100644 --- a/config.go +++ b/config.go @@ -1237,16 +1237,18 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, SOCKS: cfg.Tor.SOCKS, DNS: cfg.Tor.DNS, StreamIsolation: cfg.Tor.StreamIsolation, - NoProxyTargets: strings.Join(cfg.Tor.NoProxyTargets, ","), - ClearNet: clearNet, + NoProxyTargets: strings.Join( + cfg.Tor.NoProxyTargets, ","), + ClearNet: clearNet, } if !cfg.Tor.SkipProxyForClearNetTargets { torNet.ClearNet = &tor.ProxyNet{ SOCKS: cfg.Tor.SOCKS, DNS: cfg.Tor.DNS, StreamIsolation: cfg.Tor.StreamIsolation, - NoProxyTargets: strings.Join(cfg.Tor.NoProxyTargets, ","), - ClearNet: clearNet, + NoProxyTargets: strings.Join( + cfg.Tor.NoProxyTargets, ","), + ClearNet: clearNet, } } cfg.net = torNet diff --git a/lnd.go b/lnd.go index 2eeba4eebf8..33f8770825d 100644 --- a/lnd.go +++ b/lnd.go @@ -510,9 +510,10 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg, } if cfg.Tor.StreamIsolation && cfg.Tor.SkipProxyForClearNetTargets { - srvrLog.Warn("Danger! Skipping Tor while Stream Isolation is on." + - "This has high risk of leaking your IP. " + - "Make sure this is what you want.") + srvrLog.Warn( + "Danger! Skipping Tor while Stream Isolation is on." + + "This has high risk of leaking your IP. " + + "Make sure this is what you want.") } if cfg.Tor.Active { From f66c0e509b114998e1ae7929b2b724742e189858 Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Tue, 23 Sep 2025 10:47:11 +0000 Subject: [PATCH 15/15] chore: go mod tidy --- go.mod | 2 +- go.sum | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d8f97ec9156..fa2bee964d7 100644 --- a/go.mod +++ b/go.mod @@ -181,7 +181,7 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.39.0 // indirect + golang.org/x/net v0.39.0 golang.org/x/sys v0.32.0 // indirect golang.org/x/text v0.24.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect diff --git a/go.sum b/go.sum index e826d663233..e338089db32 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,9 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= @@ -94,9 +96,11 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= @@ -111,6 +115,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -125,7 +130,9 @@ github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0 github.com/decred/dcrd/lru v1.1.2 h1:KdCzlkxppuoIDGEvCGah1fZRicrDH36IipvlB1ROkFY= github.com/decred/dcrd/lru v1.1.2/go.mod h1:gEdCVgXs1/YoBvFWt7Scgknbhwik3FgVSzlnCcXL2N8= github.com/dhui/dktest v0.4.0 h1:z05UmuXZHO/bgj/ds2bGMBu8FI4WA+Ag/m3ghL+om7M= +github.com/dhui/dktest v0.4.0/go.mod h1:v/Dbz1LgCBOi2Uki2nUqLBGa83hWBGFMu5MrgMDCc78= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v28.1.1+incompatible h1:eyUemzeI45DY7eDPuwUcmDyDj1pM98oD5MdSpiItp8k= github.com/docker/cli v28.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I= @@ -141,6 +148,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fergusstrange/embedded-postgres v1.25.0 h1:sa+k2Ycrtz40eCRPOzI7Ry7TtkWXXJ+YRsxpKMDhxK0= @@ -164,6 +172,7 @@ github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= @@ -178,6 +187,7 @@ github.com/golang-migrate/migrate/v4 v4.17.0 h1:rd40H3QXU0AA4IoLllFcEAEo9dYKRHYN github.com/golang-migrate/migrate/v4 v4.17.0/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -199,8 +209,10 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -304,16 +316,23 @@ github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMW github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c h1:3UvYABOQRhJAApj9MdCN+Ydv841ETSoy6xLzdmmr/9A= +github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= github.com/juju/collections v0.0.0-20200605021417-0d0ec82b7271 h1:4R626WTwa7pRYQFiIRLVPepMhm05eZMEx+wIurRnMLc= +github.com/juju/collections v0.0.0-20200605021417-0d0ec82b7271/go.mod h1:5XgO71dV1JClcOJE+4dzdn4HrI5LiyKd7PlVG6eZYhY= github.com/juju/errors v0.0.0-20220203013757-bd733f3c86b9 h1:EJHbsNpQyupmMeWTq7inn+5L/WZ7JfzCVPJ+DP9McCQ= +github.com/juju/errors v0.0.0-20220203013757-bd733f3c86b9/go.mod h1:TRm7EVGA3mQOqSVcBySRY7a9Y1/gyVhh/WTCnc5sD4U= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 h1:NO5tuyw++EGLnz56Q8KMyDZRwJwWO8jQnj285J3FOmY= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg= github.com/juju/mgo/v2 v2.0.0-20210302023703-70d5d206e208 h1:/WiCm+Vpj87e4QWuWwPD/bNE9kDrWCLvPBHOQNcG2+A= +github.com/juju/mgo/v2 v2.0.0-20210302023703-70d5d206e208/go.mod h1:0OChplkvPTZ174D2FYZXg4IB9hbEwyHkD+zT+/eK+Fg= github.com/juju/retry v0.0.0-20180821225755-9058e192b216 h1:/eQL7EJQKFHByJe3DeE8Z36yqManj9UY5zppDoQi4FU= +github.com/juju/retry v0.0.0-20180821225755-9058e192b216/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494 h1:XEDzpuZb8Ma7vLja3+5hzUqVTvAqm5Y+ygvnDs5iTMM= github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494/go.mod h1:rUquetT0ALL48LHZhyRGvjjBH8xZaZ8dFClulKK5wK4= github.com/juju/utils/v3 v3.0.0-20220130232349-cd7ecef0e94a h1:5ZWDCeCF0RaITrZGemzmDFIhjR/MVSvBUqgSyaeTMbE= +github.com/juju/utils/v3 v3.0.0-20220130232349-cd7ecef0e94a/go.mod h1:LzwbbEN7buYjySp4nqnti6c6olSqRXUk6RkbSUUP1n8= github.com/juju/version/v2 v2.0.0-20211007103408-2e8da085dc23 h1:wtEPbidt1VyHlb8RSztU6ySQj29FLsOQiI9XiJhXDM4= +github.com/juju/version/v2 v2.0.0-20211007103408-2e8da085dc23/go.mod h1:Ljlbryh9sYaUSGXucslAEDf0A2XUSGvDbHJgW8ps6nc= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -329,10 +348,12 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -393,6 +414,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= @@ -405,6 +427,7 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -454,6 +477,7 @@ github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= @@ -537,6 +561,7 @@ go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8= @@ -558,6 +583,7 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -634,6 +660,7 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= +golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -736,6 +763,7 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -760,6 +788,7 @@ gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v1 v1.0.1 h1:oQFRXzZ7CkBGdm1XZm/EbQYaYNNEElNBOd09M6cqNso= gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -787,13 +816,18 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= +gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= +modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= +modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= +modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= +modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= @@ -803,7 +837,9 @@ modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWP modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= +modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= modernc.org/sqlite v1.29.10 h1:3u93dz83myFnMilBGCOLbr+HjklS6+5rJLx4q86RDAg= modernc.org/sqlite v1.29.10/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=