Found while auditing #36628
Already known upstream issue with C-tor: https://gitlab.torproject.org/tpo/core/tor/-/issues/32314
With -proxy pointed at Tor, outbound connections to IPv6 peers whose
address contains an inner :: always fail with "general failure".
Core sends every SOCKS5 destination as a DOMAINNAME, with IPv6 in its
compressed form. Tor copies the name into its relay BEGIN cell as
<name>:<port>, and the exit's tor_addr_port_split first tries to parse
the whole string as an IPv6 address. 2001:db8::1:8333 is a valid one,
because the :: absorbs the port as an eighth group. The exit then sees no
port and closes the stream. Addresses written with all eight groups, or
ending in ::, are unaffected: appending :port to them does not give a
valid address.
About 20% of the IPv6 addresses in a gossip-filled addrman, and 29% of
current IPv6 DNS seed answers, have an inner ::. The failure is closed;
there is no fallback to a direct connection.
Note that this also effects private broadcast by default.
This PR sends such addresses with all eight groups written out
(2001:db8:0:0:0:0:0:1). <name>:<port> then has nine groups, so the exit
splits at the last colon. Other forms:
| Form | Tor | Tor, SafeSocks 1 | getaddrinfo-based proxies |
|---|---|---|---|
2001:db8::1 (today) |
fails | fails | works |
[2001:db8::1] |
works | works | fails |
| ATYP IPv6 | works, logs a DNS-leak warning | refused | works |
| eight groups (this PR) | works | works | works |
Tested against tor 0.4.9.13: on mainnet, master could not reach four
seed-provided peers with inner-:: addresses (30 "general failure"); with
this change all four connected and completed the version handshake.
feature_proxy.py and a new netbase_tests case check the bytes sent.