mirror of
https://github.com/LBRYFoundation/lbcd.git
synced 2025-08-23 17:47:24 +00:00
Enable use of a different proxy for .onion addresses.
This implements --onion (and --onionuser/--onionpass) that enable a different proxy to be used to connect to .onion addresses. If no main proxy is supplied then no proxy will be used for non-onion addresses. Additionally we add --noonion that blocks connection attempts to .onion addresses entirely (and avoids using tor for proxy dns lookups). the --tor option has been supersceded and thus removed. Closes #47
This commit is contained in:
parent
34657d43d9
commit
dd7c910e86
7 changed files with 105 additions and 87 deletions
|
@ -774,13 +774,7 @@ func hostToNetAddress(host string, port uint16, services btcwire.ServiceFlag) (*
|
||||||
prefix := []byte{0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43}
|
prefix := []byte{0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43}
|
||||||
ip = net.IP(append(prefix, data...))
|
ip = net.IP(append(prefix, data...))
|
||||||
} else if ip = net.ParseIP(host); ip == nil {
|
} else if ip = net.ParseIP(host); ip == nil {
|
||||||
var err error
|
ips, err := BtcdLookup(host)
|
||||||
var ips []net.IP
|
|
||||||
if cfg.Proxy != "" {
|
|
||||||
ips, err = torLookupIP(host, cfg.Proxy)
|
|
||||||
} else {
|
|
||||||
ips, err = net.LookupIP(host)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
75
config.go
75
config.go
|
@ -5,12 +5,14 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/conformal/btcdb"
|
"github.com/conformal/btcdb"
|
||||||
_ "github.com/conformal/btcdb/ldb"
|
_ "github.com/conformal/btcdb/ldb"
|
||||||
"github.com/conformal/btcutil"
|
"github.com/conformal/btcutil"
|
||||||
"github.com/conformal/btcwire"
|
"github.com/conformal/btcwire"
|
||||||
"github.com/conformal/go-flags"
|
"github.com/conformal/go-flags"
|
||||||
|
"github.com/conformal/go-socks"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -71,7 +73,10 @@ type config 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"`
|
||||||
UseTor bool `long:"tor" description:"Specifies the proxy server used is a Tor node"`
|
OnionProxy string `long:"onion" description:"Connect to tor hidden services via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
|
||||||
|
OnionProxyUser string `long:"onionuser" description:"Username for onion proxy server"`
|
||||||
|
OnionProxyPass string `long:"onionpass" default-mask:"-" description:"Password for onion proxy server"`
|
||||||
|
NoOnion bool `long:"noonion" description:"Disable connecting to tor hidden services"`
|
||||||
TestNet3 bool `long:"testnet" description:"Use the test network"`
|
TestNet3 bool `long:"testnet" description:"Use the test network"`
|
||||||
RegressionTest bool `long:"regtest" description:"Use the regression test network"`
|
RegressionTest bool `long:"regtest" description:"Use the regression test network"`
|
||||||
DisableCheckpoints bool `long:"nocheckpoints" description:"Disable built-in checkpoints. Don't do this unless you know what you're doing."`
|
DisableCheckpoints bool `long:"nocheckpoints" description:"Disable built-in checkpoints. Don't do this unless you know what you're doing."`
|
||||||
|
@ -80,6 +85,10 @@ type config struct {
|
||||||
CpuProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"`
|
CpuProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"`
|
||||||
DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems"`
|
DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems"`
|
||||||
Upnp bool `long:"upnp" description:"Use UPnP to map our listening port outside of NAT"`
|
Upnp bool `long:"upnp" description:"Use UPnP to map our listening port outside of NAT"`
|
||||||
|
onionlookup func(string) ([]net.IP, error)
|
||||||
|
lookup func(string) ([]net.IP, error)
|
||||||
|
oniondial func(string, string) (net.Conn, error)
|
||||||
|
dial func(string, string) (net.Conn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// serviceOptions defines the configuration options for btcd as a service on
|
// serviceOptions defines the configuration options for btcd as a service on
|
||||||
|
@ -422,15 +431,6 @@ func loadConfig() (*config, []string, error) {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// --tor requires --proxy to be set.
|
|
||||||
if cfg.UseTor && cfg.Proxy == "" {
|
|
||||||
str := "%s: the --tor option requires --proxy to be set"
|
|
||||||
err := fmt.Errorf(str, "loadConfig")
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
parser.WriteHelp(os.Stderr)
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// --proxy or --connect without --listen disables listening.
|
// --proxy or --connect without --listen disables listening.
|
||||||
if (cfg.Proxy != "" || len(cfg.ConnectPeers) > 0) &&
|
if (cfg.Proxy != "" || len(cfg.ConnectPeers) > 0) &&
|
||||||
len(cfg.Listeners) == 0 {
|
len(cfg.Listeners) == 0 {
|
||||||
|
@ -494,5 +494,60 @@ func loadConfig() (*config, []string, error) {
|
||||||
btcdLog.Warnf("%v", configFileError)
|
btcdLog.Warnf("%v", configFileError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg.dial = net.Dial
|
||||||
|
cfg.lookup = net.LookupIP
|
||||||
|
if cfg.Proxy != "" {
|
||||||
|
proxy := &socks.Proxy{
|
||||||
|
Addr: cfg.Proxy,
|
||||||
|
Username: cfg.ProxyUser,
|
||||||
|
Password: cfg.ProxyPass,
|
||||||
|
}
|
||||||
|
cfg.dial = proxy.Dial
|
||||||
|
if !cfg.NoOnion {
|
||||||
|
cfg.lookup = func(host string) ([]net.IP, error) {
|
||||||
|
return torLookupIP(host, cfg.Proxy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cfg.OnionProxy != "" {
|
||||||
|
cfg.oniondial = func(a, b string) (net.Conn, error) {
|
||||||
|
proxy := &socks.Proxy{
|
||||||
|
Addr: cfg.OnionProxy,
|
||||||
|
Username: cfg.OnionProxyUser,
|
||||||
|
Password: cfg.OnionProxyPass,
|
||||||
|
}
|
||||||
|
return proxy.Dial(a, b)
|
||||||
|
}
|
||||||
|
cfg.onionlookup = func(host string) ([]net.IP, error) {
|
||||||
|
return torLookupIP(host, cfg.OnionProxy)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cfg.oniondial = cfg.dial
|
||||||
|
cfg.onionlookup = cfg.lookup
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.NoOnion {
|
||||||
|
cfg.oniondial = func(a, b string) (net.Conn, error) {
|
||||||
|
return nil, errors.New("tor has been disabled")
|
||||||
|
}
|
||||||
|
cfg.onionlookup = func(a string) ([]net.IP, error) {
|
||||||
|
return nil, errors.New("tor has been disabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &cfg, remainingArgs, nil
|
return &cfg, remainingArgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BtcdDial(network, address string) (net.Conn, error) {
|
||||||
|
if strings.HasSuffix(address, ".onion") {
|
||||||
|
return cfg.oniondial(network, address)
|
||||||
|
}
|
||||||
|
return cfg.dial(network, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BtcdLookup(host string) ([]net.IP, error) {
|
||||||
|
if strings.HasSuffix(host, ".onion") {
|
||||||
|
return cfg.onionlookup(host)
|
||||||
|
}
|
||||||
|
return cfg.lookup(host)
|
||||||
|
}
|
||||||
|
|
38
discovery.go
38
discovery.go
|
@ -7,7 +7,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,29 +40,9 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// try individual DNS server return list of strings for responses.
|
// torLookupIP uses Tor to resolve DNS via the SOCKS extension they provide for
|
||||||
func doDNSLookup(host, proxy string) ([]net.IP, error) {
|
// resolution over the Tor network. Tor itself doesnt support ipv6 so this
|
||||||
var err error
|
// doesn't either.
|
||||||
var addrs []net.IP
|
|
||||||
|
|
||||||
if proxy != "" {
|
|
||||||
addrs, err = torLookupIP(host, proxy)
|
|
||||||
} else {
|
|
||||||
addrs, err = net.LookupIP(host)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return addrs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use Tor to resolve DNS.
|
|
||||||
/*
|
|
||||||
TODO:
|
|
||||||
* this function must be documented internally
|
|
||||||
* this function does not handle IPv6
|
|
||||||
*/
|
|
||||||
func torLookupIP(host, proxy string) ([]net.IP, error) {
|
func torLookupIP(host, proxy string) ([]net.IP, error) {
|
||||||
conn, err := net.Dial("tcp", proxy)
|
conn, err := net.Dial("tcp", proxy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -149,17 +128,12 @@ func torLookupIP(host, proxy string) ([]net.IP, error) {
|
||||||
// resolution. If any errors occur then the seeder that errored will not have
|
// resolution. If any errors occur then the seeder that errored will not have
|
||||||
// any hosts in the list. Therefore if all hosts failed an empty slice of
|
// any hosts in the list. Therefore if all hosts failed an empty slice of
|
||||||
// strings will be returned.
|
// strings will be returned.
|
||||||
func dnsDiscover(seeder string, proxy string) []net.IP {
|
func dnsDiscover(seeder string) []net.IP {
|
||||||
discLog.Debugf("Fetching list of seeds from %v", seeder)
|
discLog.Debugf("Fetching list of seeds from %v", seeder)
|
||||||
peers, err := doDNSLookup(seeder, proxy)
|
peers, err := BtcdLookup(seeder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
seederPlusProxy := seeder
|
|
||||||
if proxy != "" {
|
|
||||||
seederPlusProxy = fmt.Sprintf("%s (proxy %s)",
|
|
||||||
seeder, proxy)
|
|
||||||
}
|
|
||||||
discLog.Debugf("Unable to fetch dns seeds from %s: %v",
|
discLog.Debugf("Unable to fetch dns seeds from %s: %v",
|
||||||
seederPlusProxy, err)
|
seeder, err)
|
||||||
return []net.IP{}
|
return []net.IP{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
doc.go
27
doc.go
|
@ -20,8 +20,7 @@ this location.
|
||||||
Usage:
|
Usage:
|
||||||
btcd [OPTIONS]
|
btcd [OPTIONS]
|
||||||
|
|
||||||
The flags are:
|
Application Options:
|
||||||
-h, --help Show this help message
|
|
||||||
-V, --version Display version information and exit
|
-V, --version Display version information and exit
|
||||||
-C, --configfile= Path to configuration file
|
-C, --configfile= Path to configuration file
|
||||||
-b, --datadir= Directory to store data
|
-b, --datadir= Directory to store data
|
||||||
|
@ -33,35 +32,45 @@ The flags are:
|
||||||
interfaces via --listen
|
interfaces via --listen
|
||||||
--listen= Add an interface/port to listen for connections (default
|
--listen= Add an interface/port to listen for connections (default
|
||||||
all interfaces port: 8333, testnet: 18333)
|
all interfaces port: 8333, testnet: 18333)
|
||||||
--maxpeers= Max number of inbound and outbound peers
|
--maxpeers= Max number of inbound and outbound peers (125)
|
||||||
--banduration= How long to ban misbehaving peers. Valid time units are
|
--banduration= How long to ban misbehaving peers. Valid time units are
|
||||||
{s, m, h}. Minimum 1 second
|
{s, m, h}. Minimum 1 second (24h0m0s)
|
||||||
-u, --rpcuser= Username for RPC connections
|
-u, --rpcuser= Username for RPC connections
|
||||||
-P, --rpcpass= Password for RPC connections
|
-P, --rpcpass= Password for RPC connections
|
||||||
--rpclisten= Add an interface/port to listen for RPC connections
|
--rpclisten= Add an interface/port to listen for RPC connections
|
||||||
(default localhost port: 8334, testnet: 18334)
|
(default port: 8334, testnet: 18334)
|
||||||
--rpccert= File containing the certificate file
|
--rpccert= File containing the certificate file
|
||||||
--rpckey= File containing the certificate key
|
--rpckey= File containing the certificate key
|
||||||
--norpc Disable built-in RPC server -- NOTE: The RPC server is
|
--norpc Disable built-in RPC server -- NOTE: The RPC server is
|
||||||
disabled by default if no rpcuser/rpcpass is specified
|
disabled by default if no rpcuser/rpcpass is specified
|
||||||
--nodnsseed Disable DNS seeding for peers
|
--nodnsseed Disable DNS seeding for peers
|
||||||
|
--externalip=
|
||||||
--proxy= Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)
|
--proxy= Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)
|
||||||
--proxyuser= Username for proxy server
|
--proxyuser= Username for proxy server
|
||||||
--proxypass= Password for proxy server
|
--proxypass= Password for proxy server
|
||||||
|
--onion= Connect to tor hidden services via SOCKS5 proxy (eg.
|
||||||
|
127.0.0.1:9050)
|
||||||
|
--onionuser= Username for onion proxy server
|
||||||
|
--onionpass= Password for onion proxy server
|
||||||
|
--noonion Disable connecting to tor hidden services
|
||||||
--tor Specifies the proxy server used is a Tor node
|
--tor Specifies the proxy server used is a Tor node
|
||||||
--testnet Use the test network
|
--testnet Use the test network
|
||||||
--regtest Use the regression test network
|
--regtest Use the regression test network
|
||||||
--nocheckpoints Disable built-in checkpoints. Don't do this unless you
|
--nocheckpoints Disable built-in checkpoints. Don't do this unless you
|
||||||
know what you're doing.
|
know what you're doing.
|
||||||
--dbtype= Database backend to use for the Block Chain
|
--dbtype= Database backend to use for the Block Chain (leveldb)
|
||||||
--profile= Enable HTTP profiling on given port -- NOTE port must be
|
--profile= Enable HTTP profiling on given port -- NOTE port must be
|
||||||
between 1024 and 65536
|
between 1024 and 65536 (6060)
|
||||||
--cpuprofile= Write CPU profile to the specified file
|
--cpuprofile= Write CPU profile to the specified file
|
||||||
-d, --debuglevel: Logging level for all subsystems {trace, debug, info,
|
-d, --debuglevel= Logging level for all subsystems {trace, debug, info,
|
||||||
warn, error, critical} -- You may also specify
|
warn, error, critical} -- You may also specify
|
||||||
<subsystem>=<level>,<subsystem2>=<level>,... to set the
|
<subsystem>=<level>,<subsystem2>=<level>,... to set the
|
||||||
log level for individual subsystems -- Use show to list
|
log level for individual subsystems -- Use show to list
|
||||||
available subsystems
|
available subsystems (info)
|
||||||
|
--upnp Use UPnP to map our listening port outside of NAT
|
||||||
|
|
||||||
|
Help Options:
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
23
peer.go
23
peer.go
|
@ -1544,31 +1544,16 @@ func newOutboundPeer(s *server, addr string, persistent bool) *peer {
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// Select which dial method to call depending on whether or
|
|
||||||
// not a proxy is configured. Also, add proxy information to
|
|
||||||
// logged address if needed.
|
|
||||||
dial := net.Dial
|
|
||||||
faddr := addr
|
|
||||||
if cfg.Proxy != "" {
|
|
||||||
proxy := &socks.Proxy{
|
|
||||||
Addr: cfg.Proxy,
|
|
||||||
Username: cfg.ProxyUser,
|
|
||||||
Password: cfg.ProxyPass,
|
|
||||||
}
|
|
||||||
dial = proxy.Dial
|
|
||||||
faddr = fmt.Sprintf("%s via proxy %s", addr, cfg.Proxy)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to connect to the peer. If the connection fails and
|
// Attempt to connect to the peer. If the connection fails and
|
||||||
// this is a persistent connection, retry after the retry
|
// this is a persistent connection, retry after the retry
|
||||||
// interval.
|
// interval.
|
||||||
for atomic.LoadInt32(&p.disconnect) == 0 {
|
for atomic.LoadInt32(&p.disconnect) == 0 {
|
||||||
srvrLog.Debugf("Attempting to connect to %s", faddr)
|
srvrLog.Debugf("Attempting to connect to %s", addr)
|
||||||
conn, err := dial("tcp", addr)
|
conn, err := BtcdDial("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.retryCount += 1
|
p.retryCount += 1
|
||||||
srvrLog.Debugf("Failed to connect to %s: %v",
|
srvrLog.Debugf("Failed to connect to %s: %v",
|
||||||
faddr, err)
|
addr, err)
|
||||||
if !persistent {
|
if !persistent {
|
||||||
p.server.donePeers <- p
|
p.server.donePeers <- p
|
||||||
return
|
return
|
||||||
|
@ -1576,7 +1561,7 @@ func newOutboundPeer(s *server, addr string, persistent bool) *peer {
|
||||||
scaledInterval := connectionRetryInterval.Nanoseconds() * p.retryCount / 2
|
scaledInterval := connectionRetryInterval.Nanoseconds() * p.retryCount / 2
|
||||||
scaledDuration := time.Duration(scaledInterval)
|
scaledDuration := time.Duration(scaledInterval)
|
||||||
srvrLog.Debugf("Retrying connection to %s in "+
|
srvrLog.Debugf("Retrying connection to %s in "+
|
||||||
"%s", faddr, scaledDuration)
|
"%s", addr, scaledDuration)
|
||||||
time.Sleep(scaledDuration)
|
time.Sleep(scaledDuration)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,16 @@
|
||||||
; proxyuser=
|
; proxyuser=
|
||||||
; proxypass=
|
; proxypass=
|
||||||
|
|
||||||
; The SOCKS5 proxy above is Tor (https://www.torproject.org).
|
; The SOCKS5 proxy above is assumed to be Tor (https://www.torproject.org).
|
||||||
; Although not required if the proxy set is indeed Tor, setting this option
|
; If the proxy is not tor the the following my be used to prevent using
|
||||||
; improves anonymity by sending DNS queries over the Tor network (during DNS
|
; tor specific SOCKS queries to lookup addresses (this increases anonymity when
|
||||||
; seed lookup). This stops your IP from being leaked via DNS.
|
; tor is used by preventing your IP being leaked via DNS).
|
||||||
; tor=1
|
;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
|
||||||
|
|
||||||
; ******************************************************************************
|
; ******************************************************************************
|
||||||
; Summary of 'addpeer' versus 'connect'.
|
; Summary of 'addpeer' versus 'connect'.
|
||||||
|
|
|
@ -407,12 +407,8 @@ func (s *server) seedFromDNS() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy := ""
|
|
||||||
if cfg.Proxy != "" && cfg.UseTor {
|
|
||||||
proxy = cfg.Proxy
|
|
||||||
}
|
|
||||||
for _, seeder := range activeNetParams.dnsSeeds {
|
for _, seeder := range activeNetParams.dnsSeeds {
|
||||||
seedpeers := dnsDiscover(seeder, proxy)
|
seedpeers := dnsDiscover(seeder)
|
||||||
if len(seedpeers) == 0 {
|
if len(seedpeers) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue