//Send responses to requester bool __fastcall SendToRequester( char *RecvBuffer, const size_t RecvSize, const size_t MaxLen, const uint16_t Protocol, const SOCKET_DATA &LocalSocketData) { //Response check if (RecvSize < DNS_PACKET_MINSIZE || CheckEmptyBuffer(RecvBuffer, RecvSize) || ((pdns_hdr)RecvBuffer)->ID == 0 || ((pdns_hdr)RecvBuffer)->Flags == 0) //DNS header ID and flags must not be set 0. return false; //TCP protocol if (Protocol == IPPROTO_TCP) { if (AddLengthDataToHeader(RecvBuffer, RecvSize, MaxLen) == EXIT_FAILURE) { shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); return false; } else { send(LocalSocketData.Socket, RecvBuffer, (int)(RecvSize + sizeof(uint16_t)), 0); shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); } } //UDP protocol else { sendto(LocalSocketData.Socket, RecvBuffer, (int)RecvSize, 0, (PSOCKADDR)&LocalSocketData.SockAddr, LocalSocketData.AddrLen); } return true; }
//Send responses to requester bool __fastcall SendToRequester( PSTR RecvBuffer, const size_t RecvSize, const uint16_t Protocol, const SOCKET_DATA &LocalSocketData) { //TCP if (Protocol == IPPROTO_TCP) { if (AddLengthDataToHeader(RecvBuffer, RecvSize, LARGE_PACKET_MAXSIZE) == EXIT_FAILURE) { shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); return false; } send(LocalSocketData.Socket, RecvBuffer, (int)(RecvSize + sizeof(uint16_t)), 0); shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); } //UDP else { sendto(LocalSocketData.Socket, RecvBuffer, (int)RecvSize, 0, (PSOCKADDR)&LocalSocketData.SockAddr, LocalSocketData.AddrLen); } return true; }
//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; }
//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, PSTR OriginalRecv, const size_t RecvSize) { //Initialization std::shared_ptr<char> SendBuffer(new char[LARGE_PACKET_MAXSIZE]()); std::shared_ptr<SOCKET_DATA> TCPSocketData(new SOCKET_DATA()); memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE); memset(TCPSocketData.get(), 0, sizeof(SOCKET_DATA)); //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, nullptr)) { PrintError(LOG_ERROR_NETWORK, L"SOCKS socket initialization error", 0, nullptr, 0); return EXIT_FAILURE; } //Non-blocking mode setting if (!SocketSetting(TCPSocketData->Socket, SOCKET_SETTING_NON_BLOCKING_MODE, nullptr)) { shutdown(TCPSocketData->Socket, SD_BOTH); closesocket(TCPSocketData->Socket); PrintError(LOG_ERROR_NETWORK, L"Socket non-blocking mode setting error", 0, nullptr, 0); return EXIT_FAILURE; } //Selecting structure setting std::shared_ptr<fd_set> ReadFDS(new fd_set()), WriteFDS(new fd_set()); std::shared_ptr<timeval> Timeout(new timeval()); memset(ReadFDS.get(), 0, sizeof(fd_set)); memset(WriteFDS.get(), 0, sizeof(fd_set)); memset(Timeout.get(), 0, sizeof(timeval)); //Selection exchange process if (Parameter.SOCKS_Version == SOCKS_VERSION_5) { if (!SOCKSSelectionExchange(TCPSocketData.get(), ReadFDS.get(), WriteFDS.get(), Timeout.get(), 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.get(), WriteFDS.get(), Timeout.get(), SendBuffer.get(), OriginalRecv, RecvSize, TCPSocketData.get())) { 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; } //Data exchange RecvLen = SOCKSSocketSelecting(TCPSocketData->Socket, ReadFDS.get(), WriteFDS.get(), Timeout.get(), SendBuffer.get(), RecvLen, OriginalRecv, RecvSize, DNS_PACKET_MINSIZE); shutdown(TCPSocketData->Socket, SD_BOTH); closesocket(TCPSocketData->Socket); if (RecvLen >= (SSIZE_T)DNS_PACKET_MINSIZE) { memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(uint16_t), RecvLen); return RecvLen; } return EXIT_FAILURE; }