1 /* 2 * Copyright (c) 2013-2020, The PurpleI2P Project 3 * 4 * This file is part of Purple i2pd project and licensed under BSD3 5 * 6 * See full license text in LICENSE file at top of project tree 7 */ 8 9 #include <cstring> 10 #include <cassert> 11 #include <string> 12 #include <atomic> 13 #include "SOCKS.h" 14 #include "Identity.h" 15 #include "Streaming.h" 16 #include "Destination.h" 17 #include "ClientContext.h" 18 #include "I2PEndian.h" 19 #include "I2PTunnel.h" 20 #include "I2PService.h" 21 #include "util.h" 22 23 namespace i2p 24 { 25 namespace proxy 26 { 27 static const size_t socks_buffer_size = 8192; 28 static const size_t max_socks_hostname_size = 255; // Limit for socks5 and bad idea to traverse 29 30 static const size_t SOCKS_FORWARDER_BUFFER_SIZE = 8192; 31 32 static const size_t SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE = 8; 33 34 struct SOCKSDnsAddress 35 { 36 uint8_t size; 37 char value[max_socks_hostname_size]; FromStringi2p::proxy::SOCKSDnsAddress38 void FromString (const std::string& str) 39 { 40 size = str.length(); 41 if (str.length() > max_socks_hostname_size) size = max_socks_hostname_size; 42 memcpy(value,str.c_str(),size); 43 } ToStringi2p::proxy::SOCKSDnsAddress44 std::string ToString() { return std::string(value, size); } push_backi2p::proxy::SOCKSDnsAddress45 void push_back (char c) { value[size++] = c; } 46 }; 47 48 class SOCKSServer; 49 class SOCKSHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this<SOCKSHandler> 50 { 51 private: 52 53 enum state 54 { 55 GET_SOCKSV, 56 GET_COMMAND, 57 GET_PORT, 58 GET_IPV4, 59 GET4_IDENT, 60 GET4A_HOST, 61 GET5_AUTHNUM, 62 GET5_AUTH, 63 GET5_REQUESTV, 64 GET5_GETRSV, 65 GET5_GETADDRTYPE, 66 GET5_IPV6, 67 GET5_HOST_SIZE, 68 GET5_HOST, 69 READY, 70 UPSTREAM_RESOLVE, 71 UPSTREAM_CONNECT, 72 UPSTREAM_HANDSHAKE 73 }; 74 enum authMethods 75 { 76 AUTH_NONE = 0, //No authentication, skip to next step 77 AUTH_GSSAPI = 1, //GSSAPI authentication 78 AUTH_USERPASSWD = 2, //Username and password 79 AUTH_UNACCEPTABLE = 0xff //No acceptable method found 80 }; 81 enum addrTypes 82 { 83 ADDR_IPV4 = 1, //IPv4 address (4 octets) 84 ADDR_DNS = 3, // DNS name (up to 255 octets) 85 ADDR_IPV6 = 4 //IPV6 address (16 octets) 86 }; 87 enum errTypes 88 { 89 SOCKS5_OK = 0, // No error for SOCKS5 90 SOCKS5_GEN_FAIL = 1, // General server failure 91 SOCKS5_RULE_DENIED = 2, // Connection disallowed by ruleset 92 SOCKS5_NET_UNREACH = 3, // Network unreachable 93 SOCKS5_HOST_UNREACH = 4, // Host unreachable 94 SOCKS5_CONN_REFUSED = 5, // Connection refused by the peer 95 SOCKS5_TTL_EXPIRED = 6, // TTL Expired 96 SOCKS5_CMD_UNSUP = 7, // Command unsupported 97 SOCKS5_ADDR_UNSUP = 8, // Address type unsupported 98 SOCKS4_OK = 90, // No error for SOCKS4 99 SOCKS4_FAIL = 91, // Failed establishing connecting or not allowed 100 SOCKS4_IDENTD_MISSING = 92, // Couldn't connect to the identd server 101 SOCKS4_IDENTD_DIFFER = 93 // The ID reported by the application and by identd differ 102 }; 103 enum cmdTypes 104 { 105 CMD_CONNECT = 1, // TCP Connect 106 CMD_BIND = 2, // TCP Bind 107 CMD_UDP = 3 // UDP associate 108 }; 109 enum socksVersions 110 { 111 SOCKS4 = 4, // SOCKS4 112 SOCKS5 = 5 // SOCKS5 113 }; 114 union address 115 { 116 uint32_t ip; 117 SOCKSDnsAddress dns; 118 uint8_t ipv6[16]; 119 }; 120 121 void EnterState(state nstate, uint8_t parseleft = 1); 122 bool HandleData(uint8_t *sock_buff, std::size_t len); 123 bool ValidateSOCKSRequest(); 124 void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); 125 void Terminate(); 126 void AsyncSockRead(); 127 boost::asio::const_buffers_1 GenerateSOCKS5SelectAuth(authMethods method); 128 boost::asio::const_buffers_1 GenerateSOCKS4Response(errTypes error, uint32_t ip, uint16_t port); 129 boost::asio::const_buffers_1 GenerateSOCKS5Response(errTypes error, addrTypes type, const address &addr, uint16_t port); 130 boost::asio::const_buffers_1 GenerateUpstreamRequest(); 131 bool Socks5ChooseAuth(); 132 void SocksRequestFailed(errTypes error); 133 void SocksRequestSuccess(); 134 void SentSocksFailed(const boost::system::error_code & ecode); 135 void SentSocksDone(const boost::system::error_code & ecode); 136 void SentSocksResponse(const boost::system::error_code & ecode); 137 void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream); 138 void ForwardSOCKS(); 139 140 void SocksUpstreamSuccess(); 141 void AsyncUpstreamSockRead(); 142 void SendUpstreamRequest(); 143 void HandleUpstreamData(uint8_t * buff, std::size_t len); 144 void HandleUpstreamSockSend(const boost::system::error_code & ecode, std::size_t bytes_transfered); 145 void HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); 146 void HandleUpstreamConnected(const boost::system::error_code & ecode, 147 boost::asio::ip::tcp::resolver::iterator itr); 148 void HandleUpstreamResolved(const boost::system::error_code & ecode, 149 boost::asio::ip::tcp::resolver::iterator itr); 150 151 boost::asio::ip::tcp::resolver m_proxy_resolver; 152 uint8_t m_sock_buff[socks_buffer_size]; 153 std::shared_ptr<boost::asio::ip::tcp::socket> m_sock, m_upstreamSock; 154 std::shared_ptr<i2p::stream::Stream> m_stream; 155 uint8_t *m_remaining_data; //Data left to be sent 156 uint8_t *m_remaining_upstream_data; //upstream data left to be forwarded 157 uint8_t m_response[7+max_socks_hostname_size]; 158 uint8_t m_upstream_response[SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE]; 159 uint8_t m_upstream_request[14+max_socks_hostname_size]; 160 std::size_t m_upstream_response_len; 161 address m_address; //Address 162 std::size_t m_remaining_data_len; //Size of the data left to be sent 163 uint32_t m_4aip; //Used in 4a requests 164 uint16_t m_port; 165 uint8_t m_command; 166 uint8_t m_parseleft; //Octets left to parse 167 authMethods m_authchosen; //Authentication chosen 168 addrTypes m_addrtype; //Address type chosen 169 socksVersions m_socksv; //Socks version 170 cmdTypes m_cmd; // Command requested 171 state m_state; 172 const bool m_UseUpstreamProxy; // do we want to use the upstream proxy for non i2p addresses? 173 const std::string m_UpstreamProxyAddress; 174 const uint16_t m_UpstreamProxyPort; 175 176 public: 177 SOCKSHandler(SOCKSServer * parent,std::shared_ptr<boost::asio::ip::tcp::socket> sock,const std::string & upstreamAddr,const uint16_t upstreamPort,const bool useUpstream)178 SOCKSHandler(SOCKSServer * parent, std::shared_ptr<boost::asio::ip::tcp::socket> sock, const std::string & upstreamAddr, const uint16_t upstreamPort, const bool useUpstream) : 179 I2PServiceHandler(parent), 180 m_proxy_resolver(parent->GetService()), 181 m_sock(sock), m_stream(nullptr), 182 m_authchosen(AUTH_UNACCEPTABLE), m_addrtype(ADDR_IPV4), 183 m_UseUpstreamProxy(useUpstream), 184 m_UpstreamProxyAddress(upstreamAddr), 185 m_UpstreamProxyPort(upstreamPort) 186 { m_address.ip = 0; EnterState(GET_SOCKSV); } 187 ~SOCKSHandler()188 ~SOCKSHandler() { Terminate(); } Handle()189 void Handle() { AsyncSockRead(); } 190 }; 191 AsyncSockRead()192 void SOCKSHandler::AsyncSockRead() 193 { 194 LogPrint(eLogDebug, "SOCKS: Async sock read"); 195 if (m_sock) { 196 m_sock->async_receive(boost::asio::buffer(m_sock_buff, socks_buffer_size), 197 std::bind(&SOCKSHandler::HandleSockRecv, shared_from_this(), 198 std::placeholders::_1, std::placeholders::_2)); 199 } else { 200 LogPrint(eLogError,"SOCKS: No socket for read"); 201 } 202 } 203 Terminate()204 void SOCKSHandler::Terminate() 205 { 206 if (Kill()) return; 207 if (m_sock) 208 { 209 LogPrint(eLogDebug, "SOCKS: Closing socket"); 210 m_sock->close(); 211 m_sock = nullptr; 212 } 213 if (m_upstreamSock) 214 { 215 LogPrint(eLogDebug, "SOCKS: Closing upstream socket"); 216 m_upstreamSock->close(); 217 m_upstreamSock = nullptr; 218 } 219 if (m_stream) 220 { 221 LogPrint(eLogDebug, "SOCKS: Closing stream"); 222 m_stream.reset (); 223 } 224 Done(shared_from_this()); 225 } 226 GenerateSOCKS4Response(SOCKSHandler::errTypes error,uint32_t ip,uint16_t port)227 boost::asio::const_buffers_1 SOCKSHandler::GenerateSOCKS4Response(SOCKSHandler::errTypes error, uint32_t ip, uint16_t port) 228 { 229 assert(error >= SOCKS4_OK); 230 m_response[0] = '\x00'; // version 231 m_response[1] = error; // response code 232 htobe16buf(m_response + 2, port); // port 233 htobe32buf(m_response + 4, ip); // IP 234 return boost::asio::const_buffers_1(m_response,8); 235 } 236 GenerateSOCKS5Response(SOCKSHandler::errTypes error,SOCKSHandler::addrTypes type,const SOCKSHandler::address & addr,uint16_t port)237 boost::asio::const_buffers_1 SOCKSHandler::GenerateSOCKS5Response(SOCKSHandler::errTypes error, SOCKSHandler::addrTypes type, const SOCKSHandler::address &addr, uint16_t port) 238 { 239 size_t size = 6; // header + port 240 assert(error <= SOCKS5_ADDR_UNSUP); 241 m_response[0] = '\x05'; // version 242 m_response[1] = error; // response code 243 m_response[2] = '\x00'; // reserved 244 m_response[3] = type; // address type 245 switch (type) 246 { 247 case ADDR_IPV4: 248 size += 4; 249 htobe32buf(m_response + 4, addr.ip); 250 htobe16buf(m_response + size - 2, port); 251 break; 252 case ADDR_IPV6: 253 size += 16; 254 memcpy(m_response + 4, addr.ipv6, 16); 255 htobe16buf(m_response + size - 2, port); 256 break; 257 case ADDR_DNS: 258 std::string address(addr.dns.value, addr.dns.size); 259 if(address.substr(addr.dns.size - 4, 4) == ".i2p") // overwrite if requested address inside I2P 260 { 261 m_response[3] = ADDR_IPV4; 262 size += 4; 263 memset(m_response + 4, 0, 6); // six HEX zeros 264 } 265 else 266 { 267 size += (1 + addr.dns.size); /* name length + resolved address */ 268 m_response[4] = addr.dns.size; 269 memcpy(m_response + 5, addr.dns.value, addr.dns.size); 270 htobe16buf(m_response + size - 2, port); 271 } 272 break; 273 } 274 return boost::asio::const_buffers_1(m_response, size); 275 } 276 GenerateUpstreamRequest()277 boost::asio::const_buffers_1 SOCKSHandler::GenerateUpstreamRequest() 278 { 279 size_t upstreamRequestSize = 0; 280 // TODO: negotiate with upstream 281 // SOCKS 4a 282 m_upstream_request[0] = '\x04'; //version 283 m_upstream_request[1] = m_cmd; 284 htobe16buf(m_upstream_request + 2, m_port); 285 m_upstream_request[4] = 0; 286 m_upstream_request[5] = 0; 287 m_upstream_request[6] = 0; 288 m_upstream_request[7] = 1; 289 // user id 290 m_upstream_request[8] = 'i'; 291 m_upstream_request[9] = '2'; 292 m_upstream_request[10] = 'p'; 293 m_upstream_request[11] = 'd'; 294 m_upstream_request[12] = 0; 295 upstreamRequestSize += 13; 296 if (m_address.dns.size <= max_socks_hostname_size - ( upstreamRequestSize + 1) ) { 297 // bounds check okay 298 memcpy(m_upstream_request + upstreamRequestSize, m_address.dns.value, m_address.dns.size); 299 upstreamRequestSize += m_address.dns.size; 300 // null terminate 301 m_upstream_request[++upstreamRequestSize] = 0; 302 } else { 303 LogPrint(eLogError, "SOCKS: BUG!!! m_addr.dns.sizs > max_socks_hostname - ( upstreamRequestSize + 1 ) )"); 304 } 305 return boost::asio::const_buffers_1(m_upstream_request, upstreamRequestSize); 306 } 307 Socks5ChooseAuth()308 bool SOCKSHandler::Socks5ChooseAuth() 309 { 310 m_response[0] = '\x05'; // Version 311 m_response[1] = m_authchosen; // Response code 312 boost::asio::const_buffers_1 response(m_response, 2); 313 if (m_authchosen == AUTH_UNACCEPTABLE) 314 { 315 LogPrint(eLogWarning, "SOCKS: v5 authentication negotiation failed"); 316 boost::asio::async_write(*m_sock, response, std::bind(&SOCKSHandler::SentSocksFailed, shared_from_this(), std::placeholders::_1)); 317 return false; 318 } 319 else 320 { 321 LogPrint(eLogDebug, "SOCKS: v5 choosing authentication method: ", m_authchosen); 322 boost::asio::async_write(*m_sock, response, std::bind(&SOCKSHandler::SentSocksResponse, shared_from_this(), std::placeholders::_1)); 323 return true; 324 } 325 } 326 327 /* All hope is lost beyond this point */ SocksRequestFailed(SOCKSHandler::errTypes error)328 void SOCKSHandler::SocksRequestFailed(SOCKSHandler::errTypes error) 329 { 330 boost::asio::const_buffers_1 response(nullptr,0); 331 assert(error != SOCKS4_OK && error != SOCKS5_OK); 332 switch (m_socksv) 333 { 334 case SOCKS4: 335 LogPrint(eLogWarning, "SOCKS: v4 request failed: ", error); 336 if (error < SOCKS4_OK) error = SOCKS4_FAIL; // Transparently map SOCKS5 errors 337 response = GenerateSOCKS4Response(error, m_4aip, m_port); 338 break; 339 case SOCKS5: 340 LogPrint(eLogWarning, "SOCKS: v5 request failed: ", error); 341 response = GenerateSOCKS5Response(error, m_addrtype, m_address, m_port); 342 break; 343 } 344 boost::asio::async_write(*m_sock, response, std::bind(&SOCKSHandler::SentSocksFailed, 345 shared_from_this(), std::placeholders::_1)); 346 } 347 SocksRequestSuccess()348 void SOCKSHandler::SocksRequestSuccess() 349 { 350 boost::asio::const_buffers_1 response(nullptr,0); 351 // TODO: this should depend on things like the command type and callbacks may change 352 switch (m_socksv) 353 { 354 case SOCKS4: 355 LogPrint(eLogInfo, "SOCKS: v4 connection success"); 356 response = GenerateSOCKS4Response(SOCKS4_OK, m_4aip, m_port); 357 break; 358 case SOCKS5: 359 LogPrint(eLogInfo, "SOCKS: v5 connection success"); 360 auto s = i2p::client::context.GetAddressBook().ToAddress(GetOwner()->GetLocalDestination()->GetIdentHash()); 361 address ad; ad.dns.FromString(s); 362 // HACK only 16 bits passed in port as SOCKS5 doesn't allow for more 363 response = GenerateSOCKS5Response(SOCKS5_OK, ADDR_DNS, ad, m_stream->GetRecvStreamID()); 364 break; 365 } 366 boost::asio::async_write(*m_sock, response, std::bind(&SOCKSHandler::SentSocksDone, shared_from_this(), std::placeholders::_1)); 367 } 368 EnterState(SOCKSHandler::state nstate,uint8_t parseleft)369 void SOCKSHandler::EnterState(SOCKSHandler::state nstate, uint8_t parseleft) { 370 switch (nstate) 371 { 372 case GET_PORT: parseleft = 2; break; 373 case GET_IPV4: m_addrtype = ADDR_IPV4; m_address.ip = 0; parseleft = 4; break; 374 case GET4_IDENT: m_4aip = m_address.ip; break; 375 case GET4A_HOST: 376 case GET5_HOST: m_addrtype = ADDR_DNS; m_address.dns.size = 0; break; 377 case GET5_IPV6: m_addrtype = ADDR_IPV6; parseleft = 16; break; 378 default:; 379 } 380 m_parseleft = parseleft; 381 m_state = nstate; 382 } 383 ValidateSOCKSRequest()384 bool SOCKSHandler::ValidateSOCKSRequest() 385 { 386 if ( m_cmd != CMD_CONNECT ) 387 { 388 // TODO: we need to support binds and other shit! 389 LogPrint(eLogError, "SOCKS: Unsupported command: ", m_cmd); 390 SocksRequestFailed(SOCKS5_CMD_UNSUP); 391 return false; 392 } 393 // TODO: we may want to support other address types! 394 if ( m_addrtype != ADDR_DNS ) 395 { 396 switch (m_socksv) 397 { 398 case SOCKS5: 399 LogPrint(eLogError, "SOCKS: v5 unsupported address type: ", m_addrtype); 400 break; 401 case SOCKS4: 402 LogPrint(eLogError, "SOCKS: Request with v4a rejected because it's actually SOCKS4"); 403 break; 404 } 405 SocksRequestFailed(SOCKS5_ADDR_UNSUP); 406 return false; 407 } 408 return true; 409 } 410 HandleData(uint8_t * sock_buff,std::size_t len)411 bool SOCKSHandler::HandleData(uint8_t *sock_buff, std::size_t len) 412 { 413 assert(len); // This should always be called with a least a byte left to parse 414 while (len > 0) 415 { 416 switch (m_state) 417 { 418 case GET_SOCKSV: 419 m_socksv = (SOCKSHandler::socksVersions) *sock_buff; 420 switch (*sock_buff) 421 { 422 case SOCKS4: 423 EnterState(GET_COMMAND); //Initialize the parser at the right position 424 break; 425 case SOCKS5: 426 EnterState(GET5_AUTHNUM); //Initialize the parser at the right position 427 break; 428 default: 429 LogPrint(eLogError, "SOCKS: Rejected invalid version: ", ((int)*sock_buff)); 430 Terminate(); 431 return false; 432 } 433 break; 434 case GET5_AUTHNUM: 435 EnterState(GET5_AUTH, *sock_buff); 436 break; 437 case GET5_AUTH: 438 m_parseleft --; 439 if (*sock_buff == AUTH_NONE) 440 m_authchosen = AUTH_NONE; 441 if ( m_parseleft == 0 ) 442 { 443 if (!Socks5ChooseAuth()) return false; 444 EnterState(GET5_REQUESTV); 445 } 446 break; 447 case GET_COMMAND: 448 switch (*sock_buff) 449 { 450 case CMD_CONNECT: 451 case CMD_BIND: 452 break; 453 case CMD_UDP: 454 if (m_socksv == SOCKS5) break; 455 #if (__cplusplus >= 201703L) // C++ 17 or higher 456 [[fallthrough]]; 457 #endif 458 default: 459 LogPrint(eLogError, "SOCKS: Invalid command: ", ((int)*sock_buff)); 460 SocksRequestFailed(SOCKS5_GEN_FAIL); 461 return false; 462 } 463 m_cmd = (SOCKSHandler::cmdTypes)*sock_buff; 464 switch (m_socksv) 465 { 466 case SOCKS5: EnterState(GET5_GETRSV); break; 467 case SOCKS4: EnterState(GET_PORT); break; 468 } 469 break; 470 case GET_PORT: 471 m_port = (m_port << 8)|((uint16_t)*sock_buff); 472 m_parseleft--; 473 if (m_parseleft == 0) 474 { 475 switch (m_socksv) 476 { 477 case SOCKS5: EnterState(READY); break; 478 case SOCKS4: EnterState(GET_IPV4); break; 479 } 480 } 481 break; 482 case GET_IPV4: 483 m_address.ip = (m_address.ip << 8)|((uint32_t)*sock_buff); 484 m_parseleft--; 485 if (m_parseleft == 0) 486 { 487 switch (m_socksv) 488 { 489 case SOCKS5: EnterState(GET_PORT); break; 490 case SOCKS4: EnterState(GET4_IDENT); m_4aip = m_address.ip; break; 491 } 492 } 493 break; 494 case GET4_IDENT: 495 if (!*sock_buff) 496 { 497 if( m_4aip == 0 || m_4aip > 255 ) 498 EnterState(READY); 499 else 500 EnterState(GET4A_HOST); 501 } 502 break; 503 case GET4A_HOST: 504 if (!*sock_buff) 505 { 506 EnterState(READY); 507 break; 508 } 509 if (m_address.dns.size >= max_socks_hostname_size) 510 { 511 LogPrint(eLogError, "SOCKS: v4a req failed: destination is too large"); 512 SocksRequestFailed(SOCKS4_FAIL); 513 return false; 514 } 515 m_address.dns.push_back(*sock_buff); 516 break; 517 case GET5_REQUESTV: 518 if (*sock_buff != SOCKS5) 519 { 520 LogPrint(eLogError,"SOCKS: v5 rejected unknown request version: ", ((int)*sock_buff)); 521 SocksRequestFailed(SOCKS5_GEN_FAIL); 522 return false; 523 } 524 EnterState(GET_COMMAND); 525 break; 526 case GET5_GETRSV: 527 if ( *sock_buff != 0 ) 528 { 529 LogPrint(eLogError, "SOCKS: v5 unknown reserved field: ", ((int)*sock_buff)); 530 SocksRequestFailed(SOCKS5_GEN_FAIL); 531 return false; 532 } 533 EnterState(GET5_GETADDRTYPE); 534 break; 535 case GET5_GETADDRTYPE: 536 switch (*sock_buff) 537 { 538 case ADDR_IPV4: EnterState(GET_IPV4); break; 539 case ADDR_IPV6: EnterState(GET5_IPV6); break; 540 case ADDR_DNS : EnterState(GET5_HOST_SIZE); break; 541 default: 542 LogPrint(eLogError, "SOCKS: v5 unknown address type: ", ((int)*sock_buff)); 543 SocksRequestFailed(SOCKS5_GEN_FAIL); 544 return false; 545 } 546 break; 547 case GET5_IPV6: 548 m_address.ipv6[16-m_parseleft] = *sock_buff; 549 m_parseleft--; 550 if (m_parseleft == 0) EnterState(GET_PORT); 551 break; 552 case GET5_HOST_SIZE: 553 EnterState(GET5_HOST, *sock_buff); 554 break; 555 case GET5_HOST: 556 m_address.dns.push_back(*sock_buff); 557 m_parseleft--; 558 if (m_parseleft == 0) EnterState(GET_PORT); 559 break; 560 default: 561 LogPrint(eLogError, "SOCKS: Parse state?? ", m_state); 562 Terminate(); 563 return false; 564 } 565 sock_buff++; 566 len--; 567 if (m_state == READY) 568 { 569 m_remaining_data_len = len; 570 m_remaining_data = sock_buff; 571 return ValidateSOCKSRequest(); 572 } 573 } 574 return true; 575 } 576 HandleSockRecv(const boost::system::error_code & ecode,std::size_t len)577 void SOCKSHandler::HandleSockRecv(const boost::system::error_code & ecode, std::size_t len) 578 { 579 LogPrint(eLogDebug, "SOCKS: Received ", len, " bytes"); 580 if(ecode) 581 { 582 LogPrint(eLogWarning, "SOCKS: Recv got error: ", ecode); 583 Terminate(); 584 return; 585 } 586 587 if (HandleData(m_sock_buff, len)) 588 { 589 if (m_state == READY) 590 { 591 const std::string addr = m_address.dns.ToString(); 592 LogPrint(eLogInfo, "SOCKS: Requested ", addr, ":" , m_port); 593 const size_t addrlen = addr.size(); 594 // does it end with .i2p? 595 if ( addr.rfind(".i2p") == addrlen - 4) { 596 // yes it does, make an i2p session 597 GetOwner()->CreateStream ( std::bind (&SOCKSHandler::HandleStreamRequestComplete, 598 shared_from_this(), std::placeholders::_1), m_address.dns.ToString(), m_port); 599 } else if (m_UseUpstreamProxy) { 600 // forward it to upstream proxy 601 ForwardSOCKS(); 602 } else { 603 // no upstream proxy 604 SocksRequestFailed(SOCKS5_ADDR_UNSUP); 605 } 606 } 607 else 608 AsyncSockRead(); 609 } 610 } 611 SentSocksFailed(const boost::system::error_code & ecode)612 void SOCKSHandler::SentSocksFailed(const boost::system::error_code & ecode) 613 { 614 if (ecode) 615 LogPrint (eLogError, "SOCKS: Closing socket after sending failure because: ", ecode.message ()); 616 Terminate(); 617 } 618 SentSocksDone(const boost::system::error_code & ecode)619 void SOCKSHandler::SentSocksDone(const boost::system::error_code & ecode) 620 { 621 if (!ecode) 622 { 623 if (Kill()) return; 624 LogPrint (eLogInfo, "SOCKS: New I2PTunnel connection"); 625 auto connection = std::make_shared<i2p::client::I2PTunnelConnection>(GetOwner(), m_sock, m_stream); 626 GetOwner()->AddHandler (connection); 627 connection->I2PConnect (m_remaining_data,m_remaining_data_len); 628 Done(shared_from_this()); 629 } 630 else 631 { 632 LogPrint (eLogError, "SOCKS: Closing socket after completion reply because: ", ecode.message ()); 633 Terminate(); 634 } 635 } 636 SentSocksResponse(const boost::system::error_code & ecode)637 void SOCKSHandler::SentSocksResponse(const boost::system::error_code & ecode) 638 { 639 if (ecode) 640 { 641 LogPrint (eLogError, "SOCKS: Closing socket after sending reply because: ", ecode.message ()); 642 Terminate(); 643 } 644 } 645 HandleStreamRequestComplete(std::shared_ptr<i2p::stream::Stream> stream)646 void SOCKSHandler::HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream) 647 { 648 if (stream) 649 { 650 m_stream = stream; 651 SocksRequestSuccess(); 652 } 653 else 654 { 655 LogPrint (eLogError, "SOCKS: Error when creating the stream, check the previous warnings for more info"); 656 SocksRequestFailed(SOCKS5_HOST_UNREACH); 657 } 658 } 659 ForwardSOCKS()660 void SOCKSHandler::ForwardSOCKS() 661 { 662 LogPrint(eLogInfo, "SOCKS: Forwarding to upstream"); 663 EnterState(UPSTREAM_RESOLVE); 664 boost::asio::ip::tcp::resolver::query q(m_UpstreamProxyAddress, std::to_string(m_UpstreamProxyPort)); 665 m_proxy_resolver.async_resolve(q, std::bind(&SOCKSHandler::HandleUpstreamResolved, shared_from_this(), 666 std::placeholders::_1, std::placeholders::_2)); 667 } 668 AsyncUpstreamSockRead()669 void SOCKSHandler::AsyncUpstreamSockRead() 670 { 671 LogPrint(eLogDebug, "SOCKS: Async upstream sock read"); 672 if (m_upstreamSock) { 673 m_upstreamSock->async_read_some(boost::asio::buffer(m_upstream_response, SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE), 674 std::bind(&SOCKSHandler::HandleUpstreamSockRecv, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); 675 } else { 676 LogPrint(eLogError, "SOCKS: No upstream socket for read"); 677 SocksRequestFailed(SOCKS5_GEN_FAIL); 678 } 679 } 680 HandleUpstreamSockRecv(const boost::system::error_code & ecode,std::size_t bytes_transfered)681 void SOCKSHandler::HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered) 682 { 683 if (ecode) { 684 if (m_state == UPSTREAM_HANDSHAKE ) { 685 // we are trying to handshake but it failed 686 SocksRequestFailed(SOCKS5_NET_UNREACH); 687 } else { 688 LogPrint(eLogError, "SOCKS: Bad state when reading from upstream: ", (int) m_state); 689 } 690 return; 691 } 692 HandleUpstreamData(m_upstream_response, bytes_transfered); 693 } 694 SocksUpstreamSuccess()695 void SOCKSHandler::SocksUpstreamSuccess() 696 { 697 LogPrint(eLogInfo, "SOCKS: Upstream success"); 698 boost::asio::const_buffers_1 response(nullptr, 0); 699 switch (m_socksv) 700 { 701 case SOCKS4: 702 LogPrint(eLogInfo, "SOCKS: v4 connection success"); 703 response = GenerateSOCKS4Response(SOCKS4_OK, m_4aip, m_port); 704 break; 705 case SOCKS5: 706 LogPrint(eLogInfo, "SOCKS: v5 connection success"); 707 //HACK only 16 bits passed in port as SOCKS5 doesn't allow for more 708 response = GenerateSOCKS5Response(SOCKS5_OK, ADDR_DNS, m_address, m_port); 709 break; 710 } 711 m_sock->send(response); 712 auto forwarder = std::make_shared<i2p::client::TCPIPPipe>(GetOwner(), m_sock, m_upstreamSock); 713 m_upstreamSock = nullptr; 714 m_sock = nullptr; 715 GetOwner()->AddHandler(forwarder); 716 forwarder->Start(); 717 Terminate(); 718 719 } 720 HandleUpstreamData(uint8_t * dataptr,std::size_t len)721 void SOCKSHandler::HandleUpstreamData(uint8_t * dataptr, std::size_t len) 722 { 723 if (m_state == UPSTREAM_HANDSHAKE) { 724 m_upstream_response_len += len; 725 // handle handshake data 726 if (m_upstream_response_len < SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE) { 727 // too small, continue reading 728 AsyncUpstreamSockRead(); 729 } else if (len == SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE) { 730 // just right 731 uint8_t resp = m_upstream_response[1]; 732 if (resp == SOCKS4_OK) { 733 // we have connected ! 734 SocksUpstreamSuccess(); 735 } else { 736 // upstream failure 737 LogPrint(eLogError, "SOCKS: Upstream proxy failure: ", (int) resp); 738 // TODO: runtime error? 739 SocksRequestFailed(SOCKS5_GEN_FAIL); 740 } 741 } else { 742 // too big 743 SocksRequestFailed(SOCKS5_GEN_FAIL); 744 } 745 } else { 746 // invalid state 747 LogPrint(eLogError, "SOCKS: Invalid state reading from upstream: ", (int) m_state); 748 } 749 } 750 SendUpstreamRequest()751 void SOCKSHandler::SendUpstreamRequest() 752 { 753 LogPrint(eLogInfo, "SOCKS: Negotiating with upstream proxy"); 754 EnterState(UPSTREAM_HANDSHAKE); 755 if (m_upstreamSock) { 756 boost::asio::write(*m_upstreamSock, GenerateUpstreamRequest()); 757 AsyncUpstreamSockRead(); 758 } else { 759 LogPrint(eLogError, "SOCKS: No upstream socket to send handshake to"); 760 } 761 } 762 HandleUpstreamConnected(const boost::system::error_code & ecode,boost::asio::ip::tcp::resolver::iterator itr)763 void SOCKSHandler::HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) 764 { 765 if (ecode) { 766 LogPrint(eLogWarning, "SOCKS: Could not connect to upstream proxy: ", ecode.message()); 767 SocksRequestFailed(SOCKS5_NET_UNREACH); 768 return; 769 } 770 LogPrint(eLogInfo, "SOCKS: Connected to upstream proxy"); 771 SendUpstreamRequest(); 772 } 773 HandleUpstreamResolved(const boost::system::error_code & ecode,boost::asio::ip::tcp::resolver::iterator itr)774 void SOCKSHandler::HandleUpstreamResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) 775 { 776 if (ecode) { 777 // error resolving 778 LogPrint(eLogWarning, "SOCKS: Upstream proxy", m_UpstreamProxyAddress, " not resolved: ", ecode.message()); 779 SocksRequestFailed(SOCKS5_NET_UNREACH); 780 return; 781 } 782 LogPrint(eLogInfo, "SOCKS: Upstream proxy resolved"); 783 EnterState(UPSTREAM_CONNECT); 784 auto & service = GetOwner()->GetService(); 785 m_upstreamSock = std::make_shared<boost::asio::ip::tcp::socket>(service); 786 boost::asio::async_connect(*m_upstreamSock, itr, 787 std::bind(&SOCKSHandler::HandleUpstreamConnected, 788 shared_from_this(), std::placeholders::_1, std::placeholders::_2)); 789 } 790 SOCKSServer(const std::string & name,const std::string & address,int port,bool outEnable,const std::string & outAddress,uint16_t outPort,std::shared_ptr<i2p::client::ClientDestination> localDestination)791 SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port, 792 bool outEnable, const std::string& outAddress, uint16_t outPort, 793 std::shared_ptr<i2p::client::ClientDestination> localDestination) : 794 TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name) 795 { 796 m_UseUpstreamProxy = false; 797 if (outAddress.length() > 0 && outEnable) 798 SetUpstreamProxy(outAddress, outPort); 799 } 800 CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket)801 std::shared_ptr<i2p::client::I2PServiceHandler> SOCKSServer::CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) 802 { 803 return std::make_shared<SOCKSHandler> (this, socket, m_UpstreamProxyAddress, m_UpstreamProxyPort, m_UseUpstreamProxy); 804 } 805 SetUpstreamProxy(const std::string & addr,const uint16_t port)806 void SOCKSServer::SetUpstreamProxy(const std::string & addr, const uint16_t port) 807 { 808 m_UpstreamProxyAddress = addr; 809 m_UpstreamProxyPort = port; 810 m_UseUpstreamProxy = true; 811 } 812 } 813 } 814