feature_proxy.py raw
1 #!/usr/bin/env python3
2 # Copyright (c) 2015-present 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.
6
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 - `-cjdnsreachable`
16 - Proxy configurations to test on proxy side,
17 - support no authentication (other proxy)
18 - support no authentication + user/pass authentication (Tor)
19 - proxy on IPv6
20 - proxy over unix domain sockets
21
22 - Create various proxies (as threads)
23 - Create nodes that connect to them
24 - Manipulate the peer connections using addnode (onetry) and observe effects
25 - Test the getpeerinfo `network` field for the peer
26
27 addnode connect to IPv4
28 addnode connect to IPv6
29 addnode connect to onion
30 addnode connect to generic DNS name
31 addnode connect to a CJDNS address
32
33 - Test getnetworkinfo for each node
34
35 - Test passing invalid -proxy
36 - Test passing invalid -onion
37 - Test passing invalid -i2psam
38 - Test passing -onlynet=onion without -proxy or -onion
39 - Test passing -onlynet=onion with -onion=0 and with -noonion
40 - Test passing unknown -onlynet
41 """
42
43 import os
44 import socket
45 import tempfile
46
47 from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType
48 from test_framework.test_framework import BitcoinTestFramework
49 from test_framework.util import assert_equal
50 from test_framework.netutil import test_ipv6_local, test_unix_socket
51
52 # Networks returned by RPC getpeerinfo.
53 NET_UNROUTABLE = "not_publicly_routable"
54 NET_IPV4 = "ipv4"
55 NET_IPV6 = "ipv6"
56 NET_ONION = "onion"
57 NET_I2P = "i2p"
58 NET_CJDNS = "cjdns"
59
60 # Networks returned by RPC getnetworkinfo, defined in src/rpc/net.cpp::GetNetworksInfo()
61 NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION, NET_I2P, NET_CJDNS})
62
63 # Use the shortest temp path possible since UNIX sockets may have as little as 92-char limit
64 socket_path = tempfile.NamedTemporaryFile().name
65
66 class ProxyTest(BitcoinTestFramework):
67 def set_test_params(self):
68 self.num_nodes = 7
69 self.setup_clean_chain = True
70
71 def setup_nodes(self):
72 self.have_ipv6 = test_ipv6_local()
73 self.have_unix_sockets = test_unix_socket()
74 # Create two proxies on different ports.
75 # Use port=0 to let the OS assign available ports, avoiding
76 # "address already in use" errors from concurrent tests.
77 # ... one unauthenticated
78 self.conf1 = Socks5Configuration()
79 self.conf1.addr = ('127.0.0.1', 0)
80 self.conf1.unauth = True
81 self.conf1.auth = False
82 # ... one supporting authenticated and unauthenticated (Tor)
83 self.conf2 = Socks5Configuration()
84 self.conf2.addr = ('127.0.0.1', 0)
85 self.conf2.unauth = True
86 self.conf2.auth = True
87 if self.have_ipv6:
88 # ... one on IPv6 with similar configuration
89 self.conf3 = Socks5Configuration()
90 self.conf3.af = socket.AF_INET6
91 self.conf3.addr = ('::1', 0)
92 self.conf3.unauth = True
93 self.conf3.auth = True
94 else:
95 self.log.warning("Testing without local IPv6 support")
96
97 if self.have_unix_sockets:
98 self.conf4 = Socks5Configuration()
99 self.conf4.af = socket.AF_UNIX
100 self.conf4.addr = socket_path
101 self.conf4.unauth = True
102 self.conf4.auth = True
103 else:
104 self.log.warning("Testing without local unix domain sockets support")
105
106 self.serv1 = Socks5Server(self.conf1)
107 self.serv1.start()
108 self.serv2 = Socks5Server(self.conf2)
109 self.serv2.start()
110 if self.have_ipv6:
111 self.serv3 = Socks5Server(self.conf3)
112 self.serv3.start()
113 if self.have_unix_sockets:
114 self.serv4 = Socks5Server(self.conf4)
115 self.serv4.start()
116
117 # We will not try to connect to this.
118 self.i2p_sam = ('127.0.0.1', 7656)
119
120 # Note: proxies are not used to connect to local nodes. This is because the proxy to
121 # use is based on CService.GetNetwork(), which returns NET_UNROUTABLE for localhost.
122 args = [
123 ['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}','-proxyrandomize=1'],
124 ['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}',f'-onion={self.conf2.addr[0]}:{self.conf2.addr[1]}',
125 f'-i2psam={self.i2p_sam[0]}:{self.i2p_sam[1]}', '-i2pacceptincoming=0', '-proxyrandomize=0'],
126 ['-listen', f'-proxy={self.conf2.addr[0]}:{self.conf2.addr[1]}','-proxyrandomize=1'],
127 [],
128 ['-listen', f'-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}','-proxyrandomize=1',
129 '-cjdnsreachable'],
130 [],
131 []
132 ]
133 if self.have_ipv6:
134 args[3] = ['-listen', f'-proxy=[{self.conf3.addr[0]}]:{self.conf3.addr[1]}','-proxyrandomize=0', '-noonion']
135 if self.have_unix_sockets:
136 args[5] = ['-listen', f'-proxy=unix:{socket_path}']
137 args[6] = ['-listen', f'-onion=unix:{socket_path}']
138 # This test launches many nodes; disable prevout prefetching so we don't spin up a
139 # thread pool for each one.
140 args = [a + ['-prevoutfetchthreads=0'] for a in args]
141 self.add_nodes(self.num_nodes, extra_args=args)
142 self.start_nodes()
143
144 def network_test(self, node, addr, network):
145 for peer in node.getpeerinfo():
146 if peer["addr"] == addr:
147 assert_equal(peer["network"], network)
148
149 def node_test(self, node, *, proxies, auth, test_onion, test_cjdns):
150 rv = []
151 addr = "15.61.23.23:1234"
152 self.log.debug(f"Test: outgoing IPv4 connection through node {node.index} for address {addr}")
153 # v2transport=False is used to avoid reconnections with v1 being scheduled. These could interfere with later checks.
154 node.addnode(addr, "onetry", v2transport=False)
155 cmd = proxies[0].queue.get()
156 assert isinstance(cmd, Socks5Command)
157 # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
158 assert_equal(cmd.atyp, AddressType.DOMAINNAME)
159 assert_equal(cmd.addr, b"15.61.23.23")
160 assert_equal(cmd.port, 1234)
161 if not auth:
162 assert_equal(cmd.username, None)
163 assert_equal(cmd.password, None)
164 rv.append(cmd)
165 self.network_test(node, addr, network=NET_IPV4)
166
167 if self.have_ipv6:
168 addr = "[1233:3432:2434:2343:3234:2345:6546:4534]:5443"
169 self.log.debug(f"Test: outgoing IPv6 connection through node {node.index} for address {addr}")
170 node.addnode(addr, "onetry", v2transport=False)
171 cmd = proxies[1].queue.get()
172 assert isinstance(cmd, Socks5Command)
173 # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
174 assert_equal(cmd.atyp, AddressType.DOMAINNAME)
175 assert_equal(cmd.addr, b"1233:3432:2434:2343:3234:2345:6546:4534")
176 assert_equal(cmd.port, 5443)
177 if not auth:
178 assert_equal(cmd.username, None)
179 assert_equal(cmd.password, None)
180 rv.append(cmd)
181 self.network_test(node, addr, network=NET_IPV6)
182
183 if test_onion:
184 addr = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:8333"
185 self.log.debug(f"Test: outgoing onion connection through node {node.index} for address {addr}")
186 node.addnode(addr, "onetry", v2transport=False)
187 cmd = proxies[2].queue.get()
188 assert isinstance(cmd, Socks5Command)
189 assert_equal(cmd.atyp, AddressType.DOMAINNAME)
190 assert_equal(cmd.addr, b"pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion")
191 assert_equal(cmd.port, 8333)
192 if not auth:
193 assert_equal(cmd.username, None)
194 assert_equal(cmd.password, None)
195 rv.append(cmd)
196 self.network_test(node, addr, network=NET_ONION)
197
198 if test_cjdns:
199 addr = "[fc00:1:2:3:4:5:6:7]:8888"
200 self.log.debug(f"Test: outgoing CJDNS connection through node {node.index} for address {addr}")
201 node.addnode(addr, "onetry", v2transport=False)
202 cmd = proxies[1].queue.get()
203 assert isinstance(cmd, Socks5Command)
204 assert_equal(cmd.atyp, AddressType.DOMAINNAME)
205 assert_equal(cmd.addr, b"fc00:1:2:3:4:5:6:7")
206 assert_equal(cmd.port, 8888)
207 if not auth:
208 assert_equal(cmd.username, None)
209 assert_equal(cmd.password, None)
210 rv.append(cmd)
211 self.network_test(node, addr, network=NET_CJDNS)
212
213 addr = "node.noumenon:8333"
214 self.log.debug(f"Test: outgoing DNS name connection through node {node.index} for address {addr}")
215 node.addnode(addr, "onetry", v2transport=False)
216 cmd = proxies[3].queue.get()
217 assert isinstance(cmd, Socks5Command)
218 assert_equal(cmd.atyp, AddressType.DOMAINNAME)
219 assert_equal(cmd.addr, b"node.noumenon")
220 assert_equal(cmd.port, 8333)
221 if not auth:
222 assert_equal(cmd.username, None)
223 assert_equal(cmd.password, None)
224 rv.append(cmd)
225 self.network_test(node, addr, network=NET_UNROUTABLE)
226
227 return rv
228
229 def run_test(self):
230 # basic -proxy
231 self.node_test(self.nodes[0],
232 proxies=[self.serv1, self.serv1, self.serv1, self.serv1],
233 auth=False, test_onion=True, test_cjdns=False)
234
235 # -proxy plus -onion
236 self.node_test(self.nodes[1],
237 proxies=[self.serv1, self.serv1, self.serv2, self.serv1],
238 auth=False, test_onion=True, test_cjdns=False)
239
240 # -proxy plus -onion, -proxyrandomize
241 rv = self.node_test(self.nodes[2],
242 proxies=[self.serv2, self.serv2, self.serv2, self.serv2],
243 auth=True, test_onion=True, test_cjdns=False)
244 # Check that credentials as used for -proxyrandomize connections are unique
245 credentials = set((x.username,x.password) for x in rv)
246 assert_equal(len(credentials), len(rv))
247
248 if self.have_ipv6:
249 # proxy on IPv6 localhost
250 self.node_test(self.nodes[3],
251 proxies=[self.serv3, self.serv3, self.serv3, self.serv3],
252 auth=False, test_onion=False, test_cjdns=False)
253
254 # -proxy=unauth -proxyrandomize=1 -cjdnsreachable
255 self.node_test(self.nodes[4],
256 proxies=[self.serv1, self.serv1, self.serv1, self.serv1],
257 auth=False, test_onion=True, test_cjdns=True)
258
259 if self.have_unix_sockets:
260 self.node_test(self.nodes[5],
261 proxies=[self.serv4, self.serv4, self.serv4, self.serv4],
262 auth=True, test_onion=True, test_cjdns=False)
263
264
265 def networks_dict(d):
266 r = {}
267 for x in d['networks']:
268 r[x['name']] = x
269 return r
270
271 self.log.info("Test RPC getnetworkinfo")
272 nodes_network_info = []
273
274 self.log.debug("Test that setting -proxy disables local address discovery, i.e. -discover=0")
275 for node in self.nodes:
276 network_info = node.getnetworkinfo()
277 assert_equal(network_info["localaddresses"], [])
278 nodes_network_info.append(network_info)
279
280 n0 = networks_dict(nodes_network_info[0])
281 assert_equal(NETWORKS, n0.keys())
282 for net in NETWORKS:
283 if net == NET_I2P:
284 expected_proxy = ''
285 expected_randomize = False
286 else:
287 expected_proxy = '%s:%i' % (self.conf1.addr)
288 expected_randomize = True
289 assert_equal(n0[net]['proxy'], expected_proxy)
290 assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize)
291 assert_equal(n0['onion']['reachable'], True)
292 assert_equal(n0['i2p']['reachable'], False)
293 assert_equal(n0['cjdns']['reachable'], False)
294
295 n1 = networks_dict(nodes_network_info[1])
296 assert_equal(NETWORKS, n1.keys())
297 for net in ['ipv4', 'ipv6']:
298 assert_equal(n1[net]['proxy'], f'{self.conf1.addr[0]}:{self.conf1.addr[1]}')
299 assert_equal(n1[net]['proxy_randomize_credentials'], False)
300 assert_equal(n1['onion']['proxy'], f'{self.conf2.addr[0]}:{self.conf2.addr[1]}')
301 assert_equal(n1['onion']['proxy_randomize_credentials'], False)
302 assert_equal(n1['onion']['reachable'], True)
303 assert_equal(n1['i2p']['proxy'], f'{self.i2p_sam[0]}:{self.i2p_sam[1]}')
304 assert_equal(n1['i2p']['proxy_randomize_credentials'], False)
305 assert_equal(n1['i2p']['reachable'], True)
306
307 n2 = networks_dict(nodes_network_info[2])
308 assert_equal(NETWORKS, n2.keys())
309 proxy = f'{self.conf2.addr[0]}:{self.conf2.addr[1]}'
310 for net in NETWORKS:
311 if net == NET_I2P:
312 expected_proxy = ''
313 expected_randomize = False
314 else:
315 expected_proxy = proxy
316 expected_randomize = True
317 assert_equal(n2[net]['proxy'], expected_proxy)
318 assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize)
319 assert_equal(n2['onion']['reachable'], True)
320 assert_equal(n2['i2p']['reachable'], False)
321 assert_equal(n2['cjdns']['reachable'], False)
322
323 if self.have_ipv6:
324 n3 = networks_dict(nodes_network_info[3])
325 assert_equal(NETWORKS, n3.keys())
326 proxy = f'[{self.conf3.addr[0]}]:{self.conf3.addr[1]}'
327 for net in NETWORKS:
328 expected_proxy = '' if net == NET_I2P or net == NET_ONION else proxy
329 assert_equal(n3[net]['proxy'], expected_proxy)
330 assert_equal(n3[net]['proxy_randomize_credentials'], False)
331 assert_equal(n3['onion']['reachable'], False)
332 assert_equal(n3['i2p']['reachable'], False)
333 assert_equal(n3['cjdns']['reachable'], False)
334
335 n4 = networks_dict(nodes_network_info[4])
336 assert_equal(NETWORKS, n4.keys())
337 for net in NETWORKS:
338 if net == NET_I2P:
339 expected_proxy = ''
340 expected_randomize = False
341 else:
342 expected_proxy = '%s:%i' % (self.conf1.addr)
343 expected_randomize = True
344 assert_equal(n4[net]['proxy'], expected_proxy)
345 assert_equal(n4[net]['proxy_randomize_credentials'], expected_randomize)
346 assert_equal(n4['onion']['reachable'], True)
347 assert_equal(n4['i2p']['reachable'], False)
348 assert_equal(n4['cjdns']['reachable'], True)
349
350 if self.have_unix_sockets:
351 n5 = networks_dict(nodes_network_info[5])
352 assert_equal(NETWORKS, n5.keys())
353 for net in NETWORKS:
354 if net == NET_I2P:
355 expected_proxy = ''
356 expected_randomize = False
357 else:
358 expected_proxy = 'unix:' + self.conf4.addr # no port number
359 expected_randomize = True
360 assert_equal(n5[net]['proxy'], expected_proxy)
361 assert_equal(n5[net]['proxy_randomize_credentials'], expected_randomize)
362 assert_equal(n5['onion']['reachable'], True)
363 assert_equal(n5['i2p']['reachable'], False)
364 assert_equal(n5['cjdns']['reachable'], False)
365
366 n6 = networks_dict(nodes_network_info[6])
367 assert_equal(NETWORKS, n6.keys())
368 for net in NETWORKS:
369 if net != NET_ONION:
370 expected_proxy = ''
371 expected_randomize = False
372 else:
373 expected_proxy = 'unix:' + self.conf4.addr # no port number
374 expected_randomize = True
375 assert_equal(n6[net]['proxy'], expected_proxy)
376 assert_equal(n6[net]['proxy_randomize_credentials'], expected_randomize)
377 assert_equal(n6['onion']['reachable'], True)
378 assert_equal(n6['i2p']['reachable'], False)
379 assert_equal(n6['cjdns']['reachable'], False)
380
381 self.stop_node(1)
382
383 self.log.info("Test passing invalid -proxy hostname raises expected init error")
384 self.nodes[1].extra_args = ["-proxy=abc..abc:23456"]
385 msg = "Error: Invalid -proxy address or hostname: 'abc..abc:23456'"
386 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
387
388 self.log.info("Test passing invalid -proxy port raises expected init error")
389 self.nodes[1].extra_args = ["-proxy=192.0.0.1:def"]
390 msg = "Error: Invalid port specified in -proxy: '192.0.0.1:def'"
391 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
392
393 self.log.info("Test passing invalid -onion hostname raises expected init error")
394 self.nodes[1].extra_args = ["-onion=xyz..xyz:23456"]
395 msg = "Error: Invalid -onion address or hostname: 'xyz..xyz:23456'"
396 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
397
398 self.log.info("Test passing invalid -onion port raises expected init error")
399 self.nodes[1].extra_args = ["-onion=192.0.0.1:def"]
400 msg = "Error: Invalid port specified in -onion: '192.0.0.1:def'"
401 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
402
403 self.log.info("Test passing invalid -i2psam hostname raises expected init error")
404 self.nodes[1].extra_args = ["-i2psam=def..def:23456"]
405 msg = "Error: Invalid -i2psam address or hostname: 'def..def:23456'"
406 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
407
408 self.log.info("Test passing invalid -i2psam port raises expected init error")
409 self.nodes[1].extra_args = ["-i2psam=192.0.0.1:def"]
410 msg = "Error: Invalid port specified in -i2psam: '192.0.0.1:def'"
411 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
412
413 self.log.info("Test passing invalid -onlynet=i2p without -i2psam raises expected init error")
414 self.nodes[1].extra_args = ["-onlynet=i2p"]
415 msg = "Error: Outbound connections restricted to i2p (-onlynet=i2p) but -i2psam is not provided"
416 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
417
418 self.log.info("Test passing invalid -onlynet=cjdns without -cjdnsreachable raises expected init error")
419 self.nodes[1].extra_args = ["-onlynet=cjdns"]
420 msg = "Error: Outbound connections restricted to CJDNS (-onlynet=cjdns) but -cjdnsreachable is not provided"
421 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
422
423 self.log.info("Test passing -onlynet=onion with -onion=0/-noonion raises expected init error")
424 msg = (
425 "Error: Outbound connections restricted to Tor (-onlynet=onion) but "
426 "the proxy for reaching the Tor network is explicitly forbidden: -onion=0"
427 )
428 for arg in ["-onion=0", "-noonion"]:
429 self.nodes[1].extra_args = ["-onlynet=onion", arg]
430 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
431
432 self.log.info("Test passing -onlynet=onion without -proxy, -onion or -listenonion raises expected init error")
433 self.nodes[1].extra_args = ["-onlynet=onion", "-listenonion=0"]
434 msg = (
435 "Error: Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
436 "reaching the Tor network is not provided: none of -proxy, -onion or -listenonion is given"
437 )
438 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
439
440 self.log.info("Test passing -onlynet=onion without -proxy or -onion but with -listenonion=1 is ok")
441 self.start_node(1, extra_args=["-onlynet=onion", "-listenonion=1"])
442 self.stop_node(1)
443
444 self.log.info("Test passing unknown network to -onlynet raises expected init error")
445 self.nodes[1].extra_args = ["-onlynet=abc"]
446 msg = "Error: Unknown network specified in -onlynet: 'abc'"
447 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
448
449 self.log.info("Test passing trailing '=' raises expected init error")
450 self.nodes[1].extra_args = ["-proxy=127.0.0.1:9050="]
451 msg = "Error: Invalid -proxy address or hostname, ends with '=': '127.0.0.1:9050='"
452 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
453
454 self.log.info("Test passing unrecognized network raises expected init error")
455 self.nodes[1].extra_args = ["-proxy=127.0.0.1:9050=foo"]
456 msg = "Error: Unrecognized network in -proxy='127.0.0.1:9050=foo': 'foo'"
457 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
458
459 self.log.info("Test passing proxy only for IPv6")
460 self.start_node(1, extra_args=["-proxy=127.6.6.6:6666=ipv6"])
461 nets = networks_dict(self.nodes[1].getnetworkinfo())
462 assert_equal(nets["ipv4"]["proxy"], "")
463 assert_equal(nets["ipv6"]["proxy"], "127.6.6.6:6666")
464 self.stop_node(1)
465
466 self.log.info("Test passing separate proxy for IPv4 and IPv6")
467 self.start_node(1, extra_args=["-proxy=127.4.4.4:4444=ipv4", "-proxy=127.6.6.6:6666=ipv6"])
468 nets = networks_dict(self.nodes[1].getnetworkinfo())
469 assert_equal(nets["ipv4"]["proxy"], "127.4.4.4:4444")
470 assert_equal(nets["ipv6"]["proxy"], "127.6.6.6:6666")
471 self.stop_node(1)
472
473 self.log.info("Test overriding the Onion proxy")
474 self.start_node(1, extra_args=["-proxy=127.1.1.1:1111", "-proxy=127.2.2.2:2222=onion"])
475 nets = networks_dict(self.nodes[1].getnetworkinfo())
476 assert_equal(nets["ipv4"]["proxy"], "127.1.1.1:1111")
477 assert_equal(nets["ipv6"]["proxy"], "127.1.1.1:1111")
478 assert_equal(nets["onion"]["proxy"], "127.2.2.2:2222")
479 self.stop_node(1)
480
481 self.log.info("Test removing CJDNS proxy")
482 self.start_node(1, extra_args=["-proxy=127.1.1.1:1111", "-proxy=0=cjdns"])
483 nets = networks_dict(self.nodes[1].getnetworkinfo())
484 assert_equal(nets["ipv4"]["proxy"], "127.1.1.1:1111")
485 assert_equal(nets["ipv6"]["proxy"], "127.1.1.1:1111")
486 assert_equal(nets["onion"]["proxy"], "127.1.1.1:1111")
487 assert_equal(nets["cjdns"]["proxy"], "")
488 self.stop_node(1)
489
490 self.log.info("Test passing too-long unix path to -proxy raises init error")
491 self.nodes[1].extra_args = [f"-proxy=unix:{'x' * 1000}"]
492 if self.have_unix_sockets:
493 msg = f"Error: Invalid -proxy address or hostname: 'unix:{'x' * 1000}'"
494 else:
495 # If unix sockets are not supported, the file path is incorrectly interpreted as host:port
496 msg = f"Error: Invalid port specified in -proxy: 'unix:{'x' * 1000}'"
497 self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
498
499 # Cleanup socket path we established outside the individual test directory.
500 if self.have_unix_sockets:
501 os.unlink(socket_path)
502
503 if __name__ == '__main__':
504 ProxyTest(__file__).main()
505