//Transmission and reception of SOCKS protocol(UDP) size_t __fastcall SOCKSUDPRequest( const char *OriginalSend, const size_t SendSize, char *OriginalRecv, const size_t RecvSize) { //Initialization std::shared_ptr<char> SendBuffer(new char[LARGE_PACKET_MAXSIZE]()); memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE); SOCKET_DATA TCPSocketData = {0}, LocalSocketData = {0}, UDPSocketData = {0}; memset(OriginalRecv, 0, RecvSize); //Socket initialization if (Parameter.SOCKS_Address_IPv6.Storage.ss_family > 0 && //IPv6 (Parameter.SOCKS_Protocol_Network == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv6 || //Auto select Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV6 || //IPv6 Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV4 && Parameter.SOCKS_Address_IPv4.Storage.ss_family == 0)) //Non-IPv4 { if (!Parameter.SOCKS_UDP_NoHandshake) { //TCP process TCPSocketData.SockAddr.ss_family = AF_INET6; ((PSOCKADDR_IN6)&TCPSocketData.SockAddr)->sin6_addr = Parameter.SOCKS_Address_IPv6.IPv6.sin6_addr; ((PSOCKADDR_IN6)&TCPSocketData.SockAddr)->sin6_port = Parameter.SOCKS_Address_IPv6.IPv6.sin6_port; TCPSocketData.AddrLen = sizeof(sockaddr_in6); TCPSocketData.Socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); //Local process LocalSocketData.SockAddr.ss_family = AF_INET6; LocalSocketData.AddrLen = sizeof(sockaddr_in6); } //UDP process UDPSocketData.SockAddr.ss_family = AF_INET6; ((PSOCKADDR_IN6)&UDPSocketData.SockAddr)->sin6_addr = Parameter.SOCKS_Address_IPv6.IPv6.sin6_addr; if (Parameter.SOCKS_UDP_NoHandshake) ((PSOCKADDR_IN6)&UDPSocketData.SockAddr)->sin6_port = Parameter.SOCKS_Address_IPv6.IPv6.sin6_port; UDPSocketData.AddrLen = sizeof(sockaddr_in6); UDPSocketData.Socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); } else if (Parameter.SOCKS_Address_IPv4.Storage.ss_family > 0 && //IPv4 (Parameter.SOCKS_Protocol_Network == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv4 || //Auto select Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV4 || //IPv4 Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV6 && Parameter.SOCKS_Address_IPv6.Storage.ss_family == 0)) //Non-IPv6 { if (!Parameter.SOCKS_UDP_NoHandshake) { //TCP process TCPSocketData.SockAddr.ss_family = AF_INET; ((PSOCKADDR_IN)&TCPSocketData.SockAddr)->sin_addr = Parameter.SOCKS_Address_IPv4.IPv4.sin_addr; ((PSOCKADDR_IN)&TCPSocketData.SockAddr)->sin_port = Parameter.SOCKS_Address_IPv4.IPv4.sin_port; TCPSocketData.AddrLen = sizeof(sockaddr_in); TCPSocketData.Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Local process LocalSocketData.SockAddr.ss_family = AF_INET; LocalSocketData.AddrLen = sizeof(sockaddr_in); } //UDP process UDPSocketData.SockAddr.ss_family = AF_INET; ((PSOCKADDR_IN)&UDPSocketData.SockAddr)->sin_addr = Parameter.SOCKS_Address_IPv4.IPv4.sin_addr; if (Parameter.SOCKS_UDP_NoHandshake) ((PSOCKADDR_IN)&UDPSocketData.SockAddr)->sin_port = Parameter.SOCKS_Address_IPv4.IPv4.sin_port; UDPSocketData.AddrLen = sizeof(sockaddr_in); UDPSocketData.Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); } else { return EXIT_FAILURE; } //Socket check and Hop Limits setting if (!Parameter.SOCKS_UDP_NoHandshake && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr) || TCPSocketData.SockAddr.ss_family == AF_INET6 && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV6, false, nullptr) || TCPSocketData.SockAddr.ss_family == AF_INET && (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV4, false, nullptr) || !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_DO_NOT_FRAGMENT, true, nullptr)) || !SocketSetting(UDPSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr) || UDPSocketData.SockAddr.ss_family == AF_INET6 && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV6, false, nullptr) || UDPSocketData.SockAddr.ss_family == AF_INET && (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV4, false, nullptr) || !SocketSetting(UDPSocketData.Socket, SOCKET_SETTING_DO_NOT_FRAGMENT, true, nullptr))) { closesocket(UDPSocketData.Socket); if (!Parameter.SOCKS_UDP_NoHandshake) closesocket(TCPSocketData.Socket); PrintError(LOG_LEVEL_2, LOG_ERROR_NETWORK, L"SOCKS socket initialization error", 0, nullptr, 0); return EXIT_FAILURE; } //Non-blocking mode setting if (!Parameter.SOCKS_UDP_NoHandshake && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_NON_BLOCKING_MODE, true, nullptr) || !SocketSetting(UDPSocketData.Socket, SOCKET_SETTING_NON_BLOCKING_MODE, true, nullptr)) { closesocket(UDPSocketData.Socket); if (!Parameter.SOCKS_UDP_NoHandshake) closesocket(TCPSocketData.Socket); return EXIT_FAILURE; } //Selecting structure setting fd_set ReadFDS = {0}, WriteFDS = {0}; timeval Timeout = {0}; //UDP transmission of standard SOCKS protocol must connect with TCP to server at first. if (!Parameter.SOCKS_UDP_NoHandshake) { //Selection exchange process if (!SOCKSSelectionExchange(&TCPSocketData, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), OriginalRecv, RecvSize)) { shutdown(UDPSocketData.Socket, SD_BOTH); shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(UDPSocketData.Socket); closesocket(TCPSocketData.Socket); return EXIT_FAILURE; } else { memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE); } //UDP connecting and get UDP socket infomation. if (SocketConnecting(IPPROTO_UDP, UDPSocketData.Socket, (PSOCKADDR)&UDPSocketData.SockAddr, UDPSocketData.AddrLen, nullptr, 0) == EXIT_FAILURE || getsockname(UDPSocketData.Socket, (PSOCKADDR)&LocalSocketData.SockAddr, &LocalSocketData.AddrLen) == SOCKET_ERROR) { shutdown(UDPSocketData.Socket, SD_BOTH); shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(UDPSocketData.Socket); closesocket(TCPSocketData.Socket); PrintError(LOG_LEVEL_3, LOG_ERROR_NETWORK, L"SOCKS connecting error", 0, nullptr, 0); return EXIT_FAILURE; } //Client command request process if (!SOCKSClientCommandRequest(IPPROTO_UDP, TCPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), OriginalRecv, RecvSize, &LocalSocketData)) { shutdown(UDPSocketData.Socket, SD_BOTH); shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(UDPSocketData.Socket); closesocket(TCPSocketData.Socket); return EXIT_FAILURE; } else { memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE); //Copy network infomation from server message. if (UDPSocketData.SockAddr.ss_family == AF_INET6) ((PSOCKADDR_IN6)&UDPSocketData.SockAddr)->sin6_port = ((PSOCKADDR_IN6)&LocalSocketData.SockAddr)->sin6_port; else ((PSOCKADDR_IN)&UDPSocketData.SockAddr)->sin_port = ((PSOCKADDR_IN)&LocalSocketData.SockAddr)->sin_port; } } //UDP connecting again if (SocketConnecting(IPPROTO_UDP, UDPSocketData.Socket, (PSOCKADDR)&UDPSocketData.SockAddr, UDPSocketData.AddrLen, nullptr, 0) == EXIT_FAILURE) { if (!Parameter.SOCKS_UDP_NoHandshake) { shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(TCPSocketData.Socket); } PrintError(LOG_LEVEL_3, LOG_ERROR_NETWORK, L"SOCKS connecting error", 0, nullptr, 0); return EXIT_FAILURE; } //SOCKS UDP relay header SSIZE_T RecvLen = sizeof(socks_udp_relay_request); void *SOCKS_Pointer = SendBuffer.get(); if (Parameter.SOCKS_TargetServer.Storage.ss_family == AF_INET6) //IPv6 { ((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type = SOCKS5_ADDRESS_IPV6; SOCKS_Pointer = SendBuffer.get() + RecvLen; RecvLen += (SSIZE_T)sizeof(in6_addr); *(in6_addr *)SOCKS_Pointer = Parameter.SOCKS_TargetServer.IPv6.sin6_addr; SOCKS_Pointer = SendBuffer.get() + RecvLen; RecvLen += (SSIZE_T)sizeof(uint16_t); *(uint16_t *)SOCKS_Pointer = Parameter.SOCKS_TargetServer.IPv6.sin6_port; } else if (Parameter.SOCKS_TargetServer.Storage.ss_family == AF_INET) //IPv4 { ((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type = SOCKS5_ADDRESS_IPV4; SOCKS_Pointer = SendBuffer.get() + RecvLen; RecvLen += (SSIZE_T)sizeof(in_addr); *(in_addr *)SOCKS_Pointer = Parameter.SOCKS_TargetServer.IPv4.sin_addr; SOCKS_Pointer = SendBuffer.get() + RecvLen; RecvLen += (SSIZE_T)sizeof(uint16_t); *(uint16_t *)SOCKS_Pointer = Parameter.SOCKS_TargetServer.IPv4.sin_port; } else if (Parameter.SOCKS_TargetDomain != nullptr && !Parameter.SOCKS_TargetDomain->empty()) //Damain { ((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type = SOCKS5_ADDRESS_DOMAIN; SOCKS_Pointer = SendBuffer.get() + RecvLen; RecvLen += (SSIZE_T)sizeof(uint8_t); *(uint8_t *)SOCKS_Pointer = (uint8_t)Parameter.SOCKS_TargetDomain->length(); SOCKS_Pointer = SendBuffer.get() + RecvLen; memcpy_s(SOCKS_Pointer, (SSIZE_T)LARGE_PACKET_MAXSIZE - ((SSIZE_T)sizeof(socks_udp_relay_request) + RecvLen), Parameter.SOCKS_TargetDomain->c_str(), Parameter.SOCKS_TargetDomain->length()); RecvLen += (SSIZE_T)Parameter.SOCKS_TargetDomain->length(); SOCKS_Pointer = SendBuffer.get() + RecvLen; *(uint16_t *)SOCKS_Pointer = Parameter.SOCKS_TargetDomain_Port; RecvLen += (SSIZE_T)sizeof(uint16_t); } else { shutdown(UDPSocketData.Socket, SD_BOTH); closesocket(UDPSocketData.Socket); if (!Parameter.SOCKS_UDP_NoHandshake) { shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(TCPSocketData.Socket); } return EXIT_FAILURE; } memcpy_s(SendBuffer.get() + RecvLen, RecvSize, OriginalSend, SendSize); RecvLen += (SSIZE_T)SendSize; //Socket timeout setting #if defined(PLATFORM_WIN) Timeout.tv_sec = Parameter.SOCKS_SocketTimeout_Unreliable / SECOND_TO_MILLISECOND; Timeout.tv_usec = Parameter.SOCKS_SocketTimeout_Unreliable % SECOND_TO_MILLISECOND * MICROSECOND_TO_MILLISECOND; #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) Timeout.tv_sec = Parameter.SOCKS_SocketTimeout_Reliable.tv_sec; Timeout.tv_usec = Parameter.SOCKS_SocketTimeout_Reliable.tv_usec; #endif //Data exchange RecvLen = ProxySocketSelecting(UDPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), RecvLen, OriginalRecv, RecvSize, sizeof(socks_udp_relay_request) + DNS_PACKET_MINSIZE, nullptr); shutdown(UDPSocketData.Socket, SD_BOTH); closesocket(UDPSocketData.Socket); if (!Parameter.SOCKS_UDP_NoHandshake) { shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(TCPSocketData.Socket); } if (RecvLen >= (SSIZE_T)DNS_PACKET_MINSIZE) { SSIZE_T OriginalRecvLen = RecvLen; //Remove SOCKS UDP relay header SOCKS_Pointer = OriginalRecv; if (Parameter.SOCKS_TargetServer.Storage.ss_family == AF_INET6 && //IPv6 ((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_IPV6 && RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t) + DNS_PACKET_MINSIZE) && memcmp((in6_addr *)(OriginalRecv + sizeof(socks_udp_relay_request)), &Parameter.SOCKS_TargetServer.IPv6.sin6_addr, sizeof(in6_addr)) == 0 && *(uint16_t *)(OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in6_addr)) == Parameter.SOCKS_TargetServer.IPv6.sin6_port) { memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t))); RecvLen -= sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t); } else if (Parameter.SOCKS_TargetServer.Storage.ss_family == AF_INET && //IPv4 ((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_IPV4 && RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t) + DNS_PACKET_MINSIZE) && (*(in_addr *)(OriginalRecv + sizeof(socks_udp_relay_request))).s_addr == Parameter.SOCKS_TargetServer.IPv4.sin_addr.s_addr && *(uint16_t *)(OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in_addr)) == Parameter.SOCKS_TargetServer.IPv4.sin_port) { memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t))); RecvLen -= sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t); } else if (Parameter.SOCKS_TargetDomain != nullptr && !Parameter.SOCKS_TargetDomain->empty()) //Domain /* SOCKS server will reply IPv4/IPv6 address of domain. ((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_DOMAIN && RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length() + sizeof(uint16_t) + DNS_PACKET_MINSIZE) && *(uint8_t *)(OriginalRecv + sizeof(socks_udp_relay_request)) == Parameter.SOCKS_TargetDomain->length() && memcmp(OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(uint8_t), Parameter.SOCKS_TargetDomain->c_str(), Parameter.SOCKS_TargetDomain->length()) == 0 && *(uint16_t *)(OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length()) == Parameter.SOCKS_TargetDomain_Port) */ { //IPv6 if (((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_IPV6 && RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t) + DNS_PACKET_MINSIZE)) { memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t))); RecvLen -= sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t); } //IPv4 else if (((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_IPV4 && RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t) + DNS_PACKET_MINSIZE)) { memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t))); RecvLen -= sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t); } /* SOCKS server will reply IPv4/IPv6 address of domain. memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length() + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length() + sizeof(uint16_t))); return RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length() + sizeof(uint16_t)); */ } //Server response check if (OriginalRecvLen != RecvLen) { //Responses check RecvLen = CheckResponseData( REQUEST_PROCESS_SOCKS, OriginalRecv, RecvLen, RecvSize, nullptr); if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE) return EXIT_FAILURE; //Mark DNS cache. if (Parameter.CacheType > 0) MarkDomainCache(OriginalRecv, RecvLen); return RecvLen; } } return EXIT_FAILURE; }
//Transmission and reception of HTTP protocol size_t __fastcall HTTPRequest( const char *OriginalSend, const size_t SendSize, char *OriginalRecv, const size_t RecvSize) { //Initialization SOCKET_DATA HTTPSocketData = {0}; memset(OriginalRecv, 0, RecvSize); //Socket initialization if (Parameter.HTTP_Address_IPv6.Storage.ss_family > 0 && //IPv6 (Parameter.HTTP_Protocol == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv6 || //Auto select Parameter.HTTP_Protocol == REQUEST_MODE_IPV6 || //IPv6 Parameter.HTTP_Protocol == REQUEST_MODE_IPV4 && Parameter.HTTP_Address_IPv4.Storage.ss_family == 0)) //Non-IPv4 { HTTPSocketData.SockAddr.ss_family = AF_INET6; ((PSOCKADDR_IN6)&HTTPSocketData.SockAddr)->sin6_addr = Parameter.HTTP_Address_IPv6.IPv6.sin6_addr; ((PSOCKADDR_IN6)&HTTPSocketData.SockAddr)->sin6_port = Parameter.HTTP_Address_IPv6.IPv6.sin6_port; HTTPSocketData.AddrLen = sizeof(sockaddr_in6); HTTPSocketData.Socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); } else if (Parameter.HTTP_Address_IPv4.Storage.ss_family > 0 && //IPv4 (Parameter.HTTP_Protocol == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv4 || //Auto select Parameter.HTTP_Protocol == REQUEST_MODE_IPV4 || //IPv4 Parameter.HTTP_Protocol == REQUEST_MODE_IPV6 && Parameter.HTTP_Address_IPv6.Storage.ss_family == 0)) //Non-IPv6 { HTTPSocketData.SockAddr.ss_family = AF_INET; ((PSOCKADDR_IN)&HTTPSocketData.SockAddr)->sin_addr = Parameter.HTTP_Address_IPv4.IPv4.sin_addr; ((PSOCKADDR_IN)&HTTPSocketData.SockAddr)->sin_port = Parameter.HTTP_Address_IPv4.IPv4.sin_port; HTTPSocketData.AddrLen = sizeof(sockaddr_in); HTTPSocketData.Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } else { return EXIT_FAILURE; } //Socket check if (!SocketSetting(HTTPSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, nullptr)) { PrintError(LOG_ERROR_NETWORK, L"HTTP socket initialization error", 0, nullptr, 0); return EXIT_FAILURE; } //Non-blocking mode setting if (!SocketSetting(HTTPSocketData.Socket, SOCKET_SETTING_NON_BLOCKING_MODE, nullptr)) { shutdown(HTTPSocketData.Socket, SD_BOTH); closesocket(HTTPSocketData.Socket); PrintError(LOG_ERROR_NETWORK, L"Socket non-blocking mode setting error", 0, nullptr, 0); return EXIT_FAILURE; } //Selecting structure setting fd_set ReadFDS = {0}, WriteFDS = {0}; timeval Timeout = {0}; //HTTP CONNECT request if (Parameter.HTTP_TargetDomain == nullptr || Parameter.HTTP_Version == nullptr || !HTTP_CONNECTRequest(&HTTPSocketData, &ReadFDS, &WriteFDS, &Timeout, OriginalRecv, RecvSize)) { shutdown(HTTPSocketData.Socket, SD_BOTH); closesocket(HTTPSocketData.Socket); return EXIT_FAILURE; } //Add length of request packet(It must be written in header when transpot with TCP protocol). std::shared_ptr<char> SendBuffer(new char[LARGE_PACKET_MAXSIZE]()); memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE); memcpy_s(SendBuffer.get(), RecvSize, OriginalSend, SendSize); SSIZE_T RecvLen = AddLengthDataToHeader(SendBuffer.get(), SendSize, RecvSize); if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE) { shutdown(HTTPSocketData.Socket, SD_BOTH); closesocket(HTTPSocketData.Socket); return EXIT_FAILURE; } //Socket timeout setting #if defined(PLATFORM_WIN) Timeout.tv_sec = Parameter.HTTP_SocketTimeout / SECOND_TO_MILLISECOND; Timeout.tv_usec = Parameter.HTTP_SocketTimeout % SECOND_TO_MILLISECOND * MICROSECOND_TO_MILLISECOND; #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) Timeout.tv_sec = Parameter.HTTP_SocketTimeout.tv_sec; Timeout.tv_usec = Parameter.HTTP_SocketTimeout.tv_usec; #endif //Data exchange RecvLen = ProxySocketSelecting(HTTPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), RecvLen, OriginalRecv, RecvSize, DNS_PACKET_MINSIZE, nullptr); shutdown(HTTPSocketData.Socket, SD_BOTH); closesocket(HTTPSocketData.Socket); //Server response check if (RecvLen >= (SSIZE_T)DNS_PACKET_MINSIZE && ntohs(((uint16_t *)OriginalRecv)[0]) >= DNS_PACKET_MINSIZE && RecvLen >= ntohs(((uint16_t *)OriginalRecv)[0])) { RecvLen = ntohs(((uint16_t *)OriginalRecv)[0]); memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(uint16_t), RecvLen); //Responses check RecvLen = CheckResponseData( REQUEST_PROCESS_HTTP, OriginalRecv, RecvLen, RecvSize, nullptr); if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE) return EXIT_FAILURE; //Mark DNS cache. if (Parameter.CacheType > 0) MarkDomainCache(OriginalRecv, RecvLen); return RecvLen; } return EXIT_FAILURE; }
//Transmission and reception of SOCKS protocol(TCP) size_t __fastcall SOCKSTCPRequest( const char *OriginalSend, const size_t SendSize, char *OriginalRecv, const size_t RecvSize) { //Initialization std::shared_ptr<char> SendBuffer(new char[LARGE_PACKET_MAXSIZE]()); memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE); SOCKET_DATA TCPSocketData = {0}; memset(OriginalRecv, 0, RecvSize); //Socket initialization if (Parameter.SOCKS_Address_IPv6.Storage.ss_family > 0 && //IPv6 (Parameter.SOCKS_Protocol_Network == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv6 || //Auto select Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV6 || //IPv6 Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV4 && Parameter.SOCKS_Address_IPv4.Storage.ss_family == 0)) //Non-IPv4 { TCPSocketData.SockAddr.ss_family = AF_INET6; ((PSOCKADDR_IN6)&TCPSocketData.SockAddr)->sin6_addr = Parameter.SOCKS_Address_IPv6.IPv6.sin6_addr; ((PSOCKADDR_IN6)&TCPSocketData.SockAddr)->sin6_port = Parameter.SOCKS_Address_IPv6.IPv6.sin6_port; TCPSocketData.AddrLen = sizeof(sockaddr_in6); TCPSocketData.Socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); } else if (Parameter.SOCKS_Address_IPv4.Storage.ss_family > 0 && //IPv4 (Parameter.SOCKS_Protocol_Network == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv4 || //Auto select Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV4 || //IPv4 Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV6 && Parameter.SOCKS_Address_IPv6.Storage.ss_family == 0)) //Non-IPv6 { TCPSocketData.SockAddr.ss_family = AF_INET; ((PSOCKADDR_IN)&TCPSocketData.SockAddr)->sin_addr = Parameter.SOCKS_Address_IPv4.IPv4.sin_addr; ((PSOCKADDR_IN)&TCPSocketData.SockAddr)->sin_port = Parameter.SOCKS_Address_IPv4.IPv4.sin_port; TCPSocketData.AddrLen = sizeof(sockaddr_in); TCPSocketData.Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } else { return EXIT_FAILURE; } //Socket check if (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr)) { PrintError(LOG_LEVEL_2, LOG_ERROR_NETWORK, L"SOCKS socket initialization error", 0, nullptr, 0); return EXIT_FAILURE; } //Non-blocking mode setting and Hop Limits setting if (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_NON_BLOCKING_MODE, true, nullptr) || TCPSocketData.SockAddr.ss_family == AF_INET6 && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV6, true, nullptr) || TCPSocketData.SockAddr.ss_family == AF_INET && (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV4, true, nullptr) || !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_DO_NOT_FRAGMENT, true, nullptr))) { shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(TCPSocketData.Socket); return EXIT_FAILURE; } //Selecting structure setting fd_set ReadFDS = {0}, WriteFDS = {0}; timeval Timeout = {0}; //Selection exchange process if (Parameter.SOCKS_Version == SOCKS_VERSION_5) { if (!SOCKSSelectionExchange(&TCPSocketData, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), OriginalRecv, RecvSize)) { shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(TCPSocketData.Socket); return EXIT_FAILURE; } else { memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE); } } //Client command request process if (!SOCKSClientCommandRequest(IPPROTO_TCP, TCPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), OriginalRecv, RecvSize, &TCPSocketData)) { shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(TCPSocketData.Socket); return EXIT_FAILURE; } else { memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE); } //Add length of request packet(It must be written in header when transpot with TCP protocol). memcpy_s(SendBuffer.get(), RecvSize, OriginalSend, SendSize); SSIZE_T RecvLen = AddLengthDataToHeader(SendBuffer.get(), SendSize, RecvSize); if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE) { shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(TCPSocketData.Socket); return EXIT_FAILURE; } //Socket timeout setting #if defined(PLATFORM_WIN) Timeout.tv_sec = Parameter.SOCKS_SocketTimeout_Reliable / SECOND_TO_MILLISECOND; Timeout.tv_usec = Parameter.SOCKS_SocketTimeout_Reliable % SECOND_TO_MILLISECOND * MICROSECOND_TO_MILLISECOND; #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) Timeout.tv_sec = Parameter.SOCKS_SocketTimeout_Reliable.tv_sec; Timeout.tv_usec = Parameter.SOCKS_SocketTimeout_Reliable.tv_usec; #endif //Data exchange RecvLen = ProxySocketSelecting(TCPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), RecvLen, OriginalRecv, RecvSize, DNS_PACKET_MINSIZE, nullptr); shutdown(TCPSocketData.Socket, SD_BOTH); closesocket(TCPSocketData.Socket); //Server response check if (RecvLen >= (SSIZE_T)DNS_PACKET_MINSIZE && ntohs(((uint16_t *)OriginalRecv)[0]) >= DNS_PACKET_MINSIZE && RecvLen >= ntohs(((uint16_t *)OriginalRecv)[0])) { RecvLen = ntohs(((uint16_t *)OriginalRecv)[0]); memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(uint16_t), RecvLen); //Responses check RecvLen = CheckResponseData( REQUEST_PROCESS_SOCKS, OriginalRecv, RecvLen, RecvSize, nullptr); if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE) return EXIT_FAILURE; //Mark DNS cache. if (Parameter.CacheType > 0) MarkDomainCache(OriginalRecv, RecvLen); return RecvLen; } return EXIT_FAILURE; }
//Match port of responses and send responses to system sockets process bool __fastcall MatchPortToSend(const char *Buffer, const size_t Length, const uint16_t Protocol, const uint16_t Port) { //Initialization std::shared_ptr<SOCKET_DATA> SocketData_Input(new SOCKET_DATA()); memset(SocketData_Input.get(), 0, sizeof(SOCKET_DATA)); uint16_t SystemProtocol = 0; size_t ReceiveIndex = 0; //Match port. std::unique_lock<std::mutex> OutputPacketListMutex(OutputPacketListLock); for (auto &PortTableIter:OutputPacketList) { for (auto &SocketDataIter:PortTableIter.SocketData_Output) { if (PortTableIter.ClearPortTime > 0 && //Do not scan timeout data. Protocol == AF_INET6 && SocketDataIter.AddrLen == sizeof(sockaddr_in6) && SocketDataIter.SockAddr.ss_family == AF_INET6 && Port == ((PSOCKADDR_IN6)&SocketDataIter.SockAddr)->sin6_port || //IPv6 Protocol == AF_INET && SocketDataIter.AddrLen == sizeof(sockaddr_in) && SocketDataIter.SockAddr.ss_family == AF_INET && Port == ((PSOCKADDR_IN)&SocketDataIter.SockAddr)->sin_port) //IPv4 { if (Parameter.ReceiveWaiting > 0) { ++PortTableIter.ReceiveIndex; ReceiveIndex = PortTableIter.ReceiveIndex; OutputPacketListLock.unlock(); goto StopLoop; } else { *SocketData_Input = PortTableIter.SocketData_Input; SystemProtocol = PortTableIter.Protocol_Network; PortTableIter.ClearPortTime = 0; goto ClearOutputPacketListData; } } } } goto ClearOutputPacketListData; //Stop loop, wait receiving and match port again. StopLoop: Sleep(Parameter.ReceiveWaiting); OutputPacketListLock.lock(); for (auto &PortTableIter:OutputPacketList) { for (auto &SocketDataIter:PortTableIter.SocketData_Output) { if (PortTableIter.ClearPortTime > 0 && //Do not scan timeout data. Protocol == AF_INET6 && SocketDataIter.AddrLen == sizeof(sockaddr_in6) && SocketDataIter.SockAddr.ss_family == AF_INET6 && Port == ((PSOCKADDR_IN6)&SocketDataIter.SockAddr)->sin6_port || //IPv6 Protocol == AF_INET && SocketDataIter.AddrLen == sizeof(sockaddr_in) && SocketDataIter.SockAddr.ss_family == AF_INET && Port == ((PSOCKADDR_IN)&SocketDataIter.SockAddr)->sin_port) //IPv4 { if (PortTableIter.ReceiveIndex == ReceiveIndex) { *SocketData_Input = PortTableIter.SocketData_Input; SystemProtocol = PortTableIter.Protocol_Network; PortTableIter.ClearPortTime = 0; } else { return false; } goto ClearOutputPacketListData; } } } //Stop loop and clear timeout data. ClearOutputPacketListData: //Minimum supported system of GetTickCount64() is Windows Vista(Windows XP with SP3 support). #if (defined(PLATFORM_WIN32) && !defined(PLATFORM_WIN64)) if (Parameter.FunctionPTR_GetTickCount64 != nullptr) { while (!OutputPacketList.empty() && OutputPacketList.front().ClearPortTime <= (size_t)((*Parameter.FunctionPTR_GetTickCount64)())) { //Mark timeout. if (OutputPacketList.front().ClearPortTime > 0) { if (OutputPacketList.front().Protocol_Network == AF_INET6) //IPv6 { if (OutputPacketList.front().Protocol_Transport == IPPROTO_TCP) //TCP ++AlternateSwapList.TimeoutTimes[0]; else //UDP ++AlternateSwapList.TimeoutTimes[2U]; } else if (OutputPacketList.front().Protocol_Network == AF_INET) //IPv4 { if (OutputPacketList.front().Protocol_Transport == IPPROTO_TCP) //TCP ++AlternateSwapList.TimeoutTimes[1U]; else //UDP ++AlternateSwapList.TimeoutTimes[3U]; } } OutputPacketList.pop_front(); } } else { while (!OutputPacketList.empty() && OutputPacketList.front().ClearPortTime <= GetTickCount()) { //Mark timeout. if (OutputPacketList.front().ClearPortTime > 0) { if (OutputPacketList.front().Protocol_Network == AF_INET6) //IPv6 { if (OutputPacketList.front().Protocol_Transport == IPPROTO_TCP) //TCP ++AlternateSwapList.TimeoutTimes[0]; else //UDP ++AlternateSwapList.TimeoutTimes[2U]; } else if (OutputPacketList.front().Protocol_Network == AF_INET) //IPv4 { if (OutputPacketList.front().Protocol_Transport == IPPROTO_TCP) //TCP ++AlternateSwapList.TimeoutTimes[1U]; else //UDP ++AlternateSwapList.TimeoutTimes[3U]; } } OutputPacketList.pop_front(); } } #else while (!OutputPacketList.empty() && OutputPacketList.front().ClearPortTime <= GetTickCount64()) { //Mark timeout. if (OutputPacketList.front().ClearPortTime > 0) { if (OutputPacketList.front().Protocol_Network == AF_INET6) //IPv6 { if (OutputPacketList.front().Protocol_Transport == IPPROTO_TCP) //TCP ++AlternateSwapList.TimeoutTimes[0]; else //UDP ++AlternateSwapList.TimeoutTimes[2U]; } else if (OutputPacketList.front().Protocol_Network == AF_INET) //IPv4 { if (OutputPacketList.front().Protocol_Transport == IPPROTO_TCP) //TCP ++AlternateSwapList.TimeoutTimes[1U]; else //UDP ++AlternateSwapList.TimeoutTimes[3U]; } } OutputPacketList.pop_front(); } #endif OutputPacketListMutex.unlock(); //Drop resopnses which not in OutputPacketList. if (SocketData_Input->Socket == 0 || SocketData_Input->AddrLen == 0 || SocketData_Input->SockAddr.ss_family == 0 || SystemProtocol == 0) return false; //Mark DNS Cache. if (Parameter.CacheType > 0) MarkDomainCache(Buffer, Length); //Send to localhost. SendToRequester((PSTR)Buffer, Length, SystemProtocol, *SocketData_Input); if (SystemProtocol == IPPROTO_TCP) return true; //Check global sockets. if (Parameter.LocalSocket != nullptr && !Parameter.LocalSocket->empty()) { for (auto SocketIter:*Parameter.LocalSocket) { if (SocketIter == SocketData_Input->Socket) return true; } } shutdown(SocketData_Input->Socket, SD_BOTH); closesocket(SocketData_Input->Socket); return true; }