Giel van Schijndel
13 years ago
37 changed files with 898 additions and 205 deletions
Binary file not shown.
Binary file not shown.
@ -0,0 +1,96 @@ |
|||||||
|
TOR SUPPORT IN BITCOIN |
||||||
|
====================== |
||||||
|
|
||||||
|
It is possible to run Bitcoin as a Tor hidden service, and connect to such services. |
||||||
|
|
||||||
|
The following assumes you have a Tor proxy running on port 9050. Many distributions |
||||||
|
default to having a SOCKS proxy listening on port 9050, but others may not. |
||||||
|
In particular, the Tor Browser Bundle defaults to listening on a random port. See |
||||||
|
https://www.torproject.org/docs/faq.html.en#TBBSocksPort for how to properly |
||||||
|
configure Tor. |
||||||
|
|
||||||
|
|
||||||
|
1. Run bitcoin behind a Tor proxy |
||||||
|
--------------------------------- |
||||||
|
|
||||||
|
The first step is running Bitcoin behind a Tor proxy. This will already make all |
||||||
|
outgoing connections be anonimized, but more is possible. |
||||||
|
|
||||||
|
-socks=5 SOCKS5 supports connecting-to-hostname, which can be used instead |
||||||
|
of doing a (leaking) local DNS lookup. SOCKS5 is the default, |
||||||
|
but SOCKS4 does not support this. (SOCKS4a does, but isn't |
||||||
|
implemented). |
||||||
|
|
||||||
|
-proxy=ip:port Set the proxy server. If SOCKS5 is selected (default), this proxy |
||||||
|
server will be used to try to reach .onion addresses as well. |
||||||
|
|
||||||
|
-tor=ip:port Set the proxy server to use for tor hidden services. You do not |
||||||
|
need to set this if it's the same as -proxy. You can use -notor |
||||||
|
to explicitly disable access to hidden service. |
||||||
|
|
||||||
|
-dnsseed DNS seeds are not resolved directly when a SOCKS5 proxy server is |
||||||
|
set. Rather, a short-lived proxy connection to the dns seed |
||||||
|
hostname is attempted, and peer addresses are requested. |
||||||
|
|
||||||
|
-listen When using -proxy, listening is disabled by default. If you want |
||||||
|
to run a hidden service (see next section), you'll need to enable |
||||||
|
it explicitly. |
||||||
|
|
||||||
|
-connect=X When behing a Tor proxy, you can specify .onion addresses instead |
||||||
|
-addnode=X of IP addresses or hostnames in these parameters. It requires |
||||||
|
-seednode=X SOCKS5. In Tor mode, such addresses can also be exchanged with |
||||||
|
other P2P nodes. |
||||||
|
|
||||||
|
In a typical situation, this suffices to run behind a Tor proxy: |
||||||
|
|
||||||
|
./bitcoin -proxy=127.0.0.1:9050 |
||||||
|
|
||||||
|
|
||||||
|
2. Run a bitcoin hidden server |
||||||
|
------------------------------ |
||||||
|
|
||||||
|
If you configure your Tor system accordingly, it is possible to make your node also |
||||||
|
reachable from the Tor network. Add these lines to your /etc/tor/torrc (or equivalent |
||||||
|
config file): |
||||||
|
|
||||||
|
HiddenServiceDir /var/lib/tor/bitcoin-service/ |
||||||
|
HiddenServicePort 8333 127.0.0.1:8333 |
||||||
|
|
||||||
|
The directory can be different of course, but (both) 8333's should be equal to your |
||||||
|
bitcoind's P2P listen port (8333 by default). |
||||||
|
|
||||||
|
-externalip=X You can tell bitcoin about its publically reachable address using |
||||||
|
this option, and this can be a .onion address. Given the above |
||||||
|
configuration, you can find your onion address in |
||||||
|
/var/lib/tor/bitcoin-service/hostname. Onion addresses are given |
||||||
|
preference for your node to advertize itself with, for connections |
||||||
|
coming from unroutable addresses (such as 127.0.0.1, where the |
||||||
|
Tor proxy typically runs). |
||||||
|
|
||||||
|
-listen You'll need to enable listening for incoming connections, as this |
||||||
|
is off by default behind a proxy. |
||||||
|
|
||||||
|
-discover When -externalip is specified, no attempt is made to discover local |
||||||
|
IPv4 or IPv6 addresses. If you want to run a dual stack, reachable |
||||||
|
from both Tor and IPv4 (or IPv6), you'll need to either pass your |
||||||
|
other addresses using -externalip, or explicitly enable -discover. |
||||||
|
Note that both addresses of a dual-stack system may be easily |
||||||
|
linkable using traffic analysis. |
||||||
|
|
||||||
|
In a typical situation, where you're only reachable via Tor, this should suffice: |
||||||
|
|
||||||
|
./bitcoind -proxy=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -listen |
||||||
|
|
||||||
|
(obviously replace the Onion address with your own). If you don't care too much |
||||||
|
about hiding your node, and want to be reachable on IPv4 as well, additionally |
||||||
|
specify: |
||||||
|
|
||||||
|
./bitcoind ... -discover |
||||||
|
|
||||||
|
and open port 8333 on your firewall (or use -upnp). |
||||||
|
|
||||||
|
If you only want to use Tor to reach onion addresses, but not use it as a proxy |
||||||
|
for normal IPv4/IPv6 communication, use: |
||||||
|
|
||||||
|
./bitcoin -tor=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -discover |
||||||
|
|
@ -0,0 +1,20 @@ |
|||||||
|
#include <boost/test/unit_test.hpp> |
||||||
|
|
||||||
|
#include "util.h" |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(base32_tests) |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(base32_testvectors) |
||||||
|
{ |
||||||
|
static const std::string vstrIn[] = {"","f","fo","foo","foob","fooba","foobar"}; |
||||||
|
static const std::string vstrOut[] = {"","my======","mzxq====","mzxw6===","mzxw6yq=","mzxw6ytb","mzxw6ytboi======"}; |
||||||
|
for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++) |
||||||
|
{ |
||||||
|
std::string strEnc = EncodeBase32(vstrIn[i]); |
||||||
|
BOOST_CHECK(strEnc == vstrOut[i]); |
||||||
|
std::string strDec = DecodeBase32(vstrOut[i]); |
||||||
|
BOOST_CHECK(strDec == vstrIn[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END() |
@ -0,0 +1,125 @@ |
|||||||
|
#include <boost/test/unit_test.hpp> |
||||||
|
#include <limits> |
||||||
|
|
||||||
|
#include "bignum.h" |
||||||
|
#include "util.h" |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(bignum_tests) |
||||||
|
|
||||||
|
// Unfortunately there's no standard way of preventing a function from being
|
||||||
|
// inlined, so we define a macro for it.
|
||||||
|
//
|
||||||
|
// You should use it like this:
|
||||||
|
// NOINLINE void function() {...}
|
||||||
|
#if defined(__GNUC__) |
||||||
|
// This also works and will be defined for any compiler implementing gcc
|
||||||
|
// extensions, such as clang and icc.
|
||||||
|
#define NOINLINE __attribute__((noinline)) |
||||||
|
#elif defined(_MSC_VER) |
||||||
|
#define NOINLINE __declspec(noinline) |
||||||
|
#else |
||||||
|
// We give out a warning because it impacts the correctness of one bignum test.
|
||||||
|
#warning You should define NOINLINE for your compiler. |
||||||
|
#define NOINLINE |
||||||
|
#endif |
||||||
|
|
||||||
|
// For the following test case, it is useful to use additional tools.
|
||||||
|
//
|
||||||
|
// The simplest one to use is the compiler flag -ftrapv, which detects integer
|
||||||
|
// overflows and similar errors. However, due to optimizations and compilers
|
||||||
|
// taking advantage of undefined behavior sometimes it may not actually detect
|
||||||
|
// anything.
|
||||||
|
//
|
||||||
|
// You can also use compiler-based stack protection to possibly detect possible
|
||||||
|
// stack buffer overruns.
|
||||||
|
//
|
||||||
|
// For more accurate diagnostics, you can use an undefined arithmetic operation
|
||||||
|
// detector such as the clang-based tool:
|
||||||
|
//
|
||||||
|
// "IOC: An Integer Overflow Checker for C/C++"
|
||||||
|
//
|
||||||
|
// Available at: http://embed.cs.utah.edu/ioc/
|
||||||
|
//
|
||||||
|
// It might also be useful to use Google's AddressSanitizer to detect
|
||||||
|
// stack buffer overruns, which valgrind can't currently detect.
|
||||||
|
|
||||||
|
// Let's force this code not to be inlined, in order to actually
|
||||||
|
// test a generic version of the function. This increases the chance
|
||||||
|
// that -ftrapv will detect overflows.
|
||||||
|
NOINLINE void mysetint64(CBigNum& num, int64 n) |
||||||
|
{ |
||||||
|
num.setint64(n); |
||||||
|
} |
||||||
|
|
||||||
|
// For each number, we do 2 tests: one with inline code, then we reset the
|
||||||
|
// value to 0, then the second one with a non-inlined function.
|
||||||
|
BOOST_AUTO_TEST_CASE(bignum_setint64) |
||||||
|
{ |
||||||
|
int64 n; |
||||||
|
|
||||||
|
{ |
||||||
|
n = 0; |
||||||
|
CBigNum num(n); |
||||||
|
BOOST_CHECK(num.ToString() == "0"); |
||||||
|
num.setulong(0); |
||||||
|
BOOST_CHECK(num.ToString() == "0"); |
||||||
|
mysetint64(num, n); |
||||||
|
BOOST_CHECK(num.ToString() == "0"); |
||||||
|
} |
||||||
|
{ |
||||||
|
n = 1; |
||||||
|
CBigNum num(n); |
||||||
|
BOOST_CHECK(num.ToString() == "1"); |
||||||
|
num.setulong(0); |
||||||
|
BOOST_CHECK(num.ToString() == "0"); |
||||||
|
mysetint64(num, n); |
||||||
|
BOOST_CHECK(num.ToString() == "1"); |
||||||
|
} |
||||||
|
{ |
||||||
|
n = -1; |
||||||
|
CBigNum num(n); |
||||||
|
BOOST_CHECK(num.ToString() == "-1"); |
||||||
|
num.setulong(0); |
||||||
|
BOOST_CHECK(num.ToString() == "0"); |
||||||
|
mysetint64(num, n); |
||||||
|
BOOST_CHECK(num.ToString() == "-1"); |
||||||
|
} |
||||||
|
{ |
||||||
|
n = 5; |
||||||
|
CBigNum num(n); |
||||||
|
BOOST_CHECK(num.ToString() == "5"); |
||||||
|
num.setulong(0); |
||||||
|
BOOST_CHECK(num.ToString() == "0"); |
||||||
|
mysetint64(num, n); |
||||||
|
BOOST_CHECK(num.ToString() == "5"); |
||||||
|
} |
||||||
|
{ |
||||||
|
n = -5; |
||||||
|
CBigNum num(n); |
||||||
|
BOOST_CHECK(num.ToString() == "-5"); |
||||||
|
num.setulong(0); |
||||||
|
BOOST_CHECK(num.ToString() == "0"); |
||||||
|
mysetint64(num, n); |
||||||
|
BOOST_CHECK(num.ToString() == "-5"); |
||||||
|
} |
||||||
|
{ |
||||||
|
n = std::numeric_limits<int64>::min(); |
||||||
|
CBigNum num(n); |
||||||
|
BOOST_CHECK(num.ToString() == "-9223372036854775808"); |
||||||
|
num.setulong(0); |
||||||
|
BOOST_CHECK(num.ToString() == "0"); |
||||||
|
mysetint64(num, n); |
||||||
|
BOOST_CHECK(num.ToString() == "-9223372036854775808"); |
||||||
|
} |
||||||
|
{ |
||||||
|
n = std::numeric_limits<int64>::max(); |
||||||
|
CBigNum num(n); |
||||||
|
BOOST_CHECK(num.ToString() == "9223372036854775807"); |
||||||
|
num.setulong(0); |
||||||
|
BOOST_CHECK(num.ToString() == "0"); |
||||||
|
mysetint64(num, n); |
||||||
|
BOOST_CHECK(num.ToString() == "9223372036854775807"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END() |
@ -0,0 +1,102 @@ |
|||||||
|
#include <boost/test/unit_test.hpp> |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include "netbase.h" |
||||||
|
|
||||||
|
using namespace std; |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(netbase_tests) |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(netbase_networks) |
||||||
|
{ |
||||||
|
BOOST_CHECK(CNetAddr("127.0.0.1").GetNetwork() == NET_UNROUTABLE); |
||||||
|
BOOST_CHECK(CNetAddr("::1").GetNetwork() == NET_UNROUTABLE); |
||||||
|
BOOST_CHECK(CNetAddr("8.8.8.8").GetNetwork() == NET_IPV4); |
||||||
|
BOOST_CHECK(CNetAddr("2001::8888").GetNetwork() == NET_IPV6); |
||||||
|
BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR); |
||||||
|
} |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(netbase_properties) |
||||||
|
{ |
||||||
|
BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4()); |
||||||
|
BOOST_CHECK(CNetAddr("::FFFF:192.168.1.1").IsIPv4()); |
||||||
|
BOOST_CHECK(CNetAddr("::1").IsIPv6()); |
||||||
|
BOOST_CHECK(CNetAddr("10.0.0.1").IsRFC1918()); |
||||||
|
BOOST_CHECK(CNetAddr("192.168.1.1").IsRFC1918()); |
||||||
|
BOOST_CHECK(CNetAddr("172.31.255.255").IsRFC1918()); |
||||||
|
BOOST_CHECK(CNetAddr("2001:0DB8::").IsRFC3849()); |
||||||
|
BOOST_CHECK(CNetAddr("169.254.1.1").IsRFC3927()); |
||||||
|
BOOST_CHECK(CNetAddr("2002::1").IsRFC3964()); |
||||||
|
BOOST_CHECK(CNetAddr("FC00::").IsRFC4193()); |
||||||
|
BOOST_CHECK(CNetAddr("2001::2").IsRFC4380()); |
||||||
|
BOOST_CHECK(CNetAddr("2001:10::").IsRFC4843()); |
||||||
|
BOOST_CHECK(CNetAddr("FE80::").IsRFC4862()); |
||||||
|
BOOST_CHECK(CNetAddr("64:FF9B::").IsRFC6052()); |
||||||
|
BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor()); |
||||||
|
BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal()); |
||||||
|
BOOST_CHECK(CNetAddr("::1").IsLocal()); |
||||||
|
BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable()); |
||||||
|
BOOST_CHECK(CNetAddr("2001::1").IsRoutable()); |
||||||
|
BOOST_CHECK(CNetAddr("127.0.0.1").IsValid()); |
||||||
|
} |
||||||
|
|
||||||
|
bool static TestSplitHost(string test, string host, int port) |
||||||
|
{ |
||||||
|
string hostOut; |
||||||
|
int portOut = -1; |
||||||
|
SplitHostPort(test, portOut, hostOut); |
||||||
|
return hostOut == host && port == portOut; |
||||||
|
} |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(netbase_splithost) |
||||||
|
{ |
||||||
|
BOOST_CHECK(TestSplitHost("www.bitcoin.org", "www.bitcoin.org", -1)); |
||||||
|
BOOST_CHECK(TestSplitHost("[www.bitcoin.org]", "www.bitcoin.org", -1)); |
||||||
|
BOOST_CHECK(TestSplitHost("www.bitcoin.org:80", "www.bitcoin.org", 80)); |
||||||
|
BOOST_CHECK(TestSplitHost("[www.bitcoin.org]:80", "www.bitcoin.org", 80)); |
||||||
|
BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1)); |
||||||
|
BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333)); |
||||||
|
BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1)); |
||||||
|
BOOST_CHECK(TestSplitHost("[127.0.0.1]:8333", "127.0.0.1", 8333)); |
||||||
|
BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1)); |
||||||
|
BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:8333", "::ffff:127.0.0.1", 8333)); |
||||||
|
BOOST_CHECK(TestSplitHost("[::]:8333", "::", 8333)); |
||||||
|
BOOST_CHECK(TestSplitHost("::8333", "::8333", -1)); |
||||||
|
BOOST_CHECK(TestSplitHost(":8333", "", 8333)); |
||||||
|
BOOST_CHECK(TestSplitHost("[]:8333", "", 8333)); |
||||||
|
BOOST_CHECK(TestSplitHost("", "", -1)); |
||||||
|
} |
||||||
|
|
||||||
|
bool static TestParse(string src, string canon) |
||||||
|
{ |
||||||
|
CService addr; |
||||||
|
if (!LookupNumeric(src.c_str(), addr, 65535)) |
||||||
|
return canon == ""; |
||||||
|
return canon == addr.ToString(); |
||||||
|
} |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(netbase_lookupnumeric) |
||||||
|
{ |
||||||
|
BOOST_CHECK(TestParse("127.0.0.1", "127.0.0.1:65535")); |
||||||
|
BOOST_CHECK(TestParse("127.0.0.1:8333", "127.0.0.1:8333")); |
||||||
|
BOOST_CHECK(TestParse("::ffff:127.0.0.1", "127.0.0.1:65535")); |
||||||
|
BOOST_CHECK(TestParse("::", "[::]:65535")); |
||||||
|
BOOST_CHECK(TestParse("[::]:8333", "[::]:8333")); |
||||||
|
BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535")); |
||||||
|
BOOST_CHECK(TestParse(":::", "")); |
||||||
|
} |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(onioncat_test) |
||||||
|
{ |
||||||
|
// values from http://www.cypherpunk.at/onioncat/wiki/OnionCat
|
||||||
|
CNetAddr addr1("5wyqrzbvrdsumnok.onion"); |
||||||
|
CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca"); |
||||||
|
BOOST_CHECK(addr1 == addr2); |
||||||
|
BOOST_CHECK(addr1.IsTor()); |
||||||
|
BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion"); |
||||||
|
BOOST_CHECK(addr1.IsRoutable()); |
||||||
|
} |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END() |
Loading…
Reference in new issue