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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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