[NOD-503] Remove Tor functionality (#573)

This commit is contained in:
Ori Newman 2020-01-08 10:45:27 +02:00 committed by Svarog
parent cd719b1d5b
commit d46857677f
12 changed files with 26 additions and 395 deletions

View File

@ -7,7 +7,6 @@ package addrmgr
import ( import (
"container/list" "container/list"
crand "crypto/rand" // for seeding crand "crypto/rand" // for seeding
"encoding/base32"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -17,7 +16,6 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -894,24 +892,11 @@ func (a *AddrManager) reset() {
a.addrTrying = make(map[*KnownAddress]bool) a.addrTrying = make(map[*KnownAddress]bool)
} }
// HostToNetAddress returns a netaddress given a host address. If the address // HostToNetAddress returns a netaddress given a host address. If
// is a Tor .onion address this will be taken care of. Else if the host is // the host is not an IP address it will be resolved.
// not an IP address it will be resolved (via Tor if required).
func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.ServiceFlag) (*wire.NetAddress, error) { func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.ServiceFlag) (*wire.NetAddress, error) {
// Tor address is 16 char base32 + ".onion" ip := net.ParseIP(host)
var ip net.IP if ip == nil {
if len(host) == 22 && host[16:] == ".onion" {
// go base32 encoding uses capitals (as does the rfc
// but Tor 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 {
ips, err := a.lookupFunc(host) ips, err := a.lookupFunc(host)
if err != nil { if err != nil {
return nil, err return nil, err
@ -925,25 +910,12 @@ func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.S
return wire.NewNetAddressIPPort(ip, port, services), nil return wire.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 relevant .onion address.
func ipString(na *wire.NetAddress) string {
if IsOnionCatTor(na) {
// We know now that na.IP is long enough.
base32 := base32.StdEncoding.EncodeToString(na.IP[6:])
return strings.ToLower(base32) + ".onion"
}
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 *wire.NetAddress) string { func NetAddressKey(na *wire.NetAddress) string {
port := strconv.FormatUint(uint64(na.Port), 10) port := strconv.FormatUint(uint64(na.Port), 10)
return net.JoinHostPort(ipString(na), port) return net.JoinHostPort(na.IP.String(), port)
} }
// GetAddress returns a single address that should be routable. It picks a // GetAddress returns a single address that should be routable. It picks a
@ -1287,18 +1259,6 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
return Unreachable return Unreachable
} }
if IsOnionCatTor(remoteAddr) {
if IsOnionCatTor(localAddr) {
return Private
}
if IsRoutable(localAddr) && IsIPv4(localAddr) {
return Ipv4
}
return Default
}
if IsRFC4380(remoteAddr) { if IsRFC4380(remoteAddr) {
if !IsRoutable(localAddr) { if !IsRoutable(localAddr) {
return Default return Default
@ -1376,7 +1336,7 @@ func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddress) *wire.Net
// Send something unroutable if nothing suitable. // Send something unroutable if nothing suitable.
var ip net.IP var ip net.IP
if !IsIPv4(remoteAddr) && !IsOnionCatTor(remoteAddr) { if !IsIPv4(remoteAddr) {
ip = net.IPv6zero ip = net.IPv6zero
} else { } else {
ip = net.IPv4zero ip = net.IPv4zero

View File

@ -24,11 +24,11 @@ generally helps provide greater peer diversity, and perhaps more importantly,
drastically reduces the chances an attacker is able to coerce your peer into drastically reduces the chances an attacker is able to coerce your peer into
only connecting to nodes they control. only connecting to nodes they control.
The address manager also understands routability and Tor addresses and tries The address manager also understands routability and tries hard to only return
hard to only return routable addresses. In addition, it uses the information routable addresses. In addition, it uses the information provided by the caller
provided by the caller about connected, known good, and attempted addresses to about connected, known good, and attempted addresses to periodically purge
periodically purge peers which no longer appear to be good peers as well as peers which no longer appear to be good peers as well as bias the selection
bias the selection toward known good peers. The general idea is to make a best toward known good peers. The general idea is to make a best effort at only
effort at only providing usable addresses. providing usable addresses.
*/ */
package addrmgr package addrmgr

View File

@ -5,7 +5,6 @@
package addrmgr package addrmgr
import ( import (
"fmt"
"net" "net"
"github.com/kaspanet/kaspad/config" "github.com/kaspanet/kaspad/config"
@ -73,19 +72,6 @@ var (
// rfc6598Net specifies the IPv4 block as defined by RFC6598 (100.64.0.0/10) // rfc6598Net specifies the IPv4 block as defined by RFC6598 (100.64.0.0/10)
rfc6598Net = ipNet("100.64.0.0", 10, 32) rfc6598Net = ipNet("100.64.0.0", 10, 32)
// onionCatNet defines the IPv6 address block used to support Tor.
// We encode a .onion address as a 16 byte number by decoding the
// address prior to the .onion (i.e. the key hash) base32 into a ten
// byte number. It then stores the first 6 bytes of the address as
// 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43.
//
// This is the same range used by OnionCat, which is part part of the
// RFC4193 unique local IPv6 range.
//
// In summary the format is:
// { magic 6 bytes, 10 bytes base32 decode of key hash }
onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128)
// zero4Net defines the IPv4 address block for address staring with 0 // zero4Net defines the IPv4 address block for address staring with 0
// (0.0.0.0/8). // (0.0.0.0/8).
zero4Net = ipNet("0.0.0.0", 8, 32) zero4Net = ipNet("0.0.0.0", 8, 32)
@ -111,14 +97,6 @@ func IsLocal(na *wire.NetAddress) bool {
return na.IP.IsLoopback() || zero4Net.Contains(na.IP) return na.IP.IsLoopback() || zero4Net.Contains(na.IP)
} }
// IsOnionCatTor returns whether or not the passed address is in the IPv6 range
// used by Kaspa to support Tor (fd87:d87e:eb43::/48). Note that this range
// is the same range used by OnionCat, which is part of the RFC4193 unique local
// IPv6 range.
func IsOnionCatTor(na *wire.NetAddress) bool {
return onionCatNet.Contains(na.IP)
}
// IsRFC1918 returns whether or not the passed address is part of the IPv4 // IsRFC1918 returns whether or not the passed address is part of the IPv4
// private network address space as defined by RFC1918 (10.0.0.0/8, // private network address space as defined by RFC1918 (10.0.0.0/8,
// 172.16.0.0/12, or 192.168.0.0/16). // 172.16.0.0/12, or 192.168.0.0/16).
@ -232,13 +210,12 @@ func IsRoutable(na *wire.NetAddress) bool {
return IsValid(na) && !(IsRFC1918(na) || IsRFC2544(na) || return IsValid(na) && !(IsRFC1918(na) || IsRFC2544(na) ||
IsRFC3927(na) || IsRFC4862(na) || IsRFC3849(na) || IsRFC3927(na) || IsRFC4862(na) || IsRFC3849(na) ||
IsRFC4843(na) || IsRFC5737(na) || IsRFC6598(na) || IsRFC4843(na) || IsRFC5737(na) || IsRFC6598(na) ||
IsLocal(na) || (IsRFC4193(na) && !IsOnionCatTor(na))) IsLocal(na) || (IsRFC4193(na)))
} }
// GroupKey returns a string representing the network group an address is part // GroupKey returns a string representing the network group an address is part
// of. This is the /16 for IPv4, the /32 (/36 for he.net) for IPv6, the string // of. This is the /16 for IPv4, the /32 (/36 for he.net) for IPv6, the string
// "local" for a local address, the string "tor:key" where key is the /4 of the // "local" for a local address, and the string "unroutable" for an unroutable
// onion address for Tor address, and the string "unroutable" for an unroutable
// address. // address.
func GroupKey(na *wire.NetAddress) string { func GroupKey(na *wire.NetAddress) string {
if IsLocal(na) { if IsLocal(na) {
@ -270,10 +247,6 @@ func GroupKey(na *wire.NetAddress) string {
} }
return ip.Mask(net.CIDRMask(16, 32)).String() return ip.Mask(net.CIDRMask(16, 32)).String()
} }
if IsOnionCatTor(na) {
// group is keyed off the first 4 bits of the actual onion key.
return fmt.Sprintf("tor:%d", na.IP[6]&((1<<4)-1))
}
// OK, so now we know ourselves to be a IPv6 address. // OK, so now we know ourselves to be a IPv6 address.
// We use /32 for everything, except for Hurricane Electric's // We use /32 for everything, except for Hurricane Electric's

View File

@ -202,9 +202,9 @@ func TestGroupKey(t *testing.T) {
{name: "ipv6 rfc6145 translated ipv4", ip: "::ffff:0:0c01:0203", expected: "12.1.0.0"}, {name: "ipv6 rfc6145 translated ipv4", ip: "::ffff:0:0c01:0203", expected: "12.1.0.0"},
// Tor. // Tor.
{name: "ipv6 tor onioncat", ip: "fd87:d87e:eb43:1234::5678", expected: "tor:2"}, {name: "ipv6 tor onioncat", ip: "fd87:d87e:eb43:1234::5678", expected: "unroutable"},
{name: "ipv6 tor onioncat 2", ip: "fd87:d87e:eb43:1245::6789", expected: "tor:2"}, {name: "ipv6 tor onioncat 2", ip: "fd87:d87e:eb43:1245::6789", expected: "unroutable"},
{name: "ipv6 tor onioncat 3", ip: "fd87:d87e:eb43:1345::6789", expected: "tor:3"}, {name: "ipv6 tor onioncat 3", ip: "fd87:d87e:eb43:1345::6789", expected: "unroutable"},
// IPv6 normal. // IPv6 normal.
{name: "ipv6 normal", ip: "2602:100::1", expected: "2602:100::"}, {name: "ipv6 normal", ip: "2602:100::1", expected: "2602:100::"},

View File

@ -125,11 +125,6 @@ type Flags struct {
Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"` Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
ProxyUser string `long:"proxyuser" description:"Username for proxy server"` ProxyUser string `long:"proxyuser" description:"Username for proxy server"`
ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"` ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"`
OnionProxy string // DISABLED UNTIL DECISION ABOUT TOR `long:"onion" description:"Connect to tor hidden services via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
OnionProxyUser string // DISABLED UNTIL DECISION ABOUT TOR `long:"onionuser" description:"Username for onion proxy server"`
OnionProxyPass string // DISABLED UNTIL DECISION ABOUT TOR `long:"onionpass" default-mask:"-" description:"Password for onion proxy server"`
NoOnion bool // DISABLED UNTIL DECISION ABOUT TOR `long:"noonion" description:"Disable connecting to tor hidden services"`
TorIsolation bool // DISABLED UNTIL DECISION ABOUT TOR `long:"torisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."`
DbType string `long:"dbtype" description:"Database backend to use for the Block DAG"` DbType string `long:"dbtype" description:"Database backend to use for the Block DAG"`
Profile string `long:"profile" description:"Enable HTTP profiling on given port -- NOTE port must be between 1024 and 65536"` Profile string `long:"profile" description:"Enable HTTP profiling on given port -- NOTE port must be between 1024 and 65536"`
CPUProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"` CPUProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"`
@ -163,7 +158,6 @@ type Flags struct {
type Config struct { type Config struct {
*Flags *Flags
Lookup func(string) ([]net.IP, error) Lookup func(string) ([]net.IP, error)
OnionDial func(string, string, time.Duration) (net.Conn, error)
Dial func(string, string, time.Duration) (net.Conn, error) Dial func(string, string, time.Duration) (net.Conn, error)
MiningAddrs []util.Address MiningAddrs []util.Address
MinRelayTxFee util.Amount MinRelayTxFee util.Amount
@ -779,31 +773,11 @@ func loadConfig() (*Config, []string, error) {
activeConfig.ConnectPeers = network.NormalizeAddresses(activeConfig.ConnectPeers, activeConfig.ConnectPeers = network.NormalizeAddresses(activeConfig.ConnectPeers,
activeConfig.NetParams().DefaultPort) activeConfig.NetParams().DefaultPort)
// --noonion and --onion do not mix.
if activeConfig.NoOnion && activeConfig.OnionProxy != "" {
err := errors.Errorf("%s: the --noonion and --onion options may "+
"not be activated at the same time", funcName)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
// Tor stream isolation requires either proxy or onion proxy to be set.
if activeConfig.TorIsolation && activeConfig.Proxy == "" && activeConfig.OnionProxy == "" {
str := "%s: Tor stream isolation requires either proxy or " +
"onionproxy to be set"
err := errors.Errorf(str, funcName)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
// Setup dial and DNS resolution (lookup) functions depending on the // Setup dial and DNS resolution (lookup) functions depending on the
// specified options. The default is to use the standard // specified options. The default is to use the standard
// net.DialTimeout function as well as the system DNS resolver. When a // net.DialTimeout function as well as the system DNS resolver. When a
// proxy is specified, the dial function is set to the proxy specific // proxy is specified, the dial function is set to the proxy specific
// dial function and the lookup is set to use tor (unless --noonion is // dial function.
// specified in which case the system DNS resolver is used).
activeConfig.Dial = net.DialTimeout activeConfig.Dial = net.DialTimeout
activeConfig.Lookup = net.LookupIP activeConfig.Lookup = net.LookupIP
if activeConfig.Proxy != "" { if activeConfig.Proxy != "" {
@ -816,90 +790,12 @@ func loadConfig() (*Config, []string, error) {
return nil, nil, err return nil, nil, err
} }
// Tor isolation flag means proxy credentials will be overridden
// unless there is also an onion proxy configured in which case
// that one will be overridden.
torIsolation := false
if activeConfig.TorIsolation && activeConfig.OnionProxy == "" &&
(activeConfig.ProxyUser != "" || activeConfig.ProxyPass != "") {
torIsolation = true
fmt.Fprintln(os.Stderr, "Tor isolation set -- "+
"overriding specified proxy user credentials")
}
proxy := &socks.Proxy{ proxy := &socks.Proxy{
Addr: activeConfig.Proxy, Addr: activeConfig.Proxy,
Username: activeConfig.ProxyUser, Username: activeConfig.ProxyUser,
Password: activeConfig.ProxyPass, Password: activeConfig.ProxyPass,
TorIsolation: torIsolation,
} }
activeConfig.Dial = proxy.DialTimeout activeConfig.Dial = proxy.DialTimeout
// Treat the proxy as tor and perform DNS resolution through it
// unless the --noonion flag is set or there is an
// onion-specific proxy configured.
if !activeConfig.NoOnion && activeConfig.OnionProxy == "" {
activeConfig.Lookup = func(host string) ([]net.IP, error) {
return network.TorLookupIP(host, activeConfig.Proxy)
}
}
}
// Setup onion address dial function depending on the specified options.
// The default is to use the same dial function selected above. However,
// when an onion-specific proxy is specified, the onion address dial
// function is set to use the onion-specific proxy while leaving the
// normal dial function as selected above. This allows .onion address
// traffic to be routed through a different proxy than normal traffic.
if activeConfig.OnionProxy != "" {
_, _, err := net.SplitHostPort(activeConfig.OnionProxy)
if err != nil {
str := "%s: Onion proxy address '%s' is invalid: %s"
err := errors.Errorf(str, funcName, activeConfig.OnionProxy, err)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
// Tor isolation flag means onion proxy credentials will be
// overridden.
if activeConfig.TorIsolation &&
(activeConfig.OnionProxyUser != "" || activeConfig.OnionProxyPass != "") {
fmt.Fprintln(os.Stderr, "Tor isolation set -- "+
"overriding specified onionproxy user "+
"credentials ")
}
activeConfig.OnionDial = func(network, addr string, timeout time.Duration) (net.Conn, error) {
proxy := &socks.Proxy{
Addr: activeConfig.OnionProxy,
Username: activeConfig.OnionProxyUser,
Password: activeConfig.OnionProxyPass,
TorIsolation: activeConfig.TorIsolation,
}
return proxy.DialTimeout(network, addr, timeout)
}
// When configured in bridge mode (both --onion and --proxy are
// configured), it means that the proxy configured by --proxy is
// not a tor proxy, so override the DNS resolution to use the
// onion-specific proxy.
if activeConfig.Proxy != "" {
activeConfig.Lookup = func(host string) ([]net.IP, error) {
return network.TorLookupIP(host, activeConfig.OnionProxy)
}
}
} else {
activeConfig.OnionDial = activeConfig.Dial
}
// Specifying --noonion means the onion address dial function results in
// an error.
if activeConfig.NoOnion {
activeConfig.OnionDial = func(a, b string, t time.Duration) (net.Conn, error) {
return nil, errors.New("tor has been disabled")
}
} }
// Warn about missing config file only after all other configuration is // Warn about missing config file only after all other configuration is

View File

@ -10,7 +10,7 @@ Package connmgr implements a generic Kaspa network connection manager.
Connection Manager handles all the general connection concerns such as Connection Manager handles all the general connection concerns such as
maintaining a set number of outbound connections, sourcing peers, banning, maintaining a set number of outbound connections, sourcing peers, banning,
limiting max connections, tor lookup, etc. limiting max connections, etc.
The package provides a generic connection manager which is able to accept The package provides a generic connection manager which is able to accept
connection requests from a source or a set of given addresses, dial them and connection requests from a source or a set of given addresses, dial them and

View File

@ -5,7 +5,7 @@ Connection Manager Overview
Connection Manager handles all the general connection concerns such as Connection Manager handles all the general connection concerns such as
maintaining a set number of outbound connections, sourcing peers, banning, maintaining a set number of outbound connections, sourcing peers, banning,
limiting max connections, tor lookup, etc. limiting max connections, etc.
The package provides a generic connection manager which is able to accept The package provides a generic connection manager which is able to accept
connection requests from a source or a set of given addresses, dial them and connection requests from a source or a set of given addresses, dial them and

View File

@ -28,24 +28,6 @@
; proxyuser= ; proxyuser=
; proxypass= ; proxypass=
; The SOCKS5 proxy above is assumed to be Tor (https://www.torproject.org).
; If the proxy is not tor the following may be used to prevent using tor
; specific SOCKS queries to lookup addresses (this increases anonymity when tor
; is used by preventing your IP being leaked via DNS).
; noonion=1
; Use an alternative proxy to connect to .onion addresses. The proxy is assumed
; to be a Tor node. Non .onion addresses will be contacted with the main proxy
; or without a proxy if none is set.
; onion=127.0.0.1:9051
; onionuser=
; onionpass=
; Enable Tor stream isolation by randomizing proxy user credentials resulting in
; Tor creating a new circuit for each connection. This makes it more difficult
; to correlate connections.
; torisolation=1
; Use Universal Plug and Play (UPnP) to automatically open the listen port ; Use Universal Plug and Play (UPnP) to automatically open the listen port
; and obtain the external IP address from supported devices. NOTE: This option ; and obtain the external IP address from supported devices. NOTE: This option
; will have no effect if exernal IP addresses are specified. ; will have no effect if exernal IP addresses are specified.

View File

@ -68,28 +68,6 @@ var (
userAgentVersion = version.Version() userAgentVersion = version.Version()
) )
// 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)
// simpleAddr implements the net.Addr interface with two struct fields // simpleAddr implements the net.Addr interface with two struct fields
type simpleAddr struct { type simpleAddr struct {
net, addr string net, addr string
@ -1899,16 +1877,6 @@ func addrStringToNetAddr(addr string) (net.Addr, error) {
}, nil }, nil
} }
// Tor addresses cannot be resolved to an IP, so just return an onion
// address instead.
if strings.HasSuffix(host, ".onion") {
if config.ActiveConfig().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. // Attempt to look up an IP address associated with the parsed host.
ips, err := serverutils.KaspadLookup(host) ips, err := serverutils.KaspadLookup(host)
if err != nil { if err != nil {

View File

@ -5,7 +5,6 @@ import (
"github.com/kaspanet/kaspad/rpcmodel" "github.com/kaspanet/kaspad/rpcmodel"
"github.com/kaspanet/kaspad/server/serverutils" "github.com/kaspanet/kaspad/server/serverutils"
"net" "net"
"strings"
) )
// handleGetManualNodeInfo handles getManualNodeInfo commands. // handleGetManualNodeInfo handles getManualNodeInfo commands.
@ -77,7 +76,7 @@ func getManualNodesInfo(s *Server, detailsArg *bool, node string) (interface{},
var ipList []string var ipList []string
switch { switch {
case net.ParseIP(host) != nil, strings.HasSuffix(host, ".onion"): case net.ParseIP(host) != nil:
ipList = make([]string, 1) ipList = make([]string, 1)
ipList[0] = host ipList[0] = host
default: default:

View File

@ -1,11 +1,9 @@
package serverutils package serverutils
import ( import (
"github.com/pkg/errors"
"io/ioutil" "io/ioutil"
"net" "net"
"os" "os"
"strings"
"sync" "sync"
"time" "time"
@ -34,17 +32,8 @@ type Peer struct {
} }
// KaspadLookup resolves the IP of the given host using the correct DNS lookup // KaspadLookup resolves the IP of the given host using the correct DNS lookup
// function depending on the configuration options. For example, addresses will // function depending on the configuration options.
// be resolved using tor when the --proxy flag was specified unless --noonion
// was also specified in which case the normal system DNS resolver will be used.
//
// Any attempt to resolve a tor address (.onion) will return an error since they
// are not intended to be resolved outside of the tor proxy.
func KaspadLookup(host string) ([]net.IP, error) { func KaspadLookup(host string) ([]net.IP, error) {
if strings.HasSuffix(host, ".onion") {
return nil, errors.Errorf("attempt to resolve tor address %s", host)
}
return config.ActiveConfig().Lookup(host) return config.ActiveConfig().Lookup(host)
} }
@ -73,14 +62,7 @@ func GenCertPair(certFile, keyFile string) error {
} }
// KaspadDial connects to the address on the named network using the appropriate // KaspadDial connects to the address on the named network using the appropriate
// dial function depending on the address and configuration options. For // dial function depending on the address and configuration options.
// example, .onion addresses will be dialed using the onion specific proxy if
// one was specified, but will otherwise use the normal dial function (which
// could itself use a proxy or not).
func KaspadDial(addr net.Addr) (net.Conn, error) { func KaspadDial(addr net.Addr) (net.Conn, error) {
if strings.Contains(addr.String(), ".onion:") {
return config.ActiveConfig().OnionDial(addr.Network(), addr.String(),
config.DefaultConnectTimeout)
}
return config.ActiveConfig().Dial(addr.Network(), addr.String(), config.DefaultConnectTimeout) return config.ActiveConfig().Dial(addr.Network(), addr.String(), config.DefaultConnectTimeout)
} }

View File

@ -1,129 +0,0 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package network
import (
"encoding/binary"
"github.com/pkg/errors"
"net"
)
const (
torSucceeded = 0x00
torGeneralError = 0x01
torNotAllowed = 0x02
torNetUnreachable = 0x03
torHostUnreachable = 0x04
torConnectionRefused = 0x05
torTTLExpired = 0x06
torCmdNotSupported = 0x07
torAddrNotSupported = 0x08
)
var (
// ErrTorInvalidAddressResponse indicates an invalid address was
// returned by the Tor DNS resolver.
ErrTorInvalidAddressResponse = errors.New("invalid address response")
// ErrTorInvalidProxyResponse indicates the Tor proxy returned a
// response in an unexpected format.
ErrTorInvalidProxyResponse = errors.New("invalid proxy response")
// ErrTorUnrecognizedAuthMethod indicates the authentication method
// provided is not recognized.
ErrTorUnrecognizedAuthMethod = errors.New("invalid proxy authentication method")
torStatusErrors = map[byte]error{
torSucceeded: errors.New("tor succeeded"),
torGeneralError: errors.New("tor general error"),
torNotAllowed: errors.New("tor not allowed"),
torNetUnreachable: errors.New("tor network is unreachable"),
torHostUnreachable: errors.New("tor host is unreachable"),
torConnectionRefused: errors.New("tor connection refused"),
torTTLExpired: errors.New("tor TTL expired"),
torCmdNotSupported: errors.New("tor command not supported"),
torAddrNotSupported: errors.New("tor address type not supported"),
}
)
// TorLookupIP uses Tor to resolve DNS via the SOCKS extension they provide for
// resolution over the Tor network. Tor itself doesn't support ipv6 so this
// doesn't either.
func TorLookupIP(host, proxy string) ([]net.IP, error) {
conn, err := net.Dial("tcp", proxy)
if err != nil {
return nil, err
}
defer conn.Close()
buf := []byte{'\x05', '\x01', '\x00'}
_, err = conn.Write(buf)
if err != nil {
return nil, err
}
buf = make([]byte, 2)
_, err = conn.Read(buf)
if err != nil {
return nil, err
}
if buf[0] != '\x05' {
return nil, ErrTorInvalidProxyResponse
}
if buf[1] != '\x00' {
return nil, ErrTorUnrecognizedAuthMethod
}
buf = make([]byte, 7+len(host))
buf[0] = 5 // protocol version
buf[1] = '\xF0' // Tor Resolve
buf[2] = 0 // reserved
buf[3] = 3 // Tor Resolve
buf[4] = byte(len(host))
copy(buf[5:], host)
buf[5+len(host)] = 0 // Port 0
_, err = conn.Write(buf)
if err != nil {
return nil, err
}
buf = make([]byte, 4)
_, err = conn.Read(buf)
if err != nil {
return nil, err
}
if buf[0] != 5 {
return nil, ErrTorInvalidProxyResponse
}
if buf[1] != 0 {
if int(buf[1]) >= len(torStatusErrors) {
return nil, ErrTorInvalidProxyResponse
} else if err := torStatusErrors[buf[1]]; err != nil {
return nil, err
}
return nil, ErrTorInvalidProxyResponse
}
if buf[3] != 1 {
err := torStatusErrors[torGeneralError]
return nil, err
}
buf = make([]byte, 4)
bytes, err := conn.Read(buf)
if err != nil {
return nil, err
}
if bytes != 4 {
return nil, ErrTorInvalidAddressResponse
}
r := binary.BigEndian.Uint32(buf)
addr := make([]net.IP, 1)
addr[0] = net.IPv4(byte(r>>24), byte(r>>16), byte(r>>8), byte(r))
return addr, nil
}