Handle tor and dns-name addresses.
Perform the requisite processing on .onion addresses to turn them into the tor reserved ipv6 region (the same as bitcoind and onioncat). Furthermore, when printing an ip address, reverse the conversion so we print it nicely. base32 as standard is uppercase, but tor and bitcoind seem to use lowercase so we first must for we force .onion addrs to uppercase (and to lowercase on the reverse). As a side effect we now should handle dns names on the command line (via tor if required) and add them to the addressmanger as necessary.
This commit is contained in:
parent
d2dd40aae2
commit
1e836d26f4
2 changed files with 61 additions and 3 deletions
|
@ -8,6 +8,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"container/list"
|
"container/list"
|
||||||
crand "crypto/rand" // for seeding
|
crand "crypto/rand" // for seeding
|
||||||
|
"encoding/base32"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -19,6 +20,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
@ -753,11 +755,61 @@ func NewAddrManager() *AddrManager {
|
||||||
return &am
|
return &am
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hostToNetAddress returns a netaddress given a host address. If the address is
|
||||||
|
// a tor .onion address this will be taken care of. else if the host is not an
|
||||||
|
// IP address it will be resolved (via tor if required).
|
||||||
|
func hostToNetAddress(host string, port uint16, services btcwire.ServiceFlag) (*btcwire.NetAddress, error) {
|
||||||
|
// tor address is 16 char base32 + ".onion"
|
||||||
|
var ip net.IP
|
||||||
|
if len(host) == 22 && host[16:] == ".onion" {
|
||||||
|
// go base32 encoding uses capitals (as does the rfc
|
||||||
|
// but tor and bitcoind tend to user lowercase, so we switch
|
||||||
|
// case here.
|
||||||
|
data, err := base32.StdEncoding.DecodeString(
|
||||||
|
strings.ToUpper(host[:16]))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
prefix := []byte{0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43}
|
||||||
|
ip = net.IP(append(prefix, data...))
|
||||||
|
} else if ip = net.ParseIP(host); ip == nil {
|
||||||
|
var err error
|
||||||
|
var ips []net.IP
|
||||||
|
if cfg.Proxy != "" {
|
||||||
|
ips, err = torLookupIP(host, cfg.Proxy)
|
||||||
|
} else {
|
||||||
|
ips, err = net.LookupIP(host)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(ips) == 0 {
|
||||||
|
return nil, fmt.Errorf("No addresses found for %s", host)
|
||||||
|
}
|
||||||
|
ip = ips[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return btcwire.NewNetAddressIPPort(ip, port, services), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipString returns a string for the ip from the provided NetAddress. If the
|
||||||
|
// ip is in the range used for tor addresses then it will be transformed into
|
||||||
|
// the relavent .onion address.
|
||||||
|
func ipString(na *btcwire.NetAddress) string {
|
||||||
|
if Tor(na) {
|
||||||
|
// We know now that na.IP is long enogh.
|
||||||
|
base32 := base32.StdEncoding.EncodeToString(na.IP[6:])
|
||||||
|
return strings.ToLower(base32) + ".onion"
|
||||||
|
} else {
|
||||||
|
return na.IP.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NetAddressKey returns a string key in the form of ip:port for IPv4 addresses
|
// NetAddressKey returns a string key in the form of ip:port for IPv4 addresses
|
||||||
// or [ip]:port for IPv6 addresses.
|
// or [ip]:port for IPv6 addresses.
|
||||||
func NetAddressKey(na *btcwire.NetAddress) string {
|
func NetAddressKey(na *btcwire.NetAddress) string {
|
||||||
port := strconv.FormatUint(uint64(na.Port), 10)
|
port := strconv.FormatUint(uint64(na.Port), 10)
|
||||||
addr := net.JoinHostPort(na.IP.String(), port)
|
addr := net.JoinHostPort(ipString(na), port)
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
peer.go
10
peer.go
|
@ -1325,7 +1325,7 @@ func newOutboundPeer(s *server, addr string, persistent bool) *peer {
|
||||||
// which case we return nil to be handled by the caller. This must be
|
// which case we return nil to be handled by the caller. This must be
|
||||||
// done before we fork off the goroutine because as soon as this
|
// done before we fork off the goroutine because as soon as this
|
||||||
// function returns the peer must have a valid netaddress.
|
// function returns the peer must have a valid netaddress.
|
||||||
ip, portStr, err := net.SplitHostPort(addr)
|
host, portStr, err := net.SplitHostPort(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.logError("Tried to create a new outbound peer with invalid "+
|
p.logError("Tried to create a new outbound peer with invalid "+
|
||||||
"address %s: %v", addr, err)
|
"address %s: %v", addr, err)
|
||||||
|
@ -1338,7 +1338,13 @@ func newOutboundPeer(s *server, addr string, persistent bool) *peer {
|
||||||
"port %s: %v", portStr, err)
|
"port %s: %v", portStr, err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
p.na = btcwire.NewNetAddressIPPort(net.ParseIP(ip), uint16(port), 0)
|
|
||||||
|
p.na, err = hostToNetAddress(host, uint16(port), 0)
|
||||||
|
if err != nil {
|
||||||
|
p.logError("Can not turn host %s into netaddress: %v",
|
||||||
|
host, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// Select which dial method to call depending on whether or
|
// Select which dial method to call depending on whether or
|
||||||
|
|
Loading…
Reference in a new issue