[tests] don't override __init__() in individual tests
[bitcoinplatinum.git] / test / functional / proxy_test.py
blob26cb645da431eed4f0103669f1f732e8f3db2489
1 #!/usr/bin/env python3
2 # Copyright (c) 2015-2016 The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 """Test bitcoind with different proxy configuration.
7 Test plan:
8 - Start bitcoind's with different proxy configurations
9 - Use addnode to initiate connections
10 - Verify that proxies are connected to, and the right connection command is given
11 - Proxy configurations to test on bitcoind side:
12 - `-proxy` (proxy everything)
13 - `-onion` (proxy just onions)
14 - `-proxyrandomize` Circuit randomization
15 - Proxy configurations to test on proxy side,
16 - support no authentication (other proxy)
17 - support no authentication + user/pass authentication (Tor)
18 - proxy on IPv6
20 - Create various proxies (as threads)
21 - Create bitcoinds that connect to them
22 - Manipulate the bitcoinds using addnode (onetry) an observe effects
24 addnode connect to IPv4
25 addnode connect to IPv6
26 addnode connect to onion
27 addnode connect to generic DNS name
28 """
30 import socket
31 import os
33 from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType
34 from test_framework.test_framework import BitcoinTestFramework
35 from test_framework.util import (
36 PORT_MIN,
37 PORT_RANGE,
38 assert_equal,
40 from test_framework.netutil import test_ipv6_local
42 RANGE_BEGIN = PORT_MIN + 2 * PORT_RANGE # Start after p2p and rpc ports
44 class ProxyTest(BitcoinTestFramework):
45 def setup_nodes(self):
46 self.have_ipv6 = test_ipv6_local()
47 # Create two proxies on different ports
48 # ... one unauthenticated
49 self.conf1 = Socks5Configuration()
50 self.conf1.addr = ('127.0.0.1', RANGE_BEGIN + (os.getpid() % 1000))
51 self.conf1.unauth = True
52 self.conf1.auth = False
53 # ... one supporting authenticated and unauthenticated (Tor)
54 self.conf2 = Socks5Configuration()
55 self.conf2.addr = ('127.0.0.1', RANGE_BEGIN + 1000 + (os.getpid() % 1000))
56 self.conf2.unauth = True
57 self.conf2.auth = True
58 if self.have_ipv6:
59 # ... one on IPv6 with similar configuration
60 self.conf3 = Socks5Configuration()
61 self.conf3.af = socket.AF_INET6
62 self.conf3.addr = ('::1', RANGE_BEGIN + 2000 + (os.getpid() % 1000))
63 self.conf3.unauth = True
64 self.conf3.auth = True
65 else:
66 self.log.warning("Testing without local IPv6 support")
68 self.serv1 = Socks5Server(self.conf1)
69 self.serv1.start()
70 self.serv2 = Socks5Server(self.conf2)
71 self.serv2.start()
72 if self.have_ipv6:
73 self.serv3 = Socks5Server(self.conf3)
74 self.serv3.start()
76 # Note: proxies are not used to connect to local nodes
77 # this is because the proxy to use is based on CService.GetNetwork(), which return NET_UNROUTABLE for localhost
78 args = [
79 ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
80 ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
81 ['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
84 if self.have_ipv6:
85 args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
86 self.add_nodes(self.num_nodes, extra_args=args)
87 self.start_nodes()
89 def node_test(self, node, proxies, auth, test_onion=True):
90 rv = []
91 # Test: outgoing IPv4 connection through node
92 node.addnode("15.61.23.23:1234", "onetry")
93 cmd = proxies[0].queue.get()
94 assert(isinstance(cmd, Socks5Command))
95 # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
96 assert_equal(cmd.atyp, AddressType.DOMAINNAME)
97 assert_equal(cmd.addr, b"15.61.23.23")
98 assert_equal(cmd.port, 1234)
99 if not auth:
100 assert_equal(cmd.username, None)
101 assert_equal(cmd.password, None)
102 rv.append(cmd)
104 if self.have_ipv6:
105 # Test: outgoing IPv6 connection through node
106 node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry")
107 cmd = proxies[1].queue.get()
108 assert(isinstance(cmd, Socks5Command))
109 # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
110 assert_equal(cmd.atyp, AddressType.DOMAINNAME)
111 assert_equal(cmd.addr, b"1233:3432:2434:2343:3234:2345:6546:4534")
112 assert_equal(cmd.port, 5443)
113 if not auth:
114 assert_equal(cmd.username, None)
115 assert_equal(cmd.password, None)
116 rv.append(cmd)
118 if test_onion:
119 # Test: outgoing onion connection through node
120 node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
121 cmd = proxies[2].queue.get()
122 assert(isinstance(cmd, Socks5Command))
123 assert_equal(cmd.atyp, AddressType.DOMAINNAME)
124 assert_equal(cmd.addr, b"bitcoinostk4e4re.onion")
125 assert_equal(cmd.port, 8333)
126 if not auth:
127 assert_equal(cmd.username, None)
128 assert_equal(cmd.password, None)
129 rv.append(cmd)
131 # Test: outgoing DNS name connection through node
132 node.addnode("node.noumenon:8333", "onetry")
133 cmd = proxies[3].queue.get()
134 assert(isinstance(cmd, Socks5Command))
135 assert_equal(cmd.atyp, AddressType.DOMAINNAME)
136 assert_equal(cmd.addr, b"node.noumenon")
137 assert_equal(cmd.port, 8333)
138 if not auth:
139 assert_equal(cmd.username, None)
140 assert_equal(cmd.password, None)
141 rv.append(cmd)
143 return rv
145 def run_test(self):
146 # basic -proxy
147 self.node_test(self.nodes[0], [self.serv1, self.serv1, self.serv1, self.serv1], False)
149 # -proxy plus -onion
150 self.node_test(self.nodes[1], [self.serv1, self.serv1, self.serv2, self.serv1], False)
152 # -proxy plus -onion, -proxyrandomize
153 rv = self.node_test(self.nodes[2], [self.serv2, self.serv2, self.serv2, self.serv2], True)
154 # Check that credentials as used for -proxyrandomize connections are unique
155 credentials = set((x.username,x.password) for x in rv)
156 assert_equal(len(credentials), len(rv))
158 if self.have_ipv6:
159 # proxy on IPv6 localhost
160 self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False)
162 def networks_dict(d):
163 r = {}
164 for x in d['networks']:
165 r[x['name']] = x
166 return r
168 # test RPC getnetworkinfo
169 n0 = networks_dict(self.nodes[0].getnetworkinfo())
170 for net in ['ipv4','ipv6','onion']:
171 assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr))
172 assert_equal(n0[net]['proxy_randomize_credentials'], True)
173 assert_equal(n0['onion']['reachable'], True)
175 n1 = networks_dict(self.nodes[1].getnetworkinfo())
176 for net in ['ipv4','ipv6']:
177 assert_equal(n1[net]['proxy'], '%s:%i' % (self.conf1.addr))
178 assert_equal(n1[net]['proxy_randomize_credentials'], False)
179 assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr))
180 assert_equal(n1['onion']['proxy_randomize_credentials'], False)
181 assert_equal(n1['onion']['reachable'], True)
183 n2 = networks_dict(self.nodes[2].getnetworkinfo())
184 for net in ['ipv4','ipv6','onion']:
185 assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr))
186 assert_equal(n2[net]['proxy_randomize_credentials'], True)
187 assert_equal(n2['onion']['reachable'], True)
189 if self.have_ipv6:
190 n3 = networks_dict(self.nodes[3].getnetworkinfo())
191 for net in ['ipv4','ipv6']:
192 assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr))
193 assert_equal(n3[net]['proxy_randomize_credentials'], False)
194 assert_equal(n3['onion']['reachable'], False)
196 if __name__ == '__main__':
197 ProxyTest().main()