server: Fix connections to onion nodes.

A DNS lookup was being attempted on onion addresses causing
connections to fail. This has been fixed by introducing type
onionAddr (which implements a net.Addr interface) and passing
it to btcdDial.

Also, the following onion related fixes have been made:

* getaddednodeinfo - updated to handle onion addrs.
* TorLookupIP - fixed err being shadowed.
* newServer - rename tcpAddr to netAddr
* addrStringToNetAddr - skip if host is already an IP addr.
* addrStringToNetAddr - err if tor is disabled
* getaddednodeinfo - check if host is already an IP addr.
This commit is contained in:
Javed Khan 2016-12-06 21:12:25 +05:30
parent 91b7f5c1c8
commit 8caa921ac3
3 changed files with 63 additions and 18 deletions

View file

@ -102,7 +102,7 @@ func TorLookupIP(host, proxy string) ([]net.IP, error) {
if int(buf[1]) > len(torStatusErrors) {
err = ErrTorInvalidProxyResponse
} else {
err := torStatusErrors[buf[1]]
err = torStatusErrors[buf[1]]
if err == nil {
err = ErrTorInvalidProxyResponse
}

View file

@ -919,18 +919,24 @@ func handleGetAddedNodeInfo(s *rpcServer, cmd interface{}, closeChan <-chan stru
host = peer.Addr()
}
var ipList []string
switch {
case net.ParseIP(host) != nil, strings.HasSuffix(host, ".onion"):
ipList = make([]string, 1)
ipList[0] = host
default:
// Do a DNS lookup for the address. If the lookup fails, just
// use the host.
var ipList []string
ips, err := btcdLookup(host)
if err == nil {
if err != nil {
ipList = make([]string, 1)
ipList[0] = host
break
}
ipList = make([]string, 0, len(ips))
for _, ip := range ips {
ipList = append(ipList, ip.String())
}
} else {
ipList = make([]string, 1)
ipList[0] = host
}
// Add the addresses and connection info to the result.

View file

@ -65,6 +65,28 @@ var (
userAgentVersion = fmt.Sprintf("%d.%d.%d", appMajor, appMinor, appPatch)
)
// onionAddr implements the net.Addr interface and represents a tor address.
type onionAddr struct {
addr string
}
// String returns the onion address.
//
// This is part of the net.Addr interface.
func (oa *onionAddr) String() string {
return oa.addr
}
// Network returns "onion".
//
// This is part of the net.Addr interface.
func (oa *onionAddr) Network() string {
return "onion"
}
// Ensure onionAddr implements the net.Addr interface.
var _ net.Addr = (*onionAddr)(nil)
// broadcastMsg provides the ability to house a bitcoin message to be broadcast
// to all connected peers except specified excluded peers.
type broadcastMsg struct {
@ -2469,13 +2491,13 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
permanentPeers = cfg.AddPeers
}
for _, addr := range permanentPeers {
tcpAddr, err := addrStringToNetAddr(addr)
netAddr, err := addrStringToNetAddr(addr)
if err != nil {
return nil, err
}
go s.connManager.Connect(&connmgr.ConnReq{
Addr: tcpAddr,
Addr: netAddr,
Permanent: true,
})
}
@ -2499,16 +2521,38 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
// addrStringToNetAddr takes an address in the form of 'host:port' and returns
// a net.Addr which maps to the original address with any host names resolved
// to IP addresses.
// to IP addresses. It also handles tor addresses properly by returning a
// net.Addr that encapsulates the address.
func addrStringToNetAddr(addr string) (net.Addr, error) {
host, strPort, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
port, err := strconv.Atoi(strPort)
if err != nil {
return nil, err
}
// Skip if host is already an IP address.
if ip := net.ParseIP(host); ip != nil {
return &net.TCPAddr{
IP: ip,
Port: port,
}, nil
}
// Tor addresses cannot be resolved to an IP, so just return an onion
// address instead.
if strings.HasSuffix(host, ".onion") {
if cfg.NoOnion {
return nil, errors.New("tor has been disabled")
}
return &onionAddr{addr: addr}, nil
}
// Attempt to look up an IP address associated with the parsed host.
// The btcdLookup function will transparently handle performing the
// lookup over Tor if necessary.
ips, err := btcdLookup(host)
if err != nil {
return nil, err
@ -2517,11 +2561,6 @@ func addrStringToNetAddr(addr string) (net.Addr, error) {
return nil, fmt.Errorf("no addresses found for %s", host)
}
port, err := strconv.Atoi(strPort)
if err != nil {
return nil, err
}
return &net.TCPAddr{
IP: ips[0],
Port: port,