/root/bitcoin/src/netbase.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | | // Copyright (c) 2009-2022 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 | | |
6 | | #include <bitcoin-build-config.h> // IWYU pragma: keep |
7 | | |
8 | | #include <netbase.h> |
9 | | |
10 | | #include <compat/compat.h> |
11 | | #include <logging.h> |
12 | | #include <sync.h> |
13 | | #include <tinyformat.h> |
14 | | #include <util/sock.h> |
15 | | #include <util/strencodings.h> |
16 | | #include <util/string.h> |
17 | | #include <util/time.h> |
18 | | |
19 | | #include <atomic> |
20 | | #include <chrono> |
21 | | #include <cstdint> |
22 | | #include <functional> |
23 | | #include <limits> |
24 | | #include <memory> |
25 | | |
26 | | #ifdef HAVE_SOCKADDR_UN |
27 | | #include <sys/un.h> |
28 | | #endif |
29 | | |
30 | | using util::ContainsNoNUL; |
31 | | |
32 | | // Settings |
33 | | static GlobalMutex g_proxyinfo_mutex; |
34 | | static Proxy proxyInfo[NET_MAX] GUARDED_BY(g_proxyinfo_mutex); |
35 | | static Proxy nameProxy GUARDED_BY(g_proxyinfo_mutex); |
36 | | int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; |
37 | | bool fNameLookup = DEFAULT_NAME_LOOKUP; |
38 | | |
39 | | // Need ample time for negotiation for very slow proxies such as Tor |
40 | | std::chrono::milliseconds g_socks5_recv_timeout = 20s; |
41 | | CThreadInterrupt g_socks5_interrupt; |
42 | | |
43 | | ReachableNets g_reachable_nets; |
44 | | |
45 | | std::vector<CNetAddr> WrappedGetAddrInfo(const std::string& name, bool allow_lookup) |
46 | 0 | { |
47 | 0 | addrinfo ai_hint{}; |
48 | | // We want a TCP port, which is a streaming socket type |
49 | 0 | ai_hint.ai_socktype = SOCK_STREAM; |
50 | 0 | ai_hint.ai_protocol = IPPROTO_TCP; |
51 | | // We don't care which address family (IPv4 or IPv6) is returned |
52 | 0 | ai_hint.ai_family = AF_UNSPEC; |
53 | | |
54 | | // If we allow lookups of hostnames, use the AI_ADDRCONFIG flag to only |
55 | | // return addresses whose family we have an address configured for. |
56 | | // |
57 | | // If we don't allow lookups, then use the AI_NUMERICHOST flag for |
58 | | // getaddrinfo to only decode numerical network addresses and suppress |
59 | | // hostname lookups. |
60 | 0 | ai_hint.ai_flags = allow_lookup ? AI_ADDRCONFIG : AI_NUMERICHOST; |
61 | |
|
62 | 0 | addrinfo* ai_res{nullptr}; |
63 | 0 | const int n_err{getaddrinfo(name.c_str(), nullptr, &ai_hint, &ai_res)}; |
64 | 0 | if (n_err != 0) { |
65 | 0 | if ((ai_hint.ai_flags & AI_ADDRCONFIG) == AI_ADDRCONFIG) { |
66 | | // AI_ADDRCONFIG on some systems may exclude loopback-only addresses |
67 | | // If first lookup failed we perform a second lookup without AI_ADDRCONFIG |
68 | 0 | ai_hint.ai_flags = (ai_hint.ai_flags & ~AI_ADDRCONFIG); |
69 | 0 | const int n_err_retry{getaddrinfo(name.c_str(), nullptr, &ai_hint, &ai_res)}; |
70 | 0 | if (n_err_retry != 0) { |
71 | 0 | return {}; |
72 | 0 | } |
73 | 0 | } else { |
74 | 0 | return {}; |
75 | 0 | } |
76 | 0 | } |
77 | | |
78 | | // Traverse the linked list starting with ai_trav. |
79 | 0 | addrinfo* ai_trav{ai_res}; |
80 | 0 | std::vector<CNetAddr> resolved_addresses; |
81 | 0 | while (ai_trav != nullptr) { |
82 | 0 | if (ai_trav->ai_family == AF_INET) { |
83 | 0 | assert(ai_trav->ai_addrlen >= sizeof(sockaddr_in)); |
84 | 0 | resolved_addresses.emplace_back(reinterpret_cast<sockaddr_in*>(ai_trav->ai_addr)->sin_addr); |
85 | 0 | } |
86 | 0 | if (ai_trav->ai_family == AF_INET6) { |
87 | 0 | assert(ai_trav->ai_addrlen >= sizeof(sockaddr_in6)); |
88 | 0 | const sockaddr_in6* s6{reinterpret_cast<sockaddr_in6*>(ai_trav->ai_addr)}; |
89 | 0 | resolved_addresses.emplace_back(s6->sin6_addr, s6->sin6_scope_id); |
90 | 0 | } |
91 | 0 | ai_trav = ai_trav->ai_next; |
92 | 0 | } |
93 | 0 | freeaddrinfo(ai_res); |
94 | |
|
95 | 0 | return resolved_addresses; |
96 | 0 | } |
97 | | |
98 | | DNSLookupFn g_dns_lookup{WrappedGetAddrInfo}; |
99 | | |
100 | 0 | enum Network ParseNetwork(const std::string& net_in) { |
101 | 0 | std::string net = ToLower(net_in); |
102 | 0 | if (net == "ipv4") return NET_IPV4; |
103 | 0 | if (net == "ipv6") return NET_IPV6; |
104 | 0 | if (net == "onion") return NET_ONION; |
105 | 0 | if (net == "tor") { |
106 | 0 | LogPrintf("Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n"); |
107 | 0 | return NET_ONION; |
108 | 0 | } |
109 | 0 | if (net == "i2p") { |
110 | 0 | return NET_I2P; |
111 | 0 | } |
112 | 0 | if (net == "cjdns") { |
113 | 0 | return NET_CJDNS; |
114 | 0 | } |
115 | 0 | return NET_UNROUTABLE; |
116 | 0 | } |
117 | | |
118 | | std::string GetNetworkName(enum Network net) |
119 | 0 | { |
120 | 0 | switch (net) { |
121 | 0 | case NET_UNROUTABLE: return "not_publicly_routable"; |
122 | 0 | case NET_IPV4: return "ipv4"; |
123 | 0 | case NET_IPV6: return "ipv6"; |
124 | 0 | case NET_ONION: return "onion"; |
125 | 0 | case NET_I2P: return "i2p"; |
126 | 0 | case NET_CJDNS: return "cjdns"; |
127 | 0 | case NET_INTERNAL: return "internal"; |
128 | 0 | case NET_MAX: assert(false); |
129 | 0 | } // no default case, so the compiler can warn about missing cases |
130 | | |
131 | 0 | assert(false); |
132 | 0 | } |
133 | | |
134 | | std::vector<std::string> GetNetworkNames(bool append_unroutable) |
135 | 0 | { |
136 | 0 | std::vector<std::string> names; |
137 | 0 | for (int n = 0; n < NET_MAX; ++n) { |
138 | 0 | const enum Network network{static_cast<Network>(n)}; |
139 | 0 | if (network == NET_UNROUTABLE || network == NET_INTERNAL) continue; |
140 | 0 | names.emplace_back(GetNetworkName(network)); |
141 | 0 | } |
142 | 0 | if (append_unroutable) { |
143 | 0 | names.emplace_back(GetNetworkName(NET_UNROUTABLE)); |
144 | 0 | } |
145 | 0 | return names; |
146 | 0 | } |
147 | | |
148 | | static std::vector<CNetAddr> LookupIntern(const std::string& name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function) |
149 | 0 | { |
150 | 0 | if (!ContainsNoNUL(name)) return {}; |
151 | 0 | { |
152 | 0 | CNetAddr addr; |
153 | | // From our perspective, onion addresses are not hostnames but rather |
154 | | // direct encodings of CNetAddr much like IPv4 dotted-decimal notation |
155 | | // or IPv6 colon-separated hextet notation. Since we can't use |
156 | | // getaddrinfo to decode them and it wouldn't make sense to resolve |
157 | | // them, we return a network address representing it instead. See |
158 | | // CNetAddr::SetSpecial(const std::string&) for more details. |
159 | 0 | if (addr.SetSpecial(name)) return {addr}; |
160 | 0 | } |
161 | | |
162 | 0 | std::vector<CNetAddr> addresses; |
163 | |
|
164 | 0 | for (const CNetAddr& resolved : dns_lookup_function(name, fAllowLookup)) { |
165 | 0 | if (nMaxSolutions > 0 && addresses.size() >= nMaxSolutions) { |
166 | 0 | break; |
167 | 0 | } |
168 | | /* Never allow resolving to an internal address. Consider any such result invalid */ |
169 | 0 | if (!resolved.IsInternal()) { |
170 | 0 | addresses.push_back(resolved); |
171 | 0 | } |
172 | 0 | } |
173 | |
|
174 | 0 | return addresses; |
175 | 0 | } |
176 | | |
177 | | std::vector<CNetAddr> LookupHost(const std::string& name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function) |
178 | 0 | { |
179 | 0 | if (!ContainsNoNUL(name)) return {}; |
180 | 0 | std::string strHost = name; |
181 | 0 | if (strHost.empty()) return {}; |
182 | 0 | if (strHost.front() == '[' && strHost.back() == ']') { |
183 | 0 | strHost = strHost.substr(1, strHost.size() - 2); |
184 | 0 | } |
185 | |
|
186 | 0 | return LookupIntern(strHost, nMaxSolutions, fAllowLookup, dns_lookup_function); |
187 | 0 | } |
188 | | |
189 | | std::optional<CNetAddr> LookupHost(const std::string& name, bool fAllowLookup, DNSLookupFn dns_lookup_function) |
190 | 0 | { |
191 | 0 | const std::vector<CNetAddr> addresses{LookupHost(name, 1, fAllowLookup, dns_lookup_function)}; |
192 | 0 | return addresses.empty() ? std::nullopt : std::make_optional(addresses.front()); |
193 | 0 | } |
194 | | |
195 | | std::vector<CService> Lookup(const std::string& name, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function) |
196 | 0 | { |
197 | 0 | if (name.empty() || !ContainsNoNUL(name)) { |
198 | 0 | return {}; |
199 | 0 | } |
200 | 0 | uint16_t port{portDefault}; |
201 | 0 | std::string hostname; |
202 | 0 | SplitHostPort(name, port, hostname); |
203 | |
|
204 | 0 | const std::vector<CNetAddr> addresses{LookupIntern(hostname, nMaxSolutions, fAllowLookup, dns_lookup_function)}; |
205 | 0 | if (addresses.empty()) return {}; |
206 | 0 | std::vector<CService> services; |
207 | 0 | services.reserve(addresses.size()); |
208 | 0 | for (const auto& addr : addresses) |
209 | 0 | services.emplace_back(addr, port); |
210 | 0 | return services; |
211 | 0 | } |
212 | | |
213 | | std::optional<CService> Lookup(const std::string& name, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function) |
214 | 0 | { |
215 | 0 | const std::vector<CService> services{Lookup(name, portDefault, fAllowLookup, 1, dns_lookup_function)}; |
216 | |
|
217 | 0 | return services.empty() ? std::nullopt : std::make_optional(services.front()); |
218 | 0 | } |
219 | | |
220 | | CService LookupNumeric(const std::string& name, uint16_t portDefault, DNSLookupFn dns_lookup_function) |
221 | 0 | { |
222 | 0 | if (!ContainsNoNUL(name)) { |
223 | 0 | return {}; |
224 | 0 | } |
225 | | // "1.2:345" will fail to resolve the ip, but will still set the port. |
226 | | // If the ip fails to resolve, re-init the result. |
227 | 0 | return Lookup(name, portDefault, /*fAllowLookup=*/false, dns_lookup_function).value_or(CService{}); |
228 | 0 | } |
229 | | |
230 | | bool IsUnixSocketPath(const std::string& name) |
231 | 0 | { |
232 | 0 | #ifdef HAVE_SOCKADDR_UN |
233 | 0 | if (!name.starts_with(ADDR_PREFIX_UNIX)) return false; |
234 | | |
235 | | // Split off "unix:" prefix |
236 | 0 | std::string str{name.substr(ADDR_PREFIX_UNIX.length())}; |
237 | | |
238 | | // Path size limit is platform-dependent |
239 | | // see https://manpages.ubuntu.com/manpages/xenial/en/man7/unix.7.html |
240 | 0 | if (str.size() + 1 > sizeof(((sockaddr_un*)nullptr)->sun_path)) return false; |
241 | | |
242 | 0 | return true; |
243 | | #else |
244 | | return false; |
245 | | #endif |
246 | 0 | } |
247 | | |
248 | | /** SOCKS version */ |
249 | | enum SOCKSVersion: uint8_t { |
250 | | SOCKS4 = 0x04, |
251 | | SOCKS5 = 0x05 |
252 | | }; |
253 | | |
254 | | /** Values defined for METHOD in RFC1928 */ |
255 | | enum SOCKS5Method: uint8_t { |
256 | | NOAUTH = 0x00, //!< No authentication required |
257 | | GSSAPI = 0x01, //!< GSSAPI |
258 | | USER_PASS = 0x02, //!< Username/password |
259 | | NO_ACCEPTABLE = 0xff, //!< No acceptable methods |
260 | | }; |
261 | | |
262 | | /** Values defined for CMD in RFC1928 */ |
263 | | enum SOCKS5Command: uint8_t { |
264 | | CONNECT = 0x01, |
265 | | BIND = 0x02, |
266 | | UDP_ASSOCIATE = 0x03 |
267 | | }; |
268 | | |
269 | | /** Values defined for REP in RFC1928 */ |
270 | | enum SOCKS5Reply: uint8_t { |
271 | | SUCCEEDED = 0x00, //!< Succeeded |
272 | | GENFAILURE = 0x01, //!< General failure |
273 | | NOTALLOWED = 0x02, //!< Connection not allowed by ruleset |
274 | | NETUNREACHABLE = 0x03, //!< Network unreachable |
275 | | HOSTUNREACHABLE = 0x04, //!< Network unreachable |
276 | | CONNREFUSED = 0x05, //!< Connection refused |
277 | | TTLEXPIRED = 0x06, //!< TTL expired |
278 | | CMDUNSUPPORTED = 0x07, //!< Command not supported |
279 | | ATYPEUNSUPPORTED = 0x08, //!< Address type not supported |
280 | | }; |
281 | | |
282 | | /** Values defined for ATYPE in RFC1928 */ |
283 | | enum SOCKS5Atyp: uint8_t { |
284 | | IPV4 = 0x01, |
285 | | DOMAINNAME = 0x03, |
286 | | IPV6 = 0x04, |
287 | | }; |
288 | | |
289 | | /** Status codes that can be returned by InterruptibleRecv */ |
290 | | enum class IntrRecvError { |
291 | | OK, |
292 | | Timeout, |
293 | | Disconnected, |
294 | | NetworkError, |
295 | | Interrupted |
296 | | }; |
297 | | |
298 | | /** |
299 | | * Try to read a specified number of bytes from a socket. Please read the "see |
300 | | * also" section for more detail. |
301 | | * |
302 | | * @param data The buffer where the read bytes should be stored. |
303 | | * @param len The number of bytes to read into the specified buffer. |
304 | | * @param timeout The total timeout for this read. |
305 | | * @param sock The socket (has to be in non-blocking mode) from which to read bytes. |
306 | | * |
307 | | * @returns An IntrRecvError indicating the resulting status of this read. |
308 | | * IntrRecvError::OK only if all of the specified number of bytes were |
309 | | * read. |
310 | | * |
311 | | * @see This function can be interrupted by calling g_socks5_interrupt(). |
312 | | * Sockets can be made non-blocking with Sock::SetNonBlocking(). |
313 | | */ |
314 | | static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, std::chrono::milliseconds timeout, const Sock& sock) |
315 | 0 | { |
316 | 0 | auto curTime{Now<SteadyMilliseconds>()}; |
317 | 0 | const auto endTime{curTime + timeout}; |
318 | 0 | while (len > 0 && curTime < endTime) { |
319 | 0 | ssize_t ret = sock.Recv(data, len, 0); // Optimistically try the recv first |
320 | 0 | if (ret > 0) { |
321 | 0 | len -= ret; |
322 | 0 | data += ret; |
323 | 0 | } else if (ret == 0) { // Unexpected disconnection |
324 | 0 | return IntrRecvError::Disconnected; |
325 | 0 | } else { // Other error or blocking |
326 | 0 | int nErr = WSAGetLastError(); |
327 | 0 | if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { |
328 | | // Only wait at most MAX_WAIT_FOR_IO at a time, unless |
329 | | // we're approaching the end of the specified total timeout |
330 | 0 | const auto remaining = std::chrono::milliseconds{endTime - curTime}; |
331 | 0 | const auto timeout = std::min(remaining, std::chrono::milliseconds{MAX_WAIT_FOR_IO}); |
332 | 0 | if (!sock.Wait(timeout, Sock::RECV)) { |
333 | 0 | return IntrRecvError::NetworkError; |
334 | 0 | } |
335 | 0 | } else { |
336 | 0 | return IntrRecvError::NetworkError; |
337 | 0 | } |
338 | 0 | } |
339 | 0 | if (g_socks5_interrupt) { |
340 | 0 | return IntrRecvError::Interrupted; |
341 | 0 | } |
342 | 0 | curTime = Now<SteadyMilliseconds>(); |
343 | 0 | } |
344 | 0 | return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout; |
345 | 0 | } |
346 | | |
347 | | /** Convert SOCKS5 reply to an error message */ |
348 | | static std::string Socks5ErrorString(uint8_t err) |
349 | 0 | { |
350 | 0 | switch(err) { |
351 | 0 | case SOCKS5Reply::GENFAILURE: |
352 | 0 | return "general failure"; |
353 | 0 | case SOCKS5Reply::NOTALLOWED: |
354 | 0 | return "connection not allowed"; |
355 | 0 | case SOCKS5Reply::NETUNREACHABLE: |
356 | 0 | return "network unreachable"; |
357 | 0 | case SOCKS5Reply::HOSTUNREACHABLE: |
358 | 0 | return "host unreachable"; |
359 | 0 | case SOCKS5Reply::CONNREFUSED: |
360 | 0 | return "connection refused"; |
361 | 0 | case SOCKS5Reply::TTLEXPIRED: |
362 | 0 | return "TTL expired"; |
363 | 0 | case SOCKS5Reply::CMDUNSUPPORTED: |
364 | 0 | return "protocol error"; |
365 | 0 | case SOCKS5Reply::ATYPEUNSUPPORTED: |
366 | 0 | return "address type not supported"; |
367 | 0 | default: |
368 | 0 | return "unknown"; |
369 | 0 | } |
370 | 0 | } |
371 | | |
372 | | bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* auth, const Sock& sock) |
373 | 0 | { |
374 | 0 | try { |
375 | 0 | IntrRecvError recvr; |
376 | 0 | LogDebug(BCLog::NET, "SOCKS5 connecting %s\n", strDest); |
377 | 0 | if (strDest.size() > 255) { |
378 | 0 | LogError("Hostname too long\n"); |
379 | 0 | return false; |
380 | 0 | } |
381 | | // Construct the version identifier/method selection message |
382 | 0 | std::vector<uint8_t> vSocks5Init; |
383 | 0 | vSocks5Init.push_back(SOCKSVersion::SOCKS5); // We want the SOCK5 protocol |
384 | 0 | if (auth) { |
385 | 0 | vSocks5Init.push_back(0x02); // 2 method identifiers follow... |
386 | 0 | vSocks5Init.push_back(SOCKS5Method::NOAUTH); |
387 | 0 | vSocks5Init.push_back(SOCKS5Method::USER_PASS); |
388 | 0 | } else { |
389 | 0 | vSocks5Init.push_back(0x01); // 1 method identifier follows... |
390 | 0 | vSocks5Init.push_back(SOCKS5Method::NOAUTH); |
391 | 0 | } |
392 | 0 | sock.SendComplete(vSocks5Init, g_socks5_recv_timeout, g_socks5_interrupt); |
393 | 0 | uint8_t pchRet1[2]; |
394 | 0 | if (InterruptibleRecv(pchRet1, 2, g_socks5_recv_timeout, sock) != IntrRecvError::OK) { |
395 | 0 | LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port); |
396 | 0 | return false; |
397 | 0 | } |
398 | 0 | if (pchRet1[0] != SOCKSVersion::SOCKS5) { |
399 | 0 | LogError("Proxy failed to initialize\n"); |
400 | 0 | return false; |
401 | 0 | } |
402 | 0 | if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) { |
403 | | // Perform username/password authentication (as described in RFC1929) |
404 | 0 | std::vector<uint8_t> vAuth; |
405 | 0 | vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation |
406 | 0 | if (auth->username.size() > 255 || auth->password.size() > 255) { |
407 | 0 | LogError("Proxy username or password too long\n"); |
408 | 0 | return false; |
409 | 0 | } |
410 | 0 | vAuth.push_back(auth->username.size()); |
411 | 0 | vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end()); |
412 | 0 | vAuth.push_back(auth->password.size()); |
413 | 0 | vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end()); |
414 | 0 | sock.SendComplete(vAuth, g_socks5_recv_timeout, g_socks5_interrupt); |
415 | 0 | LogDebug(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password); |
416 | 0 | uint8_t pchRetA[2]; |
417 | 0 | if (InterruptibleRecv(pchRetA, 2, g_socks5_recv_timeout, sock) != IntrRecvError::OK) { |
418 | 0 | LogError("Error reading proxy authentication response\n"); |
419 | 0 | return false; |
420 | 0 | } |
421 | 0 | if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) { |
422 | 0 | LogError("Proxy authentication unsuccessful\n"); |
423 | 0 | return false; |
424 | 0 | } |
425 | 0 | } else if (pchRet1[1] == SOCKS5Method::NOAUTH) { |
426 | | // Perform no authentication |
427 | 0 | } else { |
428 | 0 | LogError("Proxy requested wrong authentication method %02x\n", pchRet1[1]); |
429 | 0 | return false; |
430 | 0 | } |
431 | 0 | std::vector<uint8_t> vSocks5; |
432 | 0 | vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version |
433 | 0 | vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT |
434 | 0 | vSocks5.push_back(0x00); // RSV Reserved must be 0 |
435 | 0 | vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME |
436 | 0 | vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function |
437 | 0 | vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end()); |
438 | 0 | vSocks5.push_back((port >> 8) & 0xFF); |
439 | 0 | vSocks5.push_back((port >> 0) & 0xFF); |
440 | 0 | sock.SendComplete(vSocks5, g_socks5_recv_timeout, g_socks5_interrupt); |
441 | 0 | uint8_t pchRet2[4]; |
442 | 0 | if ((recvr = InterruptibleRecv(pchRet2, 4, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) { |
443 | 0 | if (recvr == IntrRecvError::Timeout) { |
444 | | /* If a timeout happens here, this effectively means we timed out while connecting |
445 | | * to the remote node. This is very common for Tor, so do not print an |
446 | | * error message. */ |
447 | 0 | return false; |
448 | 0 | } else { |
449 | 0 | LogError("Error while reading proxy response\n"); |
450 | 0 | return false; |
451 | 0 | } |
452 | 0 | } |
453 | 0 | if (pchRet2[0] != SOCKSVersion::SOCKS5) { |
454 | 0 | LogError("Proxy failed to accept request\n"); |
455 | 0 | return false; |
456 | 0 | } |
457 | 0 | if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) { |
458 | | // Failures to connect to a peer that are not proxy errors |
459 | 0 | LogPrintLevel(BCLog::NET, BCLog::Level::Debug, |
460 | 0 | "Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1])); |
461 | 0 | return false; |
462 | 0 | } |
463 | 0 | if (pchRet2[2] != 0x00) { // Reserved field must be 0 |
464 | 0 | LogError("Error: malformed proxy response\n"); |
465 | 0 | return false; |
466 | 0 | } |
467 | 0 | uint8_t pchRet3[256]; |
468 | 0 | switch (pchRet2[3]) { |
469 | 0 | case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, g_socks5_recv_timeout, sock); break; |
470 | 0 | case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, g_socks5_recv_timeout, sock); break; |
471 | 0 | case SOCKS5Atyp::DOMAINNAME: { |
472 | 0 | recvr = InterruptibleRecv(pchRet3, 1, g_socks5_recv_timeout, sock); |
473 | 0 | if (recvr != IntrRecvError::OK) { |
474 | 0 | LogError("Error reading from proxy\n"); |
475 | 0 | return false; |
476 | 0 | } |
477 | 0 | int nRecv = pchRet3[0]; |
478 | 0 | recvr = InterruptibleRecv(pchRet3, nRecv, g_socks5_recv_timeout, sock); |
479 | 0 | break; |
480 | 0 | } |
481 | 0 | default: { |
482 | 0 | LogError("Error: malformed proxy response\n"); |
483 | 0 | return false; |
484 | 0 | } |
485 | 0 | } |
486 | 0 | if (recvr != IntrRecvError::OK) { |
487 | 0 | LogError("Error reading from proxy\n"); |
488 | 0 | return false; |
489 | 0 | } |
490 | 0 | if (InterruptibleRecv(pchRet3, 2, g_socks5_recv_timeout, sock) != IntrRecvError::OK) { |
491 | 0 | LogError("Error reading from proxy\n"); |
492 | 0 | return false; |
493 | 0 | } |
494 | 0 | LogDebug(BCLog::NET, "SOCKS5 connected %s\n", strDest); |
495 | 0 | return true; |
496 | 0 | } catch (const std::runtime_error& e) { |
497 | 0 | LogError("Error during SOCKS5 proxy handshake: %s\n", e.what()); |
498 | 0 | return false; |
499 | 0 | } |
500 | 0 | } |
501 | | |
502 | | std::unique_ptr<Sock> CreateSockOS(int domain, int type, int protocol) |
503 | 0 | { |
504 | | // Not IPv4, IPv6 or UNIX |
505 | 0 | if (domain == AF_UNSPEC) return nullptr; |
506 | | |
507 | | // Create a socket in the specified address family. |
508 | 0 | SOCKET hSocket = socket(domain, type, protocol); |
509 | 0 | if (hSocket == INVALID_SOCKET) { |
510 | 0 | return nullptr; |
511 | 0 | } |
512 | | |
513 | 0 | auto sock = std::make_unique<Sock>(hSocket); |
514 | |
|
515 | 0 | if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNIX) { |
516 | 0 | return sock; |
517 | 0 | } |
518 | | |
519 | | // Ensure that waiting for I/O on this socket won't result in undefined |
520 | | // behavior. |
521 | 0 | if (!sock->IsSelectable()) { |
522 | 0 | LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n"); |
523 | 0 | return nullptr; |
524 | 0 | } |
525 | | |
526 | | #ifdef SO_NOSIGPIPE |
527 | | int set = 1; |
528 | | // Set the no-sigpipe option on the socket for BSD systems, other UNIXes |
529 | | // should use the MSG_NOSIGNAL flag for every send. |
530 | | if (sock->SetSockOpt(SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int)) == SOCKET_ERROR) { |
531 | | LogPrintf("Error setting SO_NOSIGPIPE on socket: %s, continuing anyway\n", |
532 | | NetworkErrorString(WSAGetLastError())); |
533 | | } |
534 | | #endif |
535 | | |
536 | | // Set the non-blocking option on the socket. |
537 | 0 | if (!sock->SetNonBlocking()) { |
538 | 0 | LogPrintf("Error setting socket to non-blocking: %s\n", NetworkErrorString(WSAGetLastError())); |
539 | 0 | return nullptr; |
540 | 0 | } |
541 | | |
542 | 0 | #ifdef HAVE_SOCKADDR_UN |
543 | 0 | if (domain == AF_UNIX) return sock; |
544 | 0 | #endif |
545 | | |
546 | 0 | if (protocol == IPPROTO_TCP) { |
547 | | // Set the no-delay option (disable Nagle's algorithm) on the TCP socket. |
548 | 0 | const int on{1}; |
549 | 0 | if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) { |
550 | 0 | LogDebug(BCLog::NET, "Unable to set TCP_NODELAY on a newly created socket, continuing anyway\n"); |
551 | 0 | } |
552 | 0 | } |
553 | |
|
554 | 0 | return sock; |
555 | 0 | } |
556 | | |
557 | | std::function<std::unique_ptr<Sock>(int, int, int)> CreateSock = CreateSockOS; |
558 | | |
559 | | template<typename... Args> |
560 | | static void LogConnectFailure(bool manual_connection, util::ConstevalFormatString<sizeof...(Args)> fmt, const Args&... args) |
561 | 0 | { |
562 | 0 | std::string error_message = tfm::format(fmt, args...); |
563 | 0 | if (manual_connection) { |
564 | 0 | LogPrintf("%s\n", error_message); |
565 | 0 | } else { |
566 | 0 | LogDebug(BCLog::NET, "%s\n", error_message); |
567 | 0 | } |
568 | 0 | } |
569 | | |
570 | | static bool ConnectToSocket(const Sock& sock, struct sockaddr* sockaddr, socklen_t len, const std::string& dest_str, bool manual_connection) |
571 | 0 | { |
572 | | // Connect to `sockaddr` using `sock`. |
573 | 0 | if (sock.Connect(sockaddr, len) == SOCKET_ERROR) { |
574 | 0 | int nErr = WSAGetLastError(); |
575 | | // WSAEINVAL is here because some legacy version of winsock uses it |
576 | 0 | if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) |
577 | 0 | { |
578 | | // Connection didn't actually fail, but is being established |
579 | | // asynchronously. Thus, use async I/O api (select/poll) |
580 | | // synchronously to check for successful connection with a timeout. |
581 | 0 | const Sock::Event requested = Sock::RECV | Sock::SEND; |
582 | 0 | Sock::Event occurred; |
583 | 0 | if (!sock.Wait(std::chrono::milliseconds{nConnectTimeout}, requested, &occurred)) { |
584 | 0 | LogPrintf("wait for connect to %s failed: %s\n", |
585 | 0 | dest_str, |
586 | 0 | NetworkErrorString(WSAGetLastError())); |
587 | 0 | return false; |
588 | 0 | } else if (occurred == 0) { |
589 | 0 | LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "connection attempt to %s timed out\n", dest_str); |
590 | 0 | return false; |
591 | 0 | } |
592 | | |
593 | | // Even if the wait was successful, the connect might not |
594 | | // have been successful. The reason for this failure is hidden away |
595 | | // in the SO_ERROR for the socket in modern systems. We read it into |
596 | | // sockerr here. |
597 | 0 | int sockerr; |
598 | 0 | socklen_t sockerr_len = sizeof(sockerr); |
599 | 0 | if (sock.GetSockOpt(SOL_SOCKET, SO_ERROR, (sockopt_arg_type)&sockerr, &sockerr_len) == |
600 | 0 | SOCKET_ERROR) { |
601 | 0 | LogPrintf("getsockopt() for %s failed: %s\n", dest_str, NetworkErrorString(WSAGetLastError())); |
602 | 0 | return false; |
603 | 0 | } |
604 | 0 | if (sockerr != 0) { |
605 | 0 | LogConnectFailure(manual_connection, |
606 | 0 | "connect() to %s failed after wait: %s", |
607 | 0 | dest_str, |
608 | 0 | NetworkErrorString(sockerr)); |
609 | 0 | return false; |
610 | 0 | } |
611 | 0 | } |
612 | | #ifdef WIN32 |
613 | | else if (WSAGetLastError() != WSAEISCONN) |
614 | | #else |
615 | 0 | else |
616 | 0 | #endif |
617 | 0 | { |
618 | 0 | LogConnectFailure(manual_connection, "connect() to %s failed: %s", dest_str, NetworkErrorString(WSAGetLastError())); |
619 | 0 | return false; |
620 | 0 | } |
621 | 0 | } |
622 | 0 | return true; |
623 | 0 | } |
624 | | |
625 | | std::unique_ptr<Sock> ConnectDirectly(const CService& dest, bool manual_connection) |
626 | 0 | { |
627 | 0 | auto sock = CreateSock(dest.GetSAFamily(), SOCK_STREAM, IPPROTO_TCP); |
628 | 0 | if (!sock) { |
629 | 0 | LogPrintLevel(BCLog::NET, BCLog::Level::Error, "Cannot create a socket for connecting to %s\n", dest.ToStringAddrPort()); |
630 | 0 | return {}; |
631 | 0 | } |
632 | | |
633 | | // Create a sockaddr from the specified service. |
634 | 0 | struct sockaddr_storage sockaddr; |
635 | 0 | socklen_t len = sizeof(sockaddr); |
636 | 0 | if (!dest.GetSockAddr((struct sockaddr*)&sockaddr, &len)) { |
637 | 0 | LogPrintf("Cannot get sockaddr for %s: unsupported network\n", dest.ToStringAddrPort()); |
638 | 0 | return {}; |
639 | 0 | } |
640 | | |
641 | 0 | if (!ConnectToSocket(*sock, (struct sockaddr*)&sockaddr, len, dest.ToStringAddrPort(), manual_connection)) { |
642 | 0 | return {}; |
643 | 0 | } |
644 | | |
645 | 0 | return sock; |
646 | 0 | } |
647 | | |
648 | | std::unique_ptr<Sock> Proxy::Connect() const |
649 | 0 | { |
650 | 0 | if (!IsValid()) return {}; |
651 | | |
652 | 0 | if (!m_is_unix_socket) return ConnectDirectly(proxy, /*manual_connection=*/true); |
653 | | |
654 | 0 | #ifdef HAVE_SOCKADDR_UN |
655 | 0 | auto sock = CreateSock(AF_UNIX, SOCK_STREAM, 0); |
656 | 0 | if (!sock) { |
657 | 0 | LogPrintLevel(BCLog::NET, BCLog::Level::Error, "Cannot create a socket for connecting to %s\n", m_unix_socket_path); |
658 | 0 | return {}; |
659 | 0 | } |
660 | | |
661 | 0 | const std::string path{m_unix_socket_path.substr(ADDR_PREFIX_UNIX.length())}; |
662 | |
|
663 | 0 | struct sockaddr_un addrun; |
664 | 0 | memset(&addrun, 0, sizeof(addrun)); |
665 | 0 | addrun.sun_family = AF_UNIX; |
666 | | // leave the last char in addrun.sun_path[] to be always '\0' |
667 | 0 | memcpy(addrun.sun_path, path.c_str(), std::min(sizeof(addrun.sun_path) - 1, path.length())); |
668 | 0 | socklen_t len = sizeof(addrun); |
669 | |
|
670 | 0 | if(!ConnectToSocket(*sock, (struct sockaddr*)&addrun, len, path, /*manual_connection=*/true)) { |
671 | 0 | return {}; |
672 | 0 | } |
673 | | |
674 | 0 | return sock; |
675 | | #else |
676 | | return {}; |
677 | | #endif |
678 | 0 | } |
679 | | |
680 | 0 | bool SetProxy(enum Network net, const Proxy &addrProxy) { |
681 | 0 | assert(net >= 0 && net < NET_MAX); |
682 | 0 | if (!addrProxy.IsValid()) |
683 | 0 | return false; |
684 | 0 | LOCK(g_proxyinfo_mutex); |
685 | 0 | proxyInfo[net] = addrProxy; |
686 | 0 | return true; |
687 | 0 | } |
688 | | |
689 | 0 | bool GetProxy(enum Network net, Proxy &proxyInfoOut) { |
690 | 0 | assert(net >= 0 && net < NET_MAX); |
691 | 0 | LOCK(g_proxyinfo_mutex); |
692 | 0 | if (!proxyInfo[net].IsValid()) |
693 | 0 | return false; |
694 | 0 | proxyInfoOut = proxyInfo[net]; |
695 | 0 | return true; |
696 | 0 | } |
697 | | |
698 | 0 | bool SetNameProxy(const Proxy &addrProxy) { |
699 | 0 | if (!addrProxy.IsValid()) |
700 | 0 | return false; |
701 | 0 | LOCK(g_proxyinfo_mutex); |
702 | 0 | nameProxy = addrProxy; |
703 | 0 | return true; |
704 | 0 | } |
705 | | |
706 | 0 | bool GetNameProxy(Proxy &nameProxyOut) { |
707 | 0 | LOCK(g_proxyinfo_mutex); |
708 | 0 | if(!nameProxy.IsValid()) |
709 | 0 | return false; |
710 | 0 | nameProxyOut = nameProxy; |
711 | 0 | return true; |
712 | 0 | } |
713 | | |
714 | 0 | bool HaveNameProxy() { |
715 | 0 | LOCK(g_proxyinfo_mutex); |
716 | 0 | return nameProxy.IsValid(); |
717 | 0 | } |
718 | | |
719 | 0 | bool IsProxy(const CNetAddr &addr) { |
720 | 0 | LOCK(g_proxyinfo_mutex); |
721 | 0 | for (int i = 0; i < NET_MAX; i++) { |
722 | 0 | if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy)) |
723 | 0 | return true; |
724 | 0 | } |
725 | 0 | return false; |
726 | 0 | } |
727 | | |
728 | | std::unique_ptr<Sock> ConnectThroughProxy(const Proxy& proxy, |
729 | | const std::string& dest, |
730 | | uint16_t port, |
731 | | bool& proxy_connection_failed) |
732 | 0 | { |
733 | | // first connect to proxy server |
734 | 0 | auto sock = proxy.Connect(); |
735 | 0 | if (!sock) { |
736 | 0 | proxy_connection_failed = true; |
737 | 0 | return {}; |
738 | 0 | } |
739 | | |
740 | | // do socks negotiation |
741 | 0 | if (proxy.m_randomize_credentials) { |
742 | 0 | ProxyCredentials random_auth; |
743 | 0 | static std::atomic_int counter(0); |
744 | 0 | random_auth.username = random_auth.password = strprintf("%i", counter++); |
745 | 0 | if (!Socks5(dest, port, &random_auth, *sock)) { |
746 | 0 | return {}; |
747 | 0 | } |
748 | 0 | } else { |
749 | 0 | if (!Socks5(dest, port, nullptr, *sock)) { |
750 | 0 | return {}; |
751 | 0 | } |
752 | 0 | } |
753 | 0 | return sock; |
754 | 0 | } |
755 | | |
756 | | CSubNet LookupSubNet(const std::string& subnet_str) |
757 | 0 | { |
758 | 0 | CSubNet subnet; |
759 | 0 | assert(!subnet.IsValid()); |
760 | 0 | if (!ContainsNoNUL(subnet_str)) { |
761 | 0 | return subnet; |
762 | 0 | } |
763 | | |
764 | 0 | const size_t slash_pos{subnet_str.find_last_of('/')}; |
765 | 0 | const std::string str_addr{subnet_str.substr(0, slash_pos)}; |
766 | 0 | std::optional<CNetAddr> addr{LookupHost(str_addr, /*fAllowLookup=*/false)}; |
767 | |
|
768 | 0 | if (addr.has_value()) { |
769 | 0 | addr = static_cast<CNetAddr>(MaybeFlipIPv6toCJDNS(CService{addr.value(), /*port=*/0})); |
770 | 0 | if (slash_pos != subnet_str.npos) { |
771 | 0 | const std::string netmask_str{subnet_str.substr(slash_pos + 1)}; |
772 | 0 | uint8_t netmask; |
773 | 0 | if (ParseUInt8(netmask_str, &netmask)) { |
774 | | // Valid number; assume CIDR variable-length subnet masking. |
775 | 0 | subnet = CSubNet{addr.value(), netmask}; |
776 | 0 | } else { |
777 | | // Invalid number; try full netmask syntax. Never allow lookup for netmask. |
778 | 0 | const std::optional<CNetAddr> full_netmask{LookupHost(netmask_str, /*fAllowLookup=*/false)}; |
779 | 0 | if (full_netmask.has_value()) { |
780 | 0 | subnet = CSubNet{addr.value(), full_netmask.value()}; |
781 | 0 | } |
782 | 0 | } |
783 | 0 | } else { |
784 | | // Single IP subnet (<ipv4>/32 or <ipv6>/128). |
785 | 0 | subnet = CSubNet{addr.value()}; |
786 | 0 | } |
787 | 0 | } |
788 | |
|
789 | 0 | return subnet; |
790 | 0 | } |
791 | | |
792 | | bool IsBadPort(uint16_t port) |
793 | 0 | { |
794 | | /* Don't forget to update doc/p2p-bad-ports.md if you change this list. */ |
795 | |
|
796 | 0 | switch (port) { |
797 | 0 | case 1: // tcpmux |
798 | 0 | case 7: // echo |
799 | 0 | case 9: // discard |
800 | 0 | case 11: // systat |
801 | 0 | case 13: // daytime |
802 | 0 | case 15: // netstat |
803 | 0 | case 17: // qotd |
804 | 0 | case 19: // chargen |
805 | 0 | case 20: // ftp data |
806 | 0 | case 21: // ftp access |
807 | 0 | case 22: // ssh |
808 | 0 | case 23: // telnet |
809 | 0 | case 25: // smtp |
810 | 0 | case 37: // time |
811 | 0 | case 42: // name |
812 | 0 | case 43: // nicname |
813 | 0 | case 53: // domain |
814 | 0 | case 69: // tftp |
815 | 0 | case 77: // priv-rjs |
816 | 0 | case 79: // finger |
817 | 0 | case 87: // ttylink |
818 | 0 | case 95: // supdup |
819 | 0 | case 101: // hostname |
820 | 0 | case 102: // iso-tsap |
821 | 0 | case 103: // gppitnp |
822 | 0 | case 104: // acr-nema |
823 | 0 | case 109: // pop2 |
824 | 0 | case 110: // pop3 |
825 | 0 | case 111: // sunrpc |
826 | 0 | case 113: // auth |
827 | 0 | case 115: // sftp |
828 | 0 | case 117: // uucp-path |
829 | 0 | case 119: // nntp |
830 | 0 | case 123: // NTP |
831 | 0 | case 135: // loc-srv /epmap |
832 | 0 | case 137: // netbios |
833 | 0 | case 139: // netbios |
834 | 0 | case 143: // imap2 |
835 | 0 | case 161: // snmp |
836 | 0 | case 179: // BGP |
837 | 0 | case 389: // ldap |
838 | 0 | case 427: // SLP (Also used by Apple Filing Protocol) |
839 | 0 | case 465: // smtp+ssl |
840 | 0 | case 512: // print / exec |
841 | 0 | case 513: // login |
842 | 0 | case 514: // shell |
843 | 0 | case 515: // printer |
844 | 0 | case 526: // tempo |
845 | 0 | case 530: // courier |
846 | 0 | case 531: // chat |
847 | 0 | case 532: // netnews |
848 | 0 | case 540: // uucp |
849 | 0 | case 548: // AFP (Apple Filing Protocol) |
850 | 0 | case 554: // rtsp |
851 | 0 | case 556: // remotefs |
852 | 0 | case 563: // nntp+ssl |
853 | 0 | case 587: // smtp (rfc6409) |
854 | 0 | case 601: // syslog-conn (rfc3195) |
855 | 0 | case 636: // ldap+ssl |
856 | 0 | case 989: // ftps-data |
857 | 0 | case 990: // ftps |
858 | 0 | case 993: // ldap+ssl |
859 | 0 | case 995: // pop3+ssl |
860 | 0 | case 1719: // h323gatestat |
861 | 0 | case 1720: // h323hostcall |
862 | 0 | case 1723: // pptp |
863 | 0 | case 2049: // nfs |
864 | 0 | case 3659: // apple-sasl / PasswordServer |
865 | 0 | case 4045: // lockd |
866 | 0 | case 5060: // sip |
867 | 0 | case 5061: // sips |
868 | 0 | case 6000: // X11 |
869 | 0 | case 6566: // sane-port |
870 | 0 | case 6665: // Alternate IRC |
871 | 0 | case 6666: // Alternate IRC |
872 | 0 | case 6667: // Standard IRC |
873 | 0 | case 6668: // Alternate IRC |
874 | 0 | case 6669: // Alternate IRC |
875 | 0 | case 6697: // IRC + TLS |
876 | 0 | case 10080: // Amanda |
877 | 0 | return true; |
878 | 0 | } |
879 | 0 | return false; |
880 | 0 | } |
881 | | |
882 | | CService MaybeFlipIPv6toCJDNS(const CService& service) |
883 | 0 | { |
884 | 0 | CService ret{service}; |
885 | 0 | if (ret.IsIPv6() && ret.HasCJDNSPrefix() && g_reachable_nets.Contains(NET_CJDNS)) { |
886 | 0 | ret.m_net = NET_CJDNS; |
887 | 0 | } |
888 | 0 | return ret; |
889 | 0 | } |