feature_proxy.py
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 self.add_nodes(self.num_nodes, extra_args=args) 139 self.start_nodes() 140 141 def network_test(self, node, addr, network): 142 for peer in node.getpeerinfo(): 143 if peer["addr"] == addr: 144 assert_equal(peer["network"], network) 145 146 def node_test(self, node, *, proxies, auth, test_onion, test_cjdns): 147 rv = [] 148 addr = "15.61.23.23:1234" 149 self.log.debug(f"Test: outgoing IPv4 connection through node {node.index} for address {addr}") 150 # v2transport=False is used to avoid reconnections with v1 being scheduled. These could interfere with later checks. 151 node.addnode(addr, "onetry", v2transport=False) 152 cmd = proxies[0].queue.get() 153 assert isinstance(cmd, Socks5Command) 154 # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 155 assert_equal(cmd.atyp, AddressType.DOMAINNAME) 156 assert_equal(cmd.addr, b"15.61.23.23") 157 assert_equal(cmd.port, 1234) 158 if not auth: 159 assert_equal(cmd.username, None) 160 assert_equal(cmd.password, None) 161 rv.append(cmd) 162 self.network_test(node, addr, network=NET_IPV4) 163 164 if self.have_ipv6: 165 addr = "[1233:3432:2434:2343:3234:2345:6546:4534]:5443" 166 self.log.debug(f"Test: outgoing IPv6 connection through node {node.index} for address {addr}") 167 node.addnode(addr, "onetry", v2transport=False) 168 cmd = proxies[1].queue.get() 169 assert isinstance(cmd, Socks5Command) 170 # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 171 assert_equal(cmd.atyp, AddressType.DOMAINNAME) 172 assert_equal(cmd.addr, b"1233:3432:2434:2343:3234:2345:6546:4534") 173 assert_equal(cmd.port, 5443) 174 if not auth: 175 assert_equal(cmd.username, None) 176 assert_equal(cmd.password, None) 177 rv.append(cmd) 178 self.network_test(node, addr, network=NET_IPV6) 179 180 if test_onion: 181 addr = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion:8333" 182 self.log.debug(f"Test: outgoing onion connection through node {node.index} for address {addr}") 183 node.addnode(addr, "onetry", v2transport=False) 184 cmd = proxies[2].queue.get() 185 assert isinstance(cmd, Socks5Command) 186 assert_equal(cmd.atyp, AddressType.DOMAINNAME) 187 assert_equal(cmd.addr, b"pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion") 188 assert_equal(cmd.port, 8333) 189 if not auth: 190 assert_equal(cmd.username, None) 191 assert_equal(cmd.password, None) 192 rv.append(cmd) 193 self.network_test(node, addr, network=NET_ONION) 194 195 if test_cjdns: 196 addr = "[fc00:1:2:3:4:5:6:7]:8888" 197 self.log.debug(f"Test: outgoing CJDNS connection through node {node.index} for address {addr}") 198 node.addnode(addr, "onetry", v2transport=False) 199 cmd = proxies[1].queue.get() 200 assert isinstance(cmd, Socks5Command) 201 assert_equal(cmd.atyp, AddressType.DOMAINNAME) 202 assert_equal(cmd.addr, b"fc00:1:2:3:4:5:6:7") 203 assert_equal(cmd.port, 8888) 204 if not auth: 205 assert_equal(cmd.username, None) 206 assert_equal(cmd.password, None) 207 rv.append(cmd) 208 self.network_test(node, addr, network=NET_CJDNS) 209 210 addr = "node.noumenon:8333" 211 self.log.debug(f"Test: outgoing DNS name connection through node {node.index} for address {addr}") 212 node.addnode(addr, "onetry", v2transport=False) 213 cmd = proxies[3].queue.get() 214 assert isinstance(cmd, Socks5Command) 215 assert_equal(cmd.atyp, AddressType.DOMAINNAME) 216 assert_equal(cmd.addr, b"node.noumenon") 217 assert_equal(cmd.port, 8333) 218 if not auth: 219 assert_equal(cmd.username, None) 220 assert_equal(cmd.password, None) 221 rv.append(cmd) 222 self.network_test(node, addr, network=NET_UNROUTABLE) 223 224 return rv 225 226 def run_test(self): 227 # basic -proxy 228 self.node_test(self.nodes[0], 229 proxies=[self.serv1, self.serv1, self.serv1, self.serv1], 230 auth=False, test_onion=True, test_cjdns=False) 231 232 # -proxy plus -onion 233 self.node_test(self.nodes[1], 234 proxies=[self.serv1, self.serv1, self.serv2, self.serv1], 235 auth=False, test_onion=True, test_cjdns=False) 236 237 # -proxy plus -onion, -proxyrandomize 238 rv = self.node_test(self.nodes[2], 239 proxies=[self.serv2, self.serv2, self.serv2, self.serv2], 240 auth=True, test_onion=True, test_cjdns=False) 241 # Check that credentials as used for -proxyrandomize connections are unique 242 credentials = set((x.username,x.password) for x in rv) 243 assert_equal(len(credentials), len(rv)) 244 245 if self.have_ipv6: 246 # proxy on IPv6 localhost 247 self.node_test(self.nodes[3], 248 proxies=[self.serv3, self.serv3, self.serv3, self.serv3], 249 auth=False, test_onion=False, test_cjdns=False) 250 251 # -proxy=unauth -proxyrandomize=1 -cjdnsreachable 252 self.node_test(self.nodes[4], 253 proxies=[self.serv1, self.serv1, self.serv1, self.serv1], 254 auth=False, test_onion=True, test_cjdns=True) 255 256 if self.have_unix_sockets: 257 self.node_test(self.nodes[5], 258 proxies=[self.serv4, self.serv4, self.serv4, self.serv4], 259 auth=True, test_onion=True, test_cjdns=False) 260 261 262 def networks_dict(d): 263 r = {} 264 for x in d['networks']: 265 r[x['name']] = x 266 return r 267 268 self.log.info("Test RPC getnetworkinfo") 269 nodes_network_info = [] 270 271 self.log.debug("Test that setting -proxy disables local address discovery, i.e. -discover=0") 272 for node in self.nodes: 273 network_info = node.getnetworkinfo() 274 assert_equal(network_info["localaddresses"], []) 275 nodes_network_info.append(network_info) 276 277 n0 = networks_dict(nodes_network_info[0]) 278 assert_equal(NETWORKS, n0.keys()) 279 for net in NETWORKS: 280 if net == NET_I2P: 281 expected_proxy = '' 282 expected_randomize = False 283 else: 284 expected_proxy = '%s:%i' % (self.conf1.addr) 285 expected_randomize = True 286 assert_equal(n0[net]['proxy'], expected_proxy) 287 assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize) 288 assert_equal(n0['onion']['reachable'], True) 289 assert_equal(n0['i2p']['reachable'], False) 290 assert_equal(n0['cjdns']['reachable'], False) 291 292 n1 = networks_dict(nodes_network_info[1]) 293 assert_equal(NETWORKS, n1.keys()) 294 for net in ['ipv4', 'ipv6']: 295 assert_equal(n1[net]['proxy'], f'{self.conf1.addr[0]}:{self.conf1.addr[1]}') 296 assert_equal(n1[net]['proxy_randomize_credentials'], False) 297 assert_equal(n1['onion']['proxy'], f'{self.conf2.addr[0]}:{self.conf2.addr[1]}') 298 assert_equal(n1['onion']['proxy_randomize_credentials'], False) 299 assert_equal(n1['onion']['reachable'], True) 300 assert_equal(n1['i2p']['proxy'], f'{self.i2p_sam[0]}:{self.i2p_sam[1]}') 301 assert_equal(n1['i2p']['proxy_randomize_credentials'], False) 302 assert_equal(n1['i2p']['reachable'], True) 303 304 n2 = networks_dict(nodes_network_info[2]) 305 assert_equal(NETWORKS, n2.keys()) 306 proxy = f'{self.conf2.addr[0]}:{self.conf2.addr[1]}' 307 for net in NETWORKS: 308 if net == NET_I2P: 309 expected_proxy = '' 310 expected_randomize = False 311 else: 312 expected_proxy = proxy 313 expected_randomize = True 314 assert_equal(n2[net]['proxy'], expected_proxy) 315 assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize) 316 assert_equal(n2['onion']['reachable'], True) 317 assert_equal(n2['i2p']['reachable'], False) 318 assert_equal(n2['cjdns']['reachable'], False) 319 320 if self.have_ipv6: 321 n3 = networks_dict(nodes_network_info[3]) 322 assert_equal(NETWORKS, n3.keys()) 323 proxy = f'[{self.conf3.addr[0]}]:{self.conf3.addr[1]}' 324 for net in NETWORKS: 325 expected_proxy = '' if net == NET_I2P or net == NET_ONION else proxy 326 assert_equal(n3[net]['proxy'], expected_proxy) 327 assert_equal(n3[net]['proxy_randomize_credentials'], False) 328 assert_equal(n3['onion']['reachable'], False) 329 assert_equal(n3['i2p']['reachable'], False) 330 assert_equal(n3['cjdns']['reachable'], False) 331 332 n4 = networks_dict(nodes_network_info[4]) 333 assert_equal(NETWORKS, n4.keys()) 334 for net in NETWORKS: 335 if net == NET_I2P: 336 expected_proxy = '' 337 expected_randomize = False 338 else: 339 expected_proxy = '%s:%i' % (self.conf1.addr) 340 expected_randomize = True 341 assert_equal(n4[net]['proxy'], expected_proxy) 342 assert_equal(n4[net]['proxy_randomize_credentials'], expected_randomize) 343 assert_equal(n4['onion']['reachable'], True) 344 assert_equal(n4['i2p']['reachable'], False) 345 assert_equal(n4['cjdns']['reachable'], True) 346 347 if self.have_unix_sockets: 348 n5 = networks_dict(nodes_network_info[5]) 349 assert_equal(NETWORKS, n5.keys()) 350 for net in NETWORKS: 351 if net == NET_I2P: 352 expected_proxy = '' 353 expected_randomize = False 354 else: 355 expected_proxy = 'unix:' + self.conf4.addr # no port number 356 expected_randomize = True 357 assert_equal(n5[net]['proxy'], expected_proxy) 358 assert_equal(n5[net]['proxy_randomize_credentials'], expected_randomize) 359 assert_equal(n5['onion']['reachable'], True) 360 assert_equal(n5['i2p']['reachable'], False) 361 assert_equal(n5['cjdns']['reachable'], False) 362 363 n6 = networks_dict(nodes_network_info[6]) 364 assert_equal(NETWORKS, n6.keys()) 365 for net in NETWORKS: 366 if net != NET_ONION: 367 expected_proxy = '' 368 expected_randomize = False 369 else: 370 expected_proxy = 'unix:' + self.conf4.addr # no port number 371 expected_randomize = True 372 assert_equal(n6[net]['proxy'], expected_proxy) 373 assert_equal(n6[net]['proxy_randomize_credentials'], expected_randomize) 374 assert_equal(n6['onion']['reachable'], True) 375 assert_equal(n6['i2p']['reachable'], False) 376 assert_equal(n6['cjdns']['reachable'], False) 377 378 self.stop_node(1) 379 380 self.log.info("Test passing invalid -proxy hostname raises expected init error") 381 self.nodes[1].extra_args = ["-proxy=abc..abc:23456"] 382 msg = "Error: Invalid -proxy address or hostname: 'abc..abc:23456'" 383 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 384 385 self.log.info("Test passing invalid -proxy port raises expected init error") 386 self.nodes[1].extra_args = ["-proxy=192.0.0.1:def"] 387 msg = "Error: Invalid port specified in -proxy: '192.0.0.1:def'" 388 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 389 390 self.log.info("Test passing invalid -onion hostname raises expected init error") 391 self.nodes[1].extra_args = ["-onion=xyz..xyz:23456"] 392 msg = "Error: Invalid -onion address or hostname: 'xyz..xyz:23456'" 393 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 394 395 self.log.info("Test passing invalid -onion port raises expected init error") 396 self.nodes[1].extra_args = ["-onion=192.0.0.1:def"] 397 msg = "Error: Invalid port specified in -onion: '192.0.0.1:def'" 398 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 399 400 self.log.info("Test passing invalid -i2psam hostname raises expected init error") 401 self.nodes[1].extra_args = ["-i2psam=def..def:23456"] 402 msg = "Error: Invalid -i2psam address or hostname: 'def..def:23456'" 403 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 404 405 self.log.info("Test passing invalid -i2psam port raises expected init error") 406 self.nodes[1].extra_args = ["-i2psam=192.0.0.1:def"] 407 msg = "Error: Invalid port specified in -i2psam: '192.0.0.1:def'" 408 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 409 410 self.log.info("Test passing invalid -onlynet=i2p without -i2psam raises expected init error") 411 self.nodes[1].extra_args = ["-onlynet=i2p"] 412 msg = "Error: Outbound connections restricted to i2p (-onlynet=i2p) but -i2psam is not provided" 413 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 414 415 self.log.info("Test passing invalid -onlynet=cjdns without -cjdnsreachable raises expected init error") 416 self.nodes[1].extra_args = ["-onlynet=cjdns"] 417 msg = "Error: Outbound connections restricted to CJDNS (-onlynet=cjdns) but -cjdnsreachable is not provided" 418 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 419 420 self.log.info("Test passing -onlynet=onion with -onion=0/-noonion raises expected init error") 421 msg = ( 422 "Error: Outbound connections restricted to Tor (-onlynet=onion) but " 423 "the proxy for reaching the Tor network is explicitly forbidden: -onion=0" 424 ) 425 for arg in ["-onion=0", "-noonion"]: 426 self.nodes[1].extra_args = ["-onlynet=onion", arg] 427 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 428 429 self.log.info("Test passing -onlynet=onion without -proxy, -onion or -listenonion raises expected init error") 430 self.nodes[1].extra_args = ["-onlynet=onion", "-listenonion=0"] 431 msg = ( 432 "Error: Outbound connections restricted to Tor (-onlynet=onion) but the proxy for " 433 "reaching the Tor network is not provided: none of -proxy, -onion or -listenonion is given" 434 ) 435 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 436 437 self.log.info("Test passing -onlynet=onion without -proxy or -onion but with -listenonion=1 is ok") 438 self.start_node(1, extra_args=["-onlynet=onion", "-listenonion=1"]) 439 self.stop_node(1) 440 441 self.log.info("Test passing unknown network to -onlynet raises expected init error") 442 self.nodes[1].extra_args = ["-onlynet=abc"] 443 msg = "Error: Unknown network specified in -onlynet: 'abc'" 444 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 445 446 self.log.info("Test passing trailing '=' raises expected init error") 447 self.nodes[1].extra_args = ["-proxy=127.0.0.1:9050="] 448 msg = "Error: Invalid -proxy address or hostname, ends with '=': '127.0.0.1:9050='" 449 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 450 451 self.log.info("Test passing unrecognized network raises expected init error") 452 self.nodes[1].extra_args = ["-proxy=127.0.0.1:9050=foo"] 453 msg = "Error: Unrecognized network in -proxy='127.0.0.1:9050=foo': 'foo'" 454 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 455 456 self.log.info("Test passing proxy only for IPv6") 457 self.start_node(1, extra_args=["-proxy=127.6.6.6:6666=ipv6"]) 458 nets = networks_dict(self.nodes[1].getnetworkinfo()) 459 assert_equal(nets["ipv4"]["proxy"], "") 460 assert_equal(nets["ipv6"]["proxy"], "127.6.6.6:6666") 461 self.stop_node(1) 462 463 self.log.info("Test passing separate proxy for IPv4 and IPv6") 464 self.start_node(1, extra_args=["-proxy=127.4.4.4:4444=ipv4", "-proxy=127.6.6.6:6666=ipv6"]) 465 nets = networks_dict(self.nodes[1].getnetworkinfo()) 466 assert_equal(nets["ipv4"]["proxy"], "127.4.4.4:4444") 467 assert_equal(nets["ipv6"]["proxy"], "127.6.6.6:6666") 468 self.stop_node(1) 469 470 self.log.info("Test overriding the Onion proxy") 471 self.start_node(1, extra_args=["-proxy=127.1.1.1:1111", "-proxy=127.2.2.2:2222=onion"]) 472 nets = networks_dict(self.nodes[1].getnetworkinfo()) 473 assert_equal(nets["ipv4"]["proxy"], "127.1.1.1:1111") 474 assert_equal(nets["ipv6"]["proxy"], "127.1.1.1:1111") 475 assert_equal(nets["onion"]["proxy"], "127.2.2.2:2222") 476 self.stop_node(1) 477 478 self.log.info("Test removing CJDNS proxy") 479 self.start_node(1, extra_args=["-proxy=127.1.1.1:1111", "-proxy=0=cjdns"]) 480 nets = networks_dict(self.nodes[1].getnetworkinfo()) 481 assert_equal(nets["ipv4"]["proxy"], "127.1.1.1:1111") 482 assert_equal(nets["ipv6"]["proxy"], "127.1.1.1:1111") 483 assert_equal(nets["onion"]["proxy"], "127.1.1.1:1111") 484 assert_equal(nets["cjdns"]["proxy"], "") 485 self.stop_node(1) 486 487 self.log.info("Test passing too-long unix path to -proxy raises init error") 488 self.nodes[1].extra_args = [f"-proxy=unix:{'x' * 1000}"] 489 if self.have_unix_sockets: 490 msg = f"Error: Invalid -proxy address or hostname: 'unix:{'x' * 1000}'" 491 else: 492 # If unix sockets are not supported, the file path is incorrectly interpreted as host:port 493 msg = f"Error: Invalid port specified in -proxy: 'unix:{'x' * 1000}'" 494 self.nodes[1].assert_start_raises_init_error(expected_msg=msg) 495 496 # Cleanup socket path we established outside the individual test directory. 497 if self.have_unix_sockets: 498 os.unlink(socket_path) 499 500 if __name__ == '__main__': 501 ProxyTest(__file__).main()