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