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:
parent
91b7f5c1c8
commit
8caa921ac3
3 changed files with 63 additions and 18 deletions
|
@ -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
|
||||
}
|
||||
|
|
16
rpcserver.go
16
rpcserver.go
|
@ -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.
|
||||
|
|
59
server.go
59
server.go
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue