multi: Added a NetInterface to clean up config.go

This commit adds a new interface named NetInterface and two
implementations of it: RegularNet & TorProxyNet. These two structs
are used in config.go in an attempt to clean up the code and
abstract away the dialer and DNS functions.
This commit is contained in:
nsa 2017-10-24 22:59:32 -04:00 committed by Olaoluwa Osuntokun
parent e132ad8433
commit 8c482f2be7
6 changed files with 99 additions and 87 deletions

@ -38,11 +38,10 @@ func Dial(localPriv *btcec.PrivateKey, netAddr *lnwire.NetAddress,
var conn net.Conn var conn net.Conn
var err error var err error
if dialer == nil { 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) conn, err = net.Dial("tcp", ipAddr)
} else { } else {
// A Tor proxy dial function WAS passed in so we use it instead // A dial function WAS passed in so we use it instead.
// of golang's net.Dial.
conn, err = dialer[0]("tcp", ipAddr) conn, err = dialer[0]("tcp", ipAddr)
} }
if err != nil { if err != nil {

@ -20,7 +20,6 @@ import (
flags "github.com/jessevdk/go-flags" flags "github.com/jessevdk/go-flags"
"github.com/lightningnetwork/lnd/brontide" "github.com/lightningnetwork/lnd/brontide"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/torsvc"
"github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcutil" "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"` 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"` 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) net NetInterface
lookup func(string) ([]string, error)
lookupSRV func(string, string, string) (string, []*net.SRV, error)
resolveTCP func(string, string) (*net.TCPAddr, error)
} }
// loadConfig initializes and parses the config using a config file and command // 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 // functions. When Tor's proxy is specified, the dial function is set to
// the proxy specific dial function and the DNS resolution functions use // the proxy specific dial function and the DNS resolution functions use
// Tor. // Tor.
cfg.lookup = net.LookupHost cfg.net = &RegularNet{}
cfg.lookupSRV = net.LookupSRV
cfg.resolveTCP = net.ResolveTCPAddr
if cfg.TorSocks != "" && cfg.TorDNS != "" { if cfg.TorSocks != "" && cfg.TorDNS != "" {
// Validate Tor port number // Validate Tor port number
torport, err := strconv.Atoi(cfg.TorSocks) torport, err := strconv.Atoi(cfg.TorSocks)
@ -324,22 +318,13 @@ func loadConfig() (*config, error) {
return nil, err return nil, err
} }
cfg.dial = torsvc.TorDial(cfg.TorSocks)
// If we are using Tor, since we only want connections routed // If we are using Tor, since we only want connections routed
// through Tor, listening is disabled. // through Tor, listening is disabled.
cfg.DisableListen = true cfg.DisableListen = true
cfg.lookup = func(host string) ([]string, error) { cfg.net = &TorProxyNet{
return torsvc.TorLookupHost(host, cfg.TorSocks) TorSocks: cfg.TorSocks,
} TorDNS: cfg.TorDNS,
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)
} }
} }
@ -684,36 +669,10 @@ func supportedSubsystems() []string {
func noiseDial(idPriv *btcec.PrivateKey) func(net.Addr) (net.Conn, error) { func noiseDial(idPriv *btcec.PrivateKey) func(net.Addr) (net.Conn, error) {
return func(a net.Addr) (net.Conn, error) { return func(a net.Addr) (net.Conn, error) {
lnAddr := a.(*lnwire.NetAddress) lnAddr := a.(*lnwire.NetAddress)
if cfg.dial == nil { return brontide.Dial(idPriv, lnAddr, cfg.net.Dial)
return brontide.Dial(idPriv, lnAddr)
}
return brontide.Dial(idPriv, lnAddr, cfg.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, func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
funcName string) error { funcName string) error {
// If the configuration has already set the RPCUser and RPCPass, and // If the configuration has already set the RPCUser and RPCPass, and

76
networking.go Normal file

@ -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)
}

@ -590,7 +590,7 @@ func (r *rpcServer) ConnectPeer(ctx context.Context,
} }
// We use lndResolveTCP here in case we wish to resolve hosts over Tor. // 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 { if err != nil {
return nil, err return nil, err
} }

@ -227,7 +227,7 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
addr = ip addr = ip
} }
lnAddr, err := lndResolveTCP("tcp", addr) lnAddr, err := cfg.net.ResolveTCPAddr("tcp", addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -605,8 +605,8 @@ func initNetworkBootstrappers(s *server) ([]discovery.NetworkPeerBootstrapper, e
dnsBootStrapper, err := discovery.NewDNSSeedBootstrapper( dnsBootStrapper, err := discovery.NewDNSSeedBootstrapper(
dnsSeeds, dnsSeeds,
lndLookup, cfg.net.LookupHost,
lndLookupSRV, cfg.net.LookupSRV,
) )
if err != nil { if err != nil {
return nil, err 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 // 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 // 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 // below to sample how many of these connections succeeded.
// cfg.dial for nil in case Tor's proxy dialer option was set in the
// configuration.
for _, addr := range bootStrapAddrs { for _, addr := range bootStrapAddrs {
go func(a *lnwire.NetAddress) { go func(a *lnwire.NetAddress) {
var conn *brontide.Conn conn, err := brontide.Dial(s.identityPriv, a, cfg.net.Dial)
var err error
if cfg.dial == nil {
conn, err = brontide.Dial(s.identityPriv, a)
} else {
conn, err = brontide.Dial(s.identityPriv, a, cfg.dial)
}
if err != nil { if err != nil {
srvrLog.Errorf("unable to connect to %v: %v", srvrLog.Errorf("unable to connect to %v: %v",
a, err) a, err)
@ -767,16 +759,8 @@ func (s *server) peerBootstrapper(numTargetPeers uint32,
go func(a *lnwire.NetAddress) { go func(a *lnwire.NetAddress) {
// TODO(roasbeef): can do AS, subnet, // TODO(roasbeef): can do AS, subnet,
// country diversity, etc // country diversity, etc
// We check cfg.dial for nil in case conn, err := brontide.Dial(s.identityPriv,
// a Tor's proxy dialer configuration was a, cfg.net.Dial)
// 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)
}
if err != nil { if err != nil {
srvrLog.Errorf("unable to connect "+ srvrLog.Errorf("unable to connect "+
"to %v: %v", a, err) "to %v: %v", a, err)
@ -1294,7 +1278,7 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq,
brontideConn := conn.(*brontide.Conn) brontideConn := conn.(*brontide.Conn)
var peerAddr *lnwire.NetAddress var peerAddr *lnwire.NetAddress
if cfg.dial == nil { if _, ok := cfg.net.(*RegularNet); ok {
peerAddr = &lnwire.NetAddress{ peerAddr = &lnwire.NetAddress{
IdentityKey: brontideConn.RemotePub(), IdentityKey: brontideConn.RemotePub(),
Address: conn.RemoteAddr().(*net.TCPAddr), 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 // 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 // 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 // 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 // caller.
// was set in the configuration options. conn, err := brontide.Dial(s.identityPriv, addr, cfg.net.Dial)
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)
}
if err != nil { if err != nil {
return err return err
} }

@ -43,11 +43,11 @@ var (
} }
) )
// TorDial returns a go-socks proxy dialer function that can be used to make // TorDial returns a connection to a remote peer via Tor's socks proxy. Only
// connections to peers through Tor's exposed socks proxy. // TCP is supported over Tor.
func TorDial(socksPort string) func(string, string) (net.Conn, error) { func TorDial(address, socksPort string) (net.Conn, error) {
p := &socks.Proxy{Addr: localhost + ":" + socksPort} 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 // TorLookupHost performs DNS resolution on a given hostname via Tor's