Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2020 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 <netbase.h>
7 :
8 : #include <sync.h>
9 : #include <tinyformat.h>
10 : #include <util/strencodings.h>
11 : #include <util/string.h>
12 : #include <util/system.h>
13 :
14 : #include <atomic>
15 : #include <cstdint>
16 : #include <limits>
17 :
18 : #ifndef WIN32
19 : #include <fcntl.h>
20 : #else
21 : #include <codecvt>
22 : #endif
23 :
24 : #ifdef USE_POLL
25 : #include <poll.h>
26 : #endif
27 :
28 : #if !defined(MSG_NOSIGNAL)
29 : #define MSG_NOSIGNAL 0
30 : #endif
31 :
32 : // Settings
33 640 : static Mutex g_proxyinfo_mutex;
34 6400 : static proxyType proxyInfo[NET_MAX] GUARDED_BY(g_proxyinfo_mutex);
35 640 : static proxyType 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 (milliseconds)
40 : static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
41 : static std::atomic<bool> interruptSocks5Recv(false);
42 :
43 12 : enum Network ParseNetwork(const std::string& net_in) {
44 12 : std::string net = ToLower(net_in);
45 12 : if (net == "ipv4") return NET_IPV4;
46 10 : if (net == "ipv6") return NET_IPV6;
47 8 : if (net == "onion") return NET_ONION;
48 6 : if (net == "tor") {
49 2 : LogPrintf("Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n");
50 2 : return NET_ONION;
51 : }
52 4 : return NET_UNROUTABLE;
53 12 : }
54 :
55 132 : std::string GetNetworkName(enum Network net) {
56 132 : switch(net)
57 : {
58 44 : case NET_IPV4: return "ipv4";
59 44 : case NET_IPV6: return "ipv6";
60 44 : case NET_ONION: return "onion";
61 0 : default: return "";
62 : }
63 132 : }
64 :
65 263383 : bool static LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
66 : {
67 263383 : vIP.clear();
68 :
69 263383 : if (!ValidAsCString(name)) {
70 0 : return false;
71 : }
72 :
73 : {
74 263383 : CNetAddr addr;
75 : // From our perspective, onion addresses are not hostnames but rather
76 : // direct encodings of CNetAddr much like IPv4 dotted-decimal notation
77 : // or IPv6 colon-separated hextet notation. Since we can't use
78 : // getaddrinfo to decode them and it wouldn't make sense to resolve
79 : // them, we return a network address representing it instead. See
80 : // CNetAddr::SetSpecial(const std::string&) for more details.
81 263383 : if (addr.SetSpecial(name)) {
82 6 : vIP.push_back(addr);
83 6 : return true;
84 : }
85 263383 : }
86 :
87 263377 : struct addrinfo aiHint;
88 263377 : memset(&aiHint, 0, sizeof(struct addrinfo));
89 :
90 : // We want a TCP port, which is a streaming socket type
91 263377 : aiHint.ai_socktype = SOCK_STREAM;
92 263377 : aiHint.ai_protocol = IPPROTO_TCP;
93 : // We don't care which address family (IPv4 or IPv6) is returned
94 263377 : aiHint.ai_family = AF_UNSPEC;
95 : // If we allow lookups of hostnames, use the AI_ADDRCONFIG flag to only
96 : // return addresses whose family we have an address configured for.
97 : //
98 : // If we don't allow lookups, then use the AI_NUMERICHOST flag for
99 : // getaddrinfo to only decode numerical network addresses and suppress
100 : // hostname lookups.
101 263377 : aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
102 263377 : struct addrinfo *aiRes = nullptr;
103 263377 : int nErr = getaddrinfo(name.c_str(), nullptr, &aiHint, &aiRes);
104 263377 : if (nErr)
105 17 : return false;
106 :
107 : // Traverse the linked list starting with aiTrav, add all non-internal
108 : // IPv4,v6 addresses to vIP while respecting nMaxSolutions.
109 263360 : struct addrinfo *aiTrav = aiRes;
110 526720 : while (aiTrav != nullptr && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
111 : {
112 263360 : CNetAddr resolved;
113 263360 : if (aiTrav->ai_family == AF_INET)
114 : {
115 262236 : assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
116 262236 : resolved = CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr);
117 262236 : }
118 :
119 263360 : if (aiTrav->ai_family == AF_INET6)
120 : {
121 1124 : assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
122 1124 : struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
123 1124 : resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
124 1124 : }
125 : /* Never allow resolving to an internal address. Consider any such result invalid */
126 263360 : if (!resolved.IsInternal()) {
127 263359 : vIP.push_back(resolved);
128 : }
129 :
130 263360 : aiTrav = aiTrav->ai_next;
131 263360 : }
132 :
133 263360 : freeaddrinfo(aiRes);
134 :
135 263360 : return (vIP.size() > 0);
136 263383 : }
137 :
138 : /**
139 : * Resolve a host string to its corresponding network addresses.
140 : *
141 : * @param name The string representing a host. Could be a name or a numerical
142 : * IP address (IPv6 addresses in their bracketed form are
143 : * allowed).
144 : * @param[out] vIP The resulting network addresses to which the specified host
145 : * string resolved.
146 : *
147 : * @returns Whether or not the specified host string successfully resolved to
148 : * any resulting network addresses.
149 : *
150 : * @see Lookup(const char *, std::vector<CService>&, int, bool, unsigned int)
151 : * for additional parameter descriptions.
152 : */
153 18820 : bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
154 : {
155 18820 : if (!ValidAsCString(name)) {
156 0 : return false;
157 : }
158 18820 : std::string strHost = name;
159 18820 : if (strHost.empty())
160 1 : return false;
161 18819 : if (strHost.front() == '[' && strHost.back() == ']') {
162 0 : strHost = strHost.substr(1, strHost.size() - 2);
163 0 : }
164 :
165 18819 : return LookupIntern(strHost, vIP, nMaxSolutions, fAllowLookup);
166 18820 : }
167 :
168 : /**
169 : * Resolve a host string to its first corresponding network address.
170 : *
171 : * @see LookupHost(const std::string&, std::vector<CNetAddr>&, unsigned int, bool) for
172 : * additional parameter descriptions.
173 : */
174 18622 : bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup)
175 : {
176 18622 : if (!ValidAsCString(name)) {
177 3 : return false;
178 : }
179 18619 : std::vector<CNetAddr> vIP;
180 18619 : LookupHost(name, vIP, 1, fAllowLookup);
181 18619 : if(vIP.empty())
182 3 : return false;
183 18616 : addr = vIP.front();
184 18616 : return true;
185 18622 : }
186 :
187 : /**
188 : * Resolve a service string to its corresponding service.
189 : *
190 : * @param name The string representing a service. Could be a name or a
191 : * numerical IP address (IPv6 addresses should be in their
192 : * disambiguated bracketed form), optionally followed by a port
193 : * number. (e.g. example.com:8333 or
194 : * [2001:db8:85a3:8d3:1319:8a2e:370:7348]:420)
195 : * @param[out] vAddr The resulting services to which the specified service string
196 : * resolved.
197 : * @param portDefault The default port for resulting services if not specified
198 : * by the service string.
199 : * @param fAllowLookup Whether or not hostname lookups are permitted. If yes,
200 : * external queries may be performed.
201 : * @param nMaxSolutions The maximum number of results we want, specifying 0
202 : * means "as many solutions as we get."
203 : *
204 : * @returns Whether or not the service string successfully resolved to any
205 : * resulting services.
206 : */
207 244566 : bool Lookup(const std::string& name, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
208 : {
209 244566 : if (name.empty() || !ValidAsCString(name)) {
210 2 : return false;
211 : }
212 244564 : int port = portDefault;
213 244564 : std::string hostname;
214 244564 : SplitHostPort(name, port, hostname);
215 :
216 244564 : std::vector<CNetAddr> vIP;
217 244564 : bool fRet = LookupIntern(hostname, vIP, nMaxSolutions, fAllowLookup);
218 244564 : if (!fRet)
219 8 : return false;
220 244556 : vAddr.resize(vIP.size());
221 489112 : for (unsigned int i = 0; i < vIP.size(); i++)
222 244556 : vAddr[i] = CService(vIP[i], port);
223 244556 : return true;
224 244566 : }
225 :
226 : /**
227 : * Resolve a service string to its first corresponding service.
228 : *
229 : * @see Lookup(const char *, std::vector<CService>&, int, bool, unsigned int)
230 : * for additional parameter descriptions.
231 : */
232 244317 : bool Lookup(const std::string& name, CService& addr, int portDefault, bool fAllowLookup)
233 : {
234 244317 : if (!ValidAsCString(name)) {
235 1 : return false;
236 : }
237 244316 : std::vector<CService> vService;
238 244316 : bool fRet = Lookup(name, vService, portDefault, fAllowLookup, 1);
239 244316 : if (!fRet)
240 6 : return false;
241 244310 : addr = vService[0];
242 244310 : return true;
243 244317 : }
244 :
245 : /**
246 : * Resolve a service string with a numeric IP to its first corresponding
247 : * service.
248 : *
249 : * @returns The resulting CService if the resolution was successful, [::]:0
250 : * otherwise.
251 : *
252 : * @see Lookup(const char *, CService&, int, bool) for additional parameter
253 : * descriptions.
254 : */
255 237172 : CService LookupNumeric(const std::string& name, int portDefault)
256 : {
257 237172 : if (!ValidAsCString(name)) {
258 0 : return {};
259 : }
260 237172 : CService addr;
261 : // "1.2:345" will fail to resolve the ip, but will still set the port.
262 : // If the ip fails to resolve, re-init the result.
263 237172 : if(!Lookup(name, addr, portDefault, false))
264 3 : addr = CService();
265 237172 : return addr;
266 237172 : }
267 :
268 275 : struct timeval MillisToTimeval(int64_t nTimeout)
269 : {
270 : struct timeval timeout;
271 275 : timeout.tv_sec = nTimeout / 1000;
272 275 : timeout.tv_usec = (nTimeout % 1000) * 1000;
273 275 : return timeout;
274 : }
275 :
276 : /** SOCKS version */
277 : enum SOCKSVersion: uint8_t {
278 : SOCKS4 = 0x04,
279 : SOCKS5 = 0x05
280 : };
281 :
282 : /** Values defined for METHOD in RFC1928 */
283 : enum SOCKS5Method: uint8_t {
284 : NOAUTH = 0x00, //!< No authentication required
285 : GSSAPI = 0x01, //!< GSSAPI
286 : USER_PASS = 0x02, //!< Username/password
287 : NO_ACCEPTABLE = 0xff, //!< No acceptable methods
288 : };
289 :
290 : /** Values defined for CMD in RFC1928 */
291 : enum SOCKS5Command: uint8_t {
292 : CONNECT = 0x01,
293 : BIND = 0x02,
294 : UDP_ASSOCIATE = 0x03
295 : };
296 :
297 : /** Values defined for REP in RFC1928 */
298 : enum SOCKS5Reply: uint8_t {
299 : SUCCEEDED = 0x00, //!< Succeeded
300 : GENFAILURE = 0x01, //!< General failure
301 : NOTALLOWED = 0x02, //!< Connection not allowed by ruleset
302 : NETUNREACHABLE = 0x03, //!< Network unreachable
303 : HOSTUNREACHABLE = 0x04, //!< Network unreachable
304 : CONNREFUSED = 0x05, //!< Connection refused
305 : TTLEXPIRED = 0x06, //!< TTL expired
306 : CMDUNSUPPORTED = 0x07, //!< Command not supported
307 : ATYPEUNSUPPORTED = 0x08, //!< Address type not supported
308 : };
309 :
310 : /** Values defined for ATYPE in RFC1928 */
311 : enum SOCKS5Atyp: uint8_t {
312 : IPV4 = 0x01,
313 : DOMAINNAME = 0x03,
314 : IPV6 = 0x04,
315 : };
316 :
317 : /** Status codes that can be returned by InterruptibleRecv */
318 : enum class IntrRecvError {
319 : OK,
320 : Timeout,
321 : Disconnected,
322 : NetworkError,
323 : Interrupted
324 : };
325 :
326 : /**
327 : * Try to read a specified number of bytes from a socket. Please read the "see
328 : * also" section for more detail.
329 : *
330 : * @param data The buffer where the read bytes should be stored.
331 : * @param len The number of bytes to read into the specified buffer.
332 : * @param timeout The total timeout in milliseconds for this read.
333 : * @param hSocket The socket (has to be in non-blocking mode) from which to read
334 : * bytes.
335 : *
336 : * @returns An IntrRecvError indicating the resulting status of this read.
337 : * IntrRecvError::OK only if all of the specified number of bytes were
338 : * read.
339 : *
340 : * @see This function can be interrupted by calling InterruptSocks5(bool).
341 : * Sockets can be made non-blocking with SetSocketNonBlocking(const
342 : * SOCKET&, bool).
343 : */
344 39 : static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const SOCKET& hSocket)
345 : {
346 99 : int64_t curTime = GetTimeMillis();
347 39 : int64_t endTime = curTime + timeout;
348 : // Maximum time to wait for I/O readiness. It will take up until this time
349 : // (in millis) to break off in case of an interruption.
350 39 : const int64_t maxWait = 1000;
351 99 : while (len > 0 && curTime < endTime) {
352 60 : ssize_t ret = recv(hSocket, (char*)data, len, 0); // Optimistically try the recv first
353 60 : if (ret > 0) {
354 39 : len -= ret;
355 39 : data += ret;
356 60 : } else if (ret == 0) { // Unexpected disconnection
357 0 : return IntrRecvError::Disconnected;
358 : } else { // Other error or blocking
359 21 : int nErr = WSAGetLastError();
360 21 : if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
361 21 : if (!IsSelectableSocket(hSocket)) {
362 0 : return IntrRecvError::NetworkError;
363 : }
364 : // Only wait at most maxWait milliseconds at a time, unless
365 : // we're approaching the end of the specified total timeout
366 21 : int timeout_ms = std::min(endTime - curTime, maxWait);
367 : #ifdef USE_POLL
368 : struct pollfd pollfd = {};
369 : pollfd.fd = hSocket;
370 : pollfd.events = POLLIN;
371 : int nRet = poll(&pollfd, 1, timeout_ms);
372 : #else
373 21 : struct timeval tval = MillisToTimeval(timeout_ms);
374 21 : fd_set fdset;
375 21 : FD_ZERO(&fdset);
376 21 : FD_SET(hSocket, &fdset);
377 21 : int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval);
378 : #endif
379 21 : if (nRet == SOCKET_ERROR) {
380 0 : return IntrRecvError::NetworkError;
381 : }
382 21 : } else {
383 0 : return IntrRecvError::NetworkError;
384 : }
385 21 : }
386 60 : if (interruptSocks5Recv)
387 0 : return IntrRecvError::Interrupted;
388 60 : curTime = GetTimeMillis();
389 60 : }
390 39 : return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
391 39 : }
392 :
393 : /** Credentials for proxy authentication */
394 24 : struct ProxyCredentials
395 : {
396 : std::string username;
397 : std::string password;
398 : };
399 :
400 : /** Convert SOCKS5 reply to an error message */
401 0 : static std::string Socks5ErrorString(uint8_t err)
402 : {
403 0 : switch(err) {
404 : case SOCKS5Reply::GENFAILURE:
405 0 : return "general failure";
406 : case SOCKS5Reply::NOTALLOWED:
407 0 : return "connection not allowed";
408 : case SOCKS5Reply::NETUNREACHABLE:
409 0 : return "network unreachable";
410 : case SOCKS5Reply::HOSTUNREACHABLE:
411 0 : return "host unreachable";
412 : case SOCKS5Reply::CONNREFUSED:
413 0 : return "connection refused";
414 : case SOCKS5Reply::TTLEXPIRED:
415 0 : return "TTL expired";
416 : case SOCKS5Reply::CMDUNSUPPORTED:
417 0 : return "protocol error";
418 : case SOCKS5Reply::ATYPEUNSUPPORTED:
419 0 : return "address type not supported";
420 : default:
421 0 : return "unknown";
422 : }
423 0 : }
424 :
425 : /**
426 : * Connect to a specified destination service through an already connected
427 : * SOCKS5 proxy.
428 : *
429 : * @param strDest The destination fully-qualified domain name.
430 : * @param port The destination port.
431 : * @param auth The credentials with which to authenticate with the specified
432 : * SOCKS5 proxy.
433 : * @param hSocket The SOCKS5 proxy socket.
434 : *
435 : * @returns Whether or not the operation succeeded.
436 : *
437 : * @note The specified SOCKS5 proxy socket must already be connected to the
438 : * SOCKS5 proxy.
439 : *
440 : * @see <a href="https://www.ietf.org/rfc/rfc1928.txt">RFC1928: SOCKS Protocol
441 : * Version 5</a>
442 : */
443 9 : static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, const SOCKET& hSocket)
444 : {
445 : IntrRecvError recvr;
446 9 : LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
447 9 : if (strDest.size() > 255) {
448 0 : return error("Hostname too long");
449 : }
450 : // Construct the version identifier/method selection message
451 9 : std::vector<uint8_t> vSocks5Init;
452 9 : vSocks5Init.push_back(SOCKSVersion::SOCKS5); // We want the SOCK5 protocol
453 9 : if (auth) {
454 6 : vSocks5Init.push_back(0x02); // 2 method identifiers follow...
455 6 : vSocks5Init.push_back(SOCKS5Method::NOAUTH);
456 6 : vSocks5Init.push_back(SOCKS5Method::USER_PASS);
457 6 : } else {
458 3 : vSocks5Init.push_back(0x01); // 1 method identifier follows...
459 3 : vSocks5Init.push_back(SOCKS5Method::NOAUTH);
460 : }
461 9 : ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
462 9 : if (ret != (ssize_t)vSocks5Init.size()) {
463 0 : return error("Error sending to proxy");
464 : }
465 9 : uint8_t pchRet1[2];
466 9 : if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
467 0 : LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
468 0 : return false;
469 : }
470 9 : if (pchRet1[0] != SOCKSVersion::SOCKS5) {
471 0 : return error("Proxy failed to initialize");
472 : }
473 9 : if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
474 : // Perform username/password authentication (as described in RFC1929)
475 3 : std::vector<uint8_t> vAuth;
476 3 : vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation
477 3 : if (auth->username.size() > 255 || auth->password.size() > 255)
478 0 : return error("Proxy username or password too long");
479 3 : vAuth.push_back(auth->username.size());
480 3 : vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
481 3 : vAuth.push_back(auth->password.size());
482 3 : vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
483 3 : ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
484 3 : if (ret != (ssize_t)vAuth.size()) {
485 0 : return error("Error sending authentication to proxy");
486 : }
487 3 : LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
488 3 : uint8_t pchRetA[2];
489 3 : if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
490 0 : return error("Error reading proxy authentication response");
491 : }
492 3 : if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
493 0 : return error("Proxy authentication unsuccessful");
494 : }
495 9 : } else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
496 : // Perform no authentication
497 : } else {
498 0 : return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
499 : }
500 9 : std::vector<uint8_t> vSocks5;
501 9 : vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version
502 9 : vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT
503 9 : vSocks5.push_back(0x00); // RSV Reserved must be 0
504 9 : vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME
505 9 : vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
506 9 : vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
507 9 : vSocks5.push_back((port >> 8) & 0xFF);
508 9 : vSocks5.push_back((port >> 0) & 0xFF);
509 9 : ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
510 9 : if (ret != (ssize_t)vSocks5.size()) {
511 0 : return error("Error sending to proxy");
512 : }
513 9 : uint8_t pchRet2[4];
514 9 : if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
515 0 : if (recvr == IntrRecvError::Timeout) {
516 : /* If a timeout happens here, this effectively means we timed out while connecting
517 : * to the remote node. This is very common for Tor, so do not print an
518 : * error message. */
519 0 : return false;
520 : } else {
521 0 : return error("Error while reading proxy response");
522 : }
523 : }
524 9 : if (pchRet2[0] != SOCKSVersion::SOCKS5) {
525 0 : return error("Proxy failed to accept request");
526 : }
527 9 : if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
528 : // Failures to connect to a peer that are not proxy errors
529 0 : LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
530 0 : return false;
531 : }
532 9 : if (pchRet2[2] != 0x00) { // Reserved field must be 0
533 0 : return error("Error: malformed proxy response");
534 : }
535 9 : uint8_t pchRet3[256];
536 9 : switch (pchRet2[3])
537 : {
538 9 : case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
539 0 : case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
540 : case SOCKS5Atyp::DOMAINNAME:
541 : {
542 0 : recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
543 0 : if (recvr != IntrRecvError::OK) {
544 0 : return error("Error reading from proxy");
545 : }
546 0 : int nRecv = pchRet3[0];
547 0 : recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
548 : break;
549 0 : }
550 0 : default: return error("Error: malformed proxy response");
551 : }
552 9 : if (recvr != IntrRecvError::OK) {
553 0 : return error("Error reading from proxy");
554 : }
555 9 : if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
556 0 : return error("Error reading from proxy");
557 : }
558 9 : LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
559 9 : return true;
560 9 : }
561 :
562 : /**
563 : * Try to create a socket file descriptor with specific properties in the
564 : * communications domain (address family) of the specified service.
565 : *
566 : * For details on the desired properties, see the inline comments in the source
567 : * code.
568 : */
569 748 : SOCKET CreateSocket(const CService &addrConnect)
570 : {
571 : // Create a sockaddr from the specified service.
572 748 : struct sockaddr_storage sockaddr;
573 748 : socklen_t len = sizeof(sockaddr);
574 748 : if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
575 0 : LogPrintf("Cannot create socket for %s: unsupported network\n", addrConnect.ToString());
576 0 : return INVALID_SOCKET;
577 : }
578 :
579 : // Create a TCP socket in the address family of the specified service.
580 748 : SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
581 748 : if (hSocket == INVALID_SOCKET)
582 0 : return INVALID_SOCKET;
583 :
584 : // Ensure that waiting for I/O on this socket won't result in undefined
585 : // behavior.
586 748 : if (!IsSelectableSocket(hSocket)) {
587 0 : CloseSocket(hSocket);
588 0 : LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
589 0 : return INVALID_SOCKET;
590 : }
591 :
592 : #ifdef SO_NOSIGPIPE
593 748 : int set = 1;
594 : // Set the no-sigpipe option on the socket for BSD systems, other UNIXes
595 : // should use the MSG_NOSIGNAL flag for every send.
596 748 : setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
597 : #endif
598 :
599 : // Set the no-delay option (disable Nagle's algorithm) on the TCP socket.
600 748 : SetSocketNoDelay(hSocket);
601 :
602 : // Set the non-blocking option on the socket.
603 748 : if (!SetSocketNonBlocking(hSocket, true)) {
604 0 : CloseSocket(hSocket);
605 0 : LogPrintf("CreateSocket: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
606 0 : }
607 748 : return hSocket;
608 748 : }
609 :
610 : template<typename... Args>
611 3 : static void LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args) {
612 3 : std::string error_message = tfm::format(fmt, args...);
613 3 : if (manual_connection) {
614 1 : LogPrintf("%s\n", error_message);
615 : } else {
616 2 : LogPrint(BCLog::NET, "%s\n", error_message);
617 : }
618 3 : }
619 :
620 : /**
621 : * Try to connect to the specified service on the specified socket.
622 : *
623 : * @param addrConnect The service to which to connect.
624 : * @param hSocket The socket on which to connect.
625 : * @param nTimeout Wait this many milliseconds for the connection to be
626 : * established.
627 : * @param manual_connection Whether or not the connection was manually requested
628 : * (e.g. through the addnode RPC)
629 : *
630 : * @returns Whether or not a connection was successfully made.
631 : */
632 255 : bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, int nTimeout, bool manual_connection)
633 : {
634 : // Create a sockaddr from the specified service.
635 255 : struct sockaddr_storage sockaddr;
636 255 : socklen_t len = sizeof(sockaddr);
637 255 : if (hSocket == INVALID_SOCKET) {
638 0 : LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString());
639 0 : return false;
640 : }
641 255 : if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
642 0 : LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
643 0 : return false;
644 : }
645 :
646 : // Connect to the addrConnect service on the hSocket socket.
647 255 : if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
648 : {
649 255 : int nErr = WSAGetLastError();
650 : // WSAEINVAL is here because some legacy version of winsock uses it
651 255 : if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
652 : {
653 : // Connection didn't actually fail, but is being established
654 : // asynchronously. Thus, use async I/O api (select/poll)
655 : // synchronously to check for successful connection with a timeout.
656 : #ifdef USE_POLL
657 : struct pollfd pollfd = {};
658 : pollfd.fd = hSocket;
659 : pollfd.events = POLLIN | POLLOUT;
660 : int nRet = poll(&pollfd, 1, nTimeout);
661 : #else
662 254 : struct timeval timeout = MillisToTimeval(nTimeout);
663 254 : fd_set fdset;
664 254 : FD_ZERO(&fdset);
665 254 : FD_SET(hSocket, &fdset);
666 254 : int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
667 : #endif
668 : // Upon successful completion, both select and poll return the total
669 : // number of file descriptors that have been selected. A value of 0
670 : // indicates that the call timed out and no file descriptors have
671 : // been selected.
672 254 : if (nRet == 0)
673 : {
674 4 : LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
675 4 : return false;
676 : }
677 250 : if (nRet == SOCKET_ERROR)
678 : {
679 0 : LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
680 0 : return false;
681 : }
682 :
683 : // Even if the select/poll was successful, the connect might not
684 : // have been successful. The reason for this failure is hidden away
685 : // in the SO_ERROR for the socket in modern systems. We read it into
686 : // nRet here.
687 250 : socklen_t nRetSize = sizeof(nRet);
688 250 : if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (sockopt_arg_type)&nRet, &nRetSize) == SOCKET_ERROR)
689 : {
690 0 : LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
691 0 : return false;
692 : }
693 250 : if (nRet != 0)
694 : {
695 2 : LogConnectFailure(manual_connection, "connect() to %s failed after select(): %s", addrConnect.ToString(), NetworkErrorString(nRet));
696 2 : return false;
697 : }
698 254 : }
699 : #ifdef WIN32
700 : else if (WSAGetLastError() != WSAEISCONN)
701 : #else
702 : else
703 : #endif
704 : {
705 1 : LogConnectFailure(manual_connection, "connect() to %s failed: %s", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
706 1 : return false;
707 : }
708 248 : }
709 248 : return true;
710 255 : }
711 :
712 10 : bool SetProxy(enum Network net, const proxyType &addrProxy) {
713 10 : assert(net >= 0 && net < NET_MAX);
714 10 : if (!addrProxy.IsValid())
715 0 : return false;
716 10 : LOCK(g_proxyinfo_mutex);
717 10 : proxyInfo[net] = addrProxy;
718 : return true;
719 10 : }
720 :
721 384 : bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
722 384 : assert(net >= 0 && net < NET_MAX);
723 384 : LOCK(g_proxyinfo_mutex);
724 384 : if (!proxyInfo[net].IsValid())
725 369 : return false;
726 15 : proxyInfoOut = proxyInfo[net];
727 15 : return true;
728 384 : }
729 :
730 : /**
731 : * Set the name proxy to use for all connections to nodes specified by a
732 : * hostname. After setting this proxy, connecting to a node specified by a
733 : * hostname won't result in a local lookup of said hostname, rather, connect to
734 : * the node by asking the name proxy for a proxy connection to the hostname,
735 : * effectively delegating the hostname lookup to the specified proxy.
736 : *
737 : * This delegation increases privacy for those who set the name proxy as they no
738 : * longer leak their external hostname queries to their DNS servers.
739 : *
740 : * @returns Whether or not the operation succeeded.
741 : *
742 : * @note SOCKS5's support for UDP-over-SOCKS5 has been considered, but no SOCK5
743 : * server in common use (most notably Tor) actually implements UDP
744 : * support, and a DNS resolver is beyond the scope of this project.
745 : */
746 3 : bool SetNameProxy(const proxyType &addrProxy) {
747 3 : if (!addrProxy.IsValid())
748 0 : return false;
749 3 : LOCK(g_proxyinfo_mutex);
750 3 : nameProxy = addrProxy;
751 : return true;
752 3 : }
753 :
754 4 : bool GetNameProxy(proxyType &nameProxyOut) {
755 4 : LOCK(g_proxyinfo_mutex);
756 4 : if(!nameProxy.IsValid())
757 1 : return false;
758 3 : nameProxyOut = nameProxy;
759 3 : return true;
760 4 : }
761 :
762 250 : bool HaveNameProxy() {
763 250 : LOCK(g_proxyinfo_mutex);
764 250 : return nameProxy.IsValid();
765 250 : }
766 :
767 16 : bool IsProxy(const CNetAddr &addr) {
768 16 : LOCK(g_proxyinfo_mutex);
769 96 : for (int i = 0; i < NET_MAX; i++) {
770 80 : if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy))
771 0 : return true;
772 : }
773 16 : return false;
774 16 : }
775 :
776 : /**
777 : * Connect to a specified destination service through a SOCKS5 proxy by first
778 : * connecting to the SOCKS5 proxy.
779 : *
780 : * @param proxy The SOCKS5 proxy.
781 : * @param strDest The destination service to which to connect.
782 : * @param port The destination port.
783 : * @param hSocket The socket on which to connect to the SOCKS5 proxy.
784 : * @param nTimeout Wait this many milliseconds for the connection to the SOCKS5
785 : * proxy to be established.
786 : * @param[out] outProxyConnectionFailed Whether or not the connection to the
787 : * SOCKS5 proxy failed.
788 : *
789 : * @returns Whether or not the operation succeeded.
790 : */
791 9 : bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, const SOCKET& hSocket, int nTimeout, bool& outProxyConnectionFailed)
792 : {
793 : // first connect to proxy server
794 9 : if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout, true)) {
795 0 : outProxyConnectionFailed = true;
796 0 : return false;
797 : }
798 : // do socks negotiation
799 9 : if (proxy.randomize_credentials) {
800 6 : ProxyCredentials random_auth;
801 : static std::atomic_int counter(0);
802 6 : random_auth.username = random_auth.password = strprintf("%i", counter++);
803 6 : if (!Socks5(strDest, (uint16_t)port, &random_auth, hSocket)) {
804 0 : return false;
805 : }
806 6 : } else {
807 3 : if (!Socks5(strDest, (uint16_t)port, 0, hSocket)) {
808 0 : return false;
809 : }
810 : }
811 9 : return true;
812 9 : }
813 :
814 : /**
815 : * Parse and resolve a specified subnet string into the appropriate internal
816 : * representation.
817 : *
818 : * @param strSubnet A string representation of a subnet of the form `network
819 : * address [ "/", ( CIDR-style suffix | netmask ) ]`(e.g.
820 : * `2001:db8::/32`, `192.0.2.0/255.255.255.0`, or `8.8.8.8`).
821 : * @param ret The resulting internal representation of a subnet.
822 : *
823 : * @returns Whether the operation succeeded or not.
824 : */
825 161 : bool LookupSubNet(const std::string& strSubnet, CSubNet& ret)
826 : {
827 161 : if (!ValidAsCString(strSubnet)) {
828 6 : return false;
829 : }
830 155 : size_t slash = strSubnet.find_last_of('/');
831 155 : std::vector<CNetAddr> vIP;
832 :
833 155 : std::string strAddress = strSubnet.substr(0, slash);
834 : // TODO: Use LookupHost(const std::string&, CNetAddr&, bool) instead to just get
835 : // one CNetAddr.
836 155 : if (LookupHost(strAddress, vIP, 1, false))
837 : {
838 149 : CNetAddr network = vIP[0];
839 149 : if (slash != strSubnet.npos)
840 : {
841 83 : std::string strNetmask = strSubnet.substr(slash + 1);
842 83 : uint8_t n;
843 83 : if (ParseUInt8(strNetmask, &n)) {
844 : // If valid number, assume CIDR variable-length subnet masking
845 37 : ret = CSubNet(network, n);
846 37 : return ret.IsValid();
847 : }
848 : else // If not a valid number, try full netmask syntax
849 : {
850 : // Never allow lookup for netmask
851 46 : if (LookupHost(strNetmask, vIP, 1, false)) {
852 44 : ret = CSubNet(network, vIP[0]);
853 44 : return ret.IsValid();
854 : }
855 : }
856 83 : }
857 : else
858 : {
859 66 : ret = CSubNet(network);
860 66 : return ret.IsValid();
861 : }
862 149 : }
863 8 : return false;
864 161 : }
865 :
866 : #ifdef WIN32
867 : std::string NetworkErrorString(int err)
868 : {
869 : wchar_t buf[256];
870 : buf[0] = 0;
871 : if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
872 : nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
873 : buf, ARRAYSIZE(buf), nullptr))
874 : {
875 : return strprintf("%s (%d)", std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf), err);
876 : }
877 : else
878 : {
879 : return strprintf("Unknown error (%d)", err);
880 : }
881 : }
882 : #else
883 16 : std::string NetworkErrorString(int err)
884 : {
885 16 : char buf[256];
886 16 : buf[0] = 0;
887 : /* Too bad there are two incompatible implementations of the
888 : * thread-safe strerror. */
889 16 : const char *s;
890 : #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
891 : s = strerror_r(err, buf, sizeof(buf));
892 : #else /* POSIX variant always returns message in buffer */
893 16 : s = buf;
894 16 : if (strerror_r(err, buf, sizeof(buf)))
895 0 : buf[0] = 0;
896 : #endif
897 16 : return strprintf("%s (%d)", s, err);
898 16 : }
899 : #endif
900 :
901 1944 : bool CloseSocket(SOCKET& hSocket)
902 : {
903 1944 : if (hSocket == INVALID_SOCKET)
904 730 : return false;
905 : #ifdef WIN32
906 : int ret = closesocket(hSocket);
907 : #else
908 1214 : int ret = close(hSocket);
909 : #endif
910 1214 : if (ret) {
911 0 : LogPrintf("Socket close failed: %d. Error: %s\n", hSocket, NetworkErrorString(WSAGetLastError()));
912 0 : }
913 1214 : hSocket = INVALID_SOCKET;
914 1214 : return ret != SOCKET_ERROR;
915 1944 : }
916 :
917 748 : bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking)
918 : {
919 748 : if (fNonBlocking) {
920 : #ifdef WIN32
921 : u_long nOne = 1;
922 : if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
923 : #else
924 748 : int fFlags = fcntl(hSocket, F_GETFL, 0);
925 748 : if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
926 : #endif
927 0 : return false;
928 : }
929 748 : } else {
930 : #ifdef WIN32
931 : u_long nZero = 0;
932 : if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
933 : #else
934 0 : int fFlags = fcntl(hSocket, F_GETFL, 0);
935 0 : if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
936 : #endif
937 0 : return false;
938 : }
939 0 : }
940 :
941 748 : return true;
942 748 : }
943 :
944 1214 : bool SetSocketNoDelay(const SOCKET& hSocket)
945 : {
946 1214 : int set = 1;
947 1214 : int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
948 2428 : return rc == 0;
949 1214 : }
950 :
951 1609 : void InterruptSocks5(bool interrupt)
952 : {
953 1609 : interruptSocks5Recv = interrupt;
954 1609 : }
|