diff --git a/brontide/conn.go b/brontide/conn.go index 9903c790..0edc2ee2 100644 --- a/brontide/conn.go +++ b/brontide/conn.go @@ -38,11 +38,10 @@ func Dial(localPriv *btcec.PrivateKey, netAddr *lnwire.NetAddress, var conn net.Conn var err error if dialer == nil { - // A Tor proxy dial function WAS NOT passed in. + // A dial function WAS NOT passed in. conn, err = net.Dial("tcp", ipAddr) } else { - // A Tor proxy dial function WAS passed in so we use it instead - // of golang's net.Dial. + // A dial function WAS passed in so we use it instead. conn, err = dialer[0]("tcp", ipAddr) } if err != nil { diff --git a/config.go b/config.go index 609b9142..2fd59518 100644 --- a/config.go +++ b/config.go @@ -20,7 +20,6 @@ import ( flags "github.com/jessevdk/go-flags" "github.com/lightningnetwork/lnd/brontide" "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/torsvc" "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcutil" ) @@ -187,10 +186,7 @@ type config struct { Alias string `long:"alias" description:"The node alias. Used as a moniker by peers and intelligence services"` Color string `long:"color" description:"The color of the node in hex format (i.e. '#3399FF'). Used to customize node appearance in intelligence services"` - dial func(string, string) (net.Conn, error) - lookup func(string) ([]string, error) - lookupSRV func(string, string, string) (string, []*net.SRV, error) - resolveTCP func(string, string) (*net.TCPAddr, error) + net NetInterface } // loadConfig initializes and parses the config using a config file and command @@ -300,9 +296,7 @@ func loadConfig() (*config, error) { // functions. When Tor's proxy is specified, the dial function is set to // the proxy specific dial function and the DNS resolution functions use // Tor. - cfg.lookup = net.LookupHost - cfg.lookupSRV = net.LookupSRV - cfg.resolveTCP = net.ResolveTCPAddr + cfg.net = &RegularNet{} if cfg.TorSocks != "" && cfg.TorDNS != "" { // Validate Tor port number torport, err := strconv.Atoi(cfg.TorSocks) @@ -324,22 +318,13 @@ func loadConfig() (*config, error) { return nil, err } - cfg.dial = torsvc.TorDial(cfg.TorSocks) - // If we are using Tor, since we only want connections routed // through Tor, listening is disabled. cfg.DisableListen = true - cfg.lookup = func(host string) ([]string, error) { - return torsvc.TorLookupHost(host, cfg.TorSocks) - } - cfg.lookupSRV = func(service, proto, name string) (cname string, - addrs []*net.SRV, err error) { - return torsvc.TorLookupSRV(service, proto, name, - cfg.TorSocks, cfg.TorDNS) - } - cfg.resolveTCP = func(network, address string) (*net.TCPAddr, error) { - return torsvc.TorResolveTCP(address, cfg.TorSocks) + cfg.net = &TorProxyNet{ + TorSocks: cfg.TorSocks, + TorDNS: cfg.TorDNS, } } @@ -684,36 +669,10 @@ func supportedSubsystems() []string { func noiseDial(idPriv *btcec.PrivateKey) func(net.Addr) (net.Conn, error) { return func(a net.Addr) (net.Conn, error) { lnAddr := a.(*lnwire.NetAddress) - if cfg.dial == nil { - return brontide.Dial(idPriv, lnAddr) - } - return brontide.Dial(idPriv, lnAddr, cfg.dial) + return brontide.Dial(idPriv, lnAddr, cfg.net.Dial) } } -// lndLookup resolves the IP address of a given host using the correct DNS -// function depending on the lookup configuration options. Lookup can be done -// via golang's system resolver or via Tor. When Tor is used, only IPv4 -// addresses are returned. -func lndLookup(host string) ([]string, error) { - return cfg.lookup(host) -} - -// lndLookupSRV queries a DNS server with SRV requests depending on the -// configuration options. SRV queries can be done via golang's system -// resolver or through (but not by!) Tor. -func lndLookupSRV(service, proto, name string) (string, []*net.SRV, error) { - return cfg.lookupSRV(service, proto, name) -} - -// lndResolveTCP resolves TCP addresses into type *net.TCPAddr. Depending on -// configuration options, this resolution can be done via golang's system -// resolver or via Tor. -func lndResolveTCP(network, address string) (*net.TCPAddr, error) { - return cfg.resolveTCP(network, address) -} - - func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode, funcName string) error { // If the configuration has already set the RPCUser and RPCPass, and diff --git a/networking.go b/networking.go new file mode 100644 index 00000000..3f5e6e03 --- /dev/null +++ b/networking.go @@ -0,0 +1,76 @@ +package main + +import ( + "net" + + "github.com/lightningnetwork/lnd/torsvc" +) + +// NetInterface is an interface housing a Dial function and several DNS functions. +type NetInterface interface { + Dial(string, string) (net.Conn, error) + LookupHost(string) ([]string, error) + LookupSRV(string, string, string) (string, []*net.SRV, error) + ResolveTCPAddr(string, string) (*net.TCPAddr, error) +} + +// RegularNet is an implementation of NetInterface that uses the net package +// for everything. +type RegularNet struct{} + +// TorProxyNet is an implementation of NetInterface that uses the torsvc module. +type TorProxyNet struct { + TorSocks string + TorDNS string +} + +// A compile time check to ensure RegularNet implements the NetInterface +// interface. +var _ NetInterface = (*RegularNet)(nil) + +// A compile time check to ensure TorProxyNet implements the NetInterface +// interface. +var _ NetInterface = (*TorProxyNet)(nil) + +// Dial is a wrapper of net.Dial +func (r *RegularNet) Dial(network, address string) (net.Conn, error) { + return net.Dial(network, address) +} + +// LookupHost is a wrapper of net.LookupHost +func (r *RegularNet) LookupHost(host string) ([]string, error) { + return net.LookupHost(host) +} + +// LookupSRV is a wrapper of net.LookupSRV +func (r *RegularNet) LookupSRV(service, proto, name string) (string, []*net.SRV, + error) { + return net.LookupSRV(service, proto, name) +} + +// ResolveTCPAddr is a wrapper of net.ResolveTCPAddr +func (r *RegularNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) { + return net.ResolveTCPAddr(network, address) +} + +// Dial is a wrapper of torsvc.TorDial +func (t *TorProxyNet) Dial(network, address string) (net.Conn, error) { + return torsvc.TorDial(address, t.TorSocks) +} + +// LookupHost is a wrapper of torsvc.TorLookupHost +func (t *TorProxyNet) LookupHost(host string) ([]string, error) { + return torsvc.TorLookupHost(host, t.TorSocks) +} + +// LookupSRV is a wrapper of torsvc.TorLookupSRV +func (t *TorProxyNet) LookupSRV(service, proto, name string) (string, []*net.SRV, + error) { + return torsvc.TorLookupSRV(service, proto, name, t.TorSocks, t.TorDNS) +} + +// ResolveTCPAddr is a wrapper of torsvc.TorResolveTCP +func (t *TorProxyNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, + error) { + return torsvc.TorResolveTCP(address, t.TorSocks) +} diff --git a/rpcserver.go b/rpcserver.go index 436889e2..910d41ad 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -590,7 +590,7 @@ func (r *rpcServer) ConnectPeer(ctx context.Context, } // We use lndResolveTCP here in case we wish to resolve hosts over Tor. - host, err := lndResolveTCP("tcp", addr) + host, err := cfg.net.ResolveTCPAddr("tcp", addr) if err != nil { return nil, err } diff --git a/server.go b/server.go index 13b022ac..2aca4a65 100644 --- a/server.go +++ b/server.go @@ -227,7 +227,7 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl, addr = ip } - lnAddr, err := lndResolveTCP("tcp", addr) + lnAddr, err := cfg.net.ResolveTCPAddr("tcp", addr) if err != nil { return nil, err } @@ -605,8 +605,8 @@ func initNetworkBootstrappers(s *server) ([]discovery.NetworkPeerBootstrapper, e dnsBootStrapper, err := discovery.NewDNSSeedBootstrapper( dnsSeeds, - lndLookup, - lndLookupSRV, + cfg.net.LookupHost, + cfg.net.LookupSRV, ) if err != nil { return nil, err @@ -646,18 +646,10 @@ func (s *server) peerBootstrapper(numTargetPeers uint32, // With our initial set of peers obtained, we'll launch a goroutine to // attempt to connect out to each of them. We'll be waking up shortly - // below to sample how many of these connections succeeded. We check - // cfg.dial for nil in case Tor's proxy dialer option was set in the - // configuration. + // below to sample how many of these connections succeeded. for _, addr := range bootStrapAddrs { go func(a *lnwire.NetAddress) { - var conn *brontide.Conn - var err error - if cfg.dial == nil { - conn, err = brontide.Dial(s.identityPriv, a) - } else { - conn, err = brontide.Dial(s.identityPriv, a, cfg.dial) - } + conn, err := brontide.Dial(s.identityPriv, a, cfg.net.Dial) if err != nil { srvrLog.Errorf("unable to connect to %v: %v", a, err) @@ -767,16 +759,8 @@ func (s *server) peerBootstrapper(numTargetPeers uint32, go func(a *lnwire.NetAddress) { // TODO(roasbeef): can do AS, subnet, // country diversity, etc - // We check cfg.dial for nil in case - // a Tor's proxy dialer configuration was - // set. - var conn *brontide.Conn - var err error - if cfg.dial == nil { - conn, err = brontide.Dial(s.identityPriv, a) - } else { - conn, err = brontide.Dial(s.identityPriv, a, cfg.dial) - } + conn, err := brontide.Dial(s.identityPriv, + a, cfg.net.Dial) if err != nil { srvrLog.Errorf("unable to connect "+ "to %v: %v", a, err) @@ -1294,7 +1278,7 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, brontideConn := conn.(*brontide.Conn) var peerAddr *lnwire.NetAddress - if cfg.dial == nil { + if _, ok := cfg.net.(*RegularNet); ok { peerAddr = &lnwire.NetAddress{ IdentityKey: brontideConn.RemotePub(), Address: conn.RemoteAddr().(*net.TCPAddr), @@ -1696,14 +1680,8 @@ func (s *server) ConnectToPeer(addr *lnwire.NetAddress, perm bool) error { // If we're not making a persistent connection, then we'll attempt to // connect to the target peer. If the we can't make the connection, or // the crypto negotiation breaks down, then return an error to the - // caller. We check cfg.dial for nil in case Tor's proxy dialer function - // was set in the configuration options. - var conn *brontide.Conn - if cfg.dial == nil { - conn, err = brontide.Dial(s.identityPriv, addr) - } else { - conn, err = brontide.Dial(s.identityPriv, addr, cfg.dial) - } + // caller. + conn, err := brontide.Dial(s.identityPriv, addr, cfg.net.Dial) if err != nil { return err } diff --git a/torsvc/torsvc.go b/torsvc/torsvc.go index eec0d633..02f2ed39 100644 --- a/torsvc/torsvc.go +++ b/torsvc/torsvc.go @@ -43,11 +43,11 @@ var ( } ) -// TorDial returns a go-socks proxy dialer function that can be used to make -// connections to peers through Tor's exposed socks proxy. -func TorDial(socksPort string) func(string, string) (net.Conn, error) { +// TorDial returns a connection to a remote peer via Tor's socks proxy. Only +// TCP is supported over Tor. +func TorDial(address, socksPort string) (net.Conn, error) { p := &socks.Proxy{Addr: localhost + ":" + socksPort} - return p.Dial + return p.Dial("tcp", address) } // TorLookupHost performs DNS resolution on a given hostname via Tor's