mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-10-14 00:59:33 +00:00
[NOD-503] Remove Tor functionality (#573)
This commit is contained in:
parent
cd719b1d5b
commit
d46857677f
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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::"},
|
||||||
|
112
config/config.go
112
config/config.go
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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 {
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user