void __fastcall UDPRequestProcess( const DNS_PACKET_DATA &Packet, const SOCKET_DATA &LocalSocketData) { //EDNS switching(Part 1) size_t EDNS_SwitchLength = Packet.Length; uint16_t EDNS_Packet_Flags = ((dns_hdr *)(Packet.Buffer))->Flags; if (Parameter.EDNS_Label && !Parameter.EDNS_Switch.EDNS_UDP) { //Reset EDNS flags, resource record counts and packet length. ((dns_hdr *)(Packet.Buffer))->Flags = htons(ntohs(((dns_hdr *)(Packet.Buffer))->Flags) & (~DNS_GET_BIT_AD)); ((dns_hdr *)(Packet.Buffer))->Flags = htons(ntohs(((dns_hdr *)(Packet.Buffer))->Flags) & (~DNS_GET_BIT_CD)); if (((dns_hdr *)(Packet.Buffer))->Additional > 0) ((dns_hdr *)(Packet.Buffer))->Additional = htons(ntohs(((dns_hdr *)(Packet.Buffer))->Additional) - 1U); EDNS_SwitchLength -= Packet.EDNS_Record; } //Multi request process if (Parameter.AlternateMultiRequest || Parameter.MultiRequestTimes > 1U) UDPRequestMulti(Packet.Buffer, EDNS_SwitchLength, &LocalSocketData, Packet.Protocol); //Normal request process else UDPRequest(Packet.Buffer, EDNS_SwitchLength, &LocalSocketData, Packet.Protocol); //Fin TCP request connection. if (Packet.Protocol == IPPROTO_TCP && SocketSetting(LocalSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr)) { shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); } //EDNS switching(Part 2) if (Parameter.EDNS_Label && !Parameter.EDNS_Switch.EDNS_UDP) { ((dns_hdr *)(Packet.Buffer))->Flags = EDNS_Packet_Flags; ((dns_hdr *)(Packet.Buffer))->Additional = htons(ntohs(((dns_hdr *)(Packet.Buffer))->Additional) + 1U); } return; }
//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 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 of DNSCurve UDP protocol(Multiple threading) size_t DNSCurve_UDP_RequestMultiple( const uint8_t * const OriginalSend, const size_t SendSize, uint8_t * const OriginalRecv, const size_t RecvSize, const uint16_t QueryType, const SOCKET_DATA &LocalSocketData) { //Key initialization uint8_t *PrecomputationKey = nullptr, *Alternate_PrecomputationKey = nullptr; DNSCURVE_HEAP_BUFFER_TABLE<uint8_t> PrecomputationKeyBuffer, Alternate_PrecomputationKeyBuffer; if (DNSCurveParameter.IsEncryption && DNSCurveParameter.IsClientEphemeralKey) { DNSCURVE_HEAP_BUFFER_TABLE<uint8_t> PrecomputationKeyBufferTemp(crypto_box_BEFORENMBYTES), Alternate_PrecomputationKeyBufferTemp(crypto_box_BEFORENMBYTES); //Main PrecomputationKeyBufferTemp.Swap(PrecomputationKeyBuffer); PrecomputationKey = PrecomputationKeyBuffer.Buffer; //Alternate Alternate_PrecomputationKeyBufferTemp.Swap(Alternate_PrecomputationKeyBuffer); Alternate_PrecomputationKey = Alternate_PrecomputationKeyBuffer.Buffer; } //Initialization(Part 1) std::vector<SOCKET_DATA> UDPSocketDataList; std::vector<DNSCURVE_SOCKET_SELECTING_TABLE> UDPSocketSelectingDataList; std::unique_ptr<uint8_t[]> SendBuffer(nullptr); std::unique_ptr<uint8_t[]> Alternate_SendBuffer(nullptr); DNSCURVE_SERVER_DATA *PacketTarget = nullptr; size_t DataLength = 0, Alternate_DataLength = 0; memset(OriginalRecv, 0, RecvSize); //Socket precomputation DNSCurve_SocketPrecomputation(IPPROTO_UDP, OriginalSend, SendSize, RecvSize, &PrecomputationKey, &Alternate_PrecomputationKey, &PacketTarget, UDPSocketDataList, UDPSocketSelectingDataList, QueryType, LocalSocketData, SendBuffer, DataLength, Alternate_SendBuffer, Alternate_DataLength); if (UDPSocketDataList.empty() || UDPSocketDataList.size() != UDPSocketSelectingDataList.size()) return EXIT_FAILURE; //Socket selecting structure initialization for (auto &SocketSelectingItem:UDPSocketSelectingDataList) { //Encryption mode if (DNSCurveParameter.IsEncryption) { DNSCurve_PacketTargetSetting(SocketSelectingItem.ServerType, &PacketTarget); SocketSelectingItem.ReceiveMagicNumber = PacketTarget->ReceiveMagicNumber; //Alternate if (SocketSelectingItem.ServerType == DNSCURVE_SERVER_TYPE::ALTERNATE_IPV6 || SocketSelectingItem.ServerType == DNSCURVE_SERVER_TYPE::ALTERNATE_IPV4) { SocketSelectingItem.PrecomputationKey = Alternate_PrecomputationKey; SocketSelectingItem.SendBuffer = Alternate_SendBuffer.get(); SocketSelectingItem.SendSize = Alternate_DataLength; } //Main else { SocketSelectingItem.PrecomputationKey = PrecomputationKey; SocketSelectingItem.SendBuffer = SendBuffer.get(); SocketSelectingItem.SendSize = DataLength; } } //Normal mode else { SocketSelectingItem.SendBuffer = const_cast<uint8_t *>(OriginalSend); SocketSelectingItem.SendSize = SendSize; } SocketSelectingItem.RecvLen = 0; SocketSelectingItem.IsPacketDone = false; } //Socket selecting ssize_t ErrorCode = 0; const auto RecvLen = SocketSelectingOnce(REQUEST_PROCESS_TYPE::DNSCURVE_MAIN, IPPROTO_UDP, UDPSocketDataList, &UDPSocketSelectingDataList, nullptr, 0, OriginalRecv, RecvSize, &ErrorCode, &LocalSocketData); if (ErrorCode == WSAETIMEDOUT && !Parameter.AlternateMultipleRequest) //Mark timeout. { if (UDPSocketDataList.front().AddrLen == sizeof(sockaddr_in6)) ++AlternateSwapList.TimeoutTimes.at(ALTERNATE_SWAP_TYPE_DNSCURVE_UDP_IPV6); else if (UDPSocketDataList.front().AddrLen == sizeof(sockaddr_in)) ++AlternateSwapList.TimeoutTimes.at(ALTERNATE_SWAP_TYPE_DNSCURVE_UDP_IPV4); } //Close all sockets. for (auto &SocketItem:UDPSocketDataList) { if (SocketSetting(SocketItem.Socket, SOCKET_SETTING_TYPE::INVALID_CHECK, false, nullptr)) SocketSetting(SocketItem.Socket, SOCKET_SETTING_TYPE::CLOSE, false, nullptr); } return RecvLen; }
//Transmission of DNSCurve UDP protocol size_t DNSCurve_UDP_RequestSingle( const uint8_t * const OriginalSend, const size_t SendSize, uint8_t * const OriginalRecv, const size_t RecvSize, const uint16_t QueryType, const SOCKET_DATA &LocalSocketData) { //Initialization std::vector<SOCKET_DATA> UDPSocketDataList(1U); memset(&UDPSocketDataList.front(), 0, sizeof(UDPSocketDataList.front())); UDPSocketDataList.front().Socket = INVALID_SOCKET; DNSCURVE_SOCKET_SELECTING_TABLE UDPSocketSelectingData; DNSCURVE_SERVER_DATA *PacketTarget = nullptr; bool *IsAlternate = nullptr; size_t *AlternateTimeoutTimes = nullptr; memset(OriginalRecv, 0, RecvSize); const auto SendBuffer = OriginalRecv; //Socket initialization ssize_t RecvLen = SelectTargetSocketSingle(REQUEST_PROCESS_TYPE::DNSCURVE_MAIN, IPPROTO_UDP, QueryType, &LocalSocketData, &UDPSocketDataList.front(), &IsAlternate, &AlternateTimeoutTimes, nullptr, &UDPSocketSelectingData.ServerType, reinterpret_cast<void **>(&PacketTarget)); if (RecvLen == EXIT_FAILURE || UDPSocketSelectingData.ServerType == DNSCURVE_SERVER_TYPE::NONE) { SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::CLOSE, false, nullptr); PrintError(LOG_LEVEL_TYPE::LEVEL_2, LOG_ERROR_TYPE::NETWORK, L"DNSCurve UDP socket initialization error", 0, nullptr, 0); return EXIT_FAILURE; } //Make Precomputation Key between client and server. uint8_t *Client_PublicKey = nullptr, *PrecomputationKey = nullptr; std::unique_ptr<uint8_t[]> Client_PublicKey_Buffer(nullptr); std::unique_ptr<uint8_t[]> PrecomputationKeyBuffer(nullptr); if (DNSCurveParameter.IsEncryption && DNSCurveParameter.IsClientEphemeralKey) { auto Client_PublicKey_BufferTemp = std::make_unique<uint8_t[]>(crypto_box_PUBLICKEYBYTES); auto PrecomputationKeyBufferTemp = std::make_unique<uint8_t[]>(crypto_box_BEFORENMBYTES); std::swap(Client_PublicKey_Buffer, Client_PublicKey_BufferTemp); std::swap(PrecomputationKeyBuffer, PrecomputationKeyBufferTemp); Client_PublicKey = Client_PublicKey_Buffer.get(); PrecomputationKey = PrecomputationKeyBuffer.get(); if (!DNSCurve_PrecomputationKeySetting(PrecomputationKey, Client_PublicKey, PacketTarget->ServerFingerprint)) { SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::CLOSE, false, nullptr); return EXIT_FAILURE; } } else { PrecomputationKey = PacketTarget->PrecomputationKey; Client_PublicKey = DNSCurveParameter.Client_PublicKey; } //Socket attribute setting(Timeout) and UDP connecting if (!SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::TIMEOUT, true, &DNSCurveParameter.DNSCurve_SocketTimeout_Unreliable) || SocketConnecting(IPPROTO_UDP, UDPSocketDataList.front().Socket, reinterpret_cast<const sockaddr *>(&UDPSocketDataList.front().SockAddr), UDPSocketDataList.front().AddrLen, nullptr, 0) == EXIT_FAILURE) { SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::CLOSE, false, nullptr); return EXIT_FAILURE; } //Make encryption or normal packet. RecvLen = DNSCurve_PacketEncryption(IPPROTO_UDP, PacketTarget->SendMagicNumber, Client_PublicKey, PrecomputationKey, OriginalSend, SendSize, SendBuffer, RecvSize); if (RecvLen < static_cast<const ssize_t>(DNS_PACKET_MINSIZE)) { SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::CLOSE, false, nullptr); return EXIT_FAILURE; } //Socket selecting structure initialization std::vector<DNSCURVE_SOCKET_SELECTING_TABLE> UDPSocketSelectingDataList; if (DNSCurveParameter.IsEncryption) //Encryption mode { UDPSocketSelectingData.PrecomputationKey = PrecomputationKey; UDPSocketSelectingData.ReceiveMagicNumber = PacketTarget->ReceiveMagicNumber; UDPSocketSelectingData.SendBuffer = SendBuffer; UDPSocketSelectingData.SendSize = RecvLen; } else { //Normal mode UDPSocketSelectingData.SendBuffer = const_cast<uint8_t *>(OriginalSend); UDPSocketSelectingData.SendSize = SendSize; } UDPSocketSelectingData.RecvLen = 0; UDPSocketSelectingData.IsPacketDone = false; UDPSocketSelectingDataList.push_back(std::move(UDPSocketSelectingData)); //Socket selecting ssize_t ErrorCode = 0; RecvLen = SocketSelectingOnce(REQUEST_PROCESS_TYPE::DNSCURVE_MAIN, IPPROTO_UDP, UDPSocketDataList, &UDPSocketSelectingDataList, nullptr, 0, OriginalRecv, RecvSize, &ErrorCode, &LocalSocketData); if (ErrorCode == WSAETIMEDOUT && !Parameter.AlternateMultipleRequest) //Mark timeout. { if (UDPSocketDataList.front().AddrLen == sizeof(sockaddr_in6)) ++AlternateSwapList.TimeoutTimes.at(ALTERNATE_SWAP_TYPE_DNSCURVE_UDP_IPV6); else if (UDPSocketDataList.front().AddrLen == sizeof(sockaddr_in)) ++AlternateSwapList.TimeoutTimes.at(ALTERNATE_SWAP_TYPE_DNSCURVE_UDP_IPV4); } //Close all sockets. if (SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::INVALID_CHECK, false, nullptr)) SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::CLOSE, false, nullptr); return RecvLen; }
//Get signature data from server via UDP request bool DNSCurve_SignatureRequest_UDP( const uint16_t Protocol, const bool IsAlternate) { //Initialization const auto SendBuffer = std::make_unique<uint8_t[]>(PACKET_NORMAL_MAXSIZE + MEMORY_RESERVED_BYTES); const auto RecvBuffer = std::make_unique<uint8_t[]>(PACKET_NORMAL_MAXSIZE + MEMORY_RESERVED_BYTES); memset(SendBuffer.get(), 0, PACKET_NORMAL_MAXSIZE + MEMORY_RESERVED_BYTES); memset(RecvBuffer.get(), 0, PACKET_NORMAL_MAXSIZE + MEMORY_RESERVED_BYTES); std::vector<SOCKET_DATA> UDPSocketDataList(1U); memset(&UDPSocketDataList.front(), 0, sizeof(UDPSocketDataList.front())); UDPSocketDataList.front().Socket = INVALID_SOCKET; //Make packet data(Part 1). const auto DNS_Header = reinterpret_cast<dns_hdr *>(SendBuffer.get()); auto DataLength = sizeof(dns_hdr); #if defined(ENABLE_PCAP) DNS_Header->ID = Parameter.DomainTest_ID; #else GenerateRandomBuffer(&DNS_Header->ID, sizeof(DNS_Header->ID), nullptr, 0, 0); #endif DNS_Header->Flags = hton16(DNS_FLAG_REQUEST_STANDARD); DNS_Header->Question = hton16(UINT16_NUM_ONE); if (Protocol == AF_INET6) { if (IsAlternate) DataLength += StringToPacketQuery(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv6.ProviderName, SendBuffer.get() + DataLength, PACKET_NORMAL_MAXSIZE - DataLength); else //Main DataLength += StringToPacketQuery(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv6.ProviderName, SendBuffer.get() + DataLength, PACKET_NORMAL_MAXSIZE - DataLength); } else if (Protocol == AF_INET) { if (IsAlternate) DataLength += StringToPacketQuery(DNSCurveParameter.DNSCurve_Target_Server_Alternate_IPv4.ProviderName, SendBuffer.get() + DataLength, PACKET_NORMAL_MAXSIZE - DataLength); else //Main DataLength += StringToPacketQuery(DNSCurveParameter.DNSCurve_Target_Server_Main_IPv4.ProviderName, SendBuffer.get() + DataLength, PACKET_NORMAL_MAXSIZE - DataLength); } else { return false; } reinterpret_cast<dns_qry *>(SendBuffer.get() + DataLength)->Type = hton16(DNS_TYPE_TEXT); reinterpret_cast<dns_qry *>(SendBuffer.get() + DataLength)->Classes = hton16(DNS_CLASS_INTERNET); DataLength += sizeof(dns_qry); //EDNS Label DataLength = Add_EDNS_LabelToPacket(SendBuffer.get(), DataLength, PACKET_NORMAL_MAXSIZE, nullptr); //Socket initialization(Part 1) std::wstring Message; size_t TotalSleepTime = 0; ssize_t RecvLen = 0; auto FileModifiedTime = GlobalRunningStatus.ConfigFileModifiedTime; auto ServerType = DNSCURVE_SERVER_TYPE::NONE; const auto PacketTarget = DNSCurve_SelectSignatureTargetSocket(Protocol, IsAlternate, ServerType, UDPSocketDataList); if (PacketTarget == nullptr) { SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::CLOSE, false, nullptr); PrintError(LOG_LEVEL_TYPE::LEVEL_2, LOG_ERROR_TYPE::SYSTEM, L"DNSCurve UDP Signature Request module Monitor terminated", 0, nullptr, 0); return false; } //Send request. while (!GlobalRunningStatus.IsNeedExit) { //Sleep time controller if (TotalSleepTime > 0) { //Configuration files have been changed. if (FileModifiedTime != GlobalRunningStatus.ConfigFileModifiedTime) { FileModifiedTime = GlobalRunningStatus.ConfigFileModifiedTime; TotalSleepTime = 0; } //Interval time is not enough. else if (TotalSleepTime < DNSCurveParameter.KeyRecheckTime) { TotalSleepTime += Parameter.FileRefreshTime; //Next loop Sleep(Parameter.FileRefreshTime); continue; } //Interval time is enough, next recheck time. else { TotalSleepTime = 0; } } //Socket initialization(Part 2) if (Protocol == AF_INET6) UDPSocketDataList.front().Socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); else if (Protocol == AF_INET) UDPSocketDataList.front().Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); else goto JumpTo_Restart; if (!SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::INVALID_CHECK, true, nullptr) || !SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::NON_BLOCKING_MODE, true, nullptr) || (Protocol == AF_INET6 && !SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::HOP_LIMITS_IPV6, true, nullptr)) || (Protocol == AF_INET && (!SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::HOP_LIMITS_IPV4, true, nullptr) || !SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::DO_NOT_FRAGMENT, true, nullptr)))) goto JumpTo_Restart; //Socket selecting RecvLen = SocketSelectingOnce(REQUEST_PROCESS_TYPE::DNSCURVE_SIGN, IPPROTO_UDP, UDPSocketDataList, nullptr, SendBuffer.get(), DataLength, RecvBuffer.get(), PACKET_NORMAL_MAXSIZE, nullptr, nullptr); if (RecvLen < static_cast<const ssize_t>(DNS_PACKET_MINSIZE)) { goto JumpTo_Restart; } else { //Check signature. if (!DNSCruve_GetSignatureData(RecvBuffer.get() + DNS_PACKET_RR_LOCATE(RecvBuffer.get(), PACKET_NORMAL_MAXSIZE), ServerType) || CheckEmptyBuffer(PacketTarget->ServerFingerprint, crypto_box_PUBLICKEYBYTES) || CheckEmptyBuffer(PacketTarget->SendMagicNumber, DNSCURVE_MAGIC_QUERY_LEN)) goto JumpTo_Restart; } //Wait for sending again. TotalSleepTime += Parameter.FileRefreshTime; continue; //Jump here to restart. JumpTo_Restart: SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::CLOSE, false, nullptr); //Print error log. PrintLog_DNSCurve(ServerType, Message); if (!Message.empty()) { Message.append(L"UDP get signature data error"); PrintError(LOG_LEVEL_TYPE::LEVEL_3, LOG_ERROR_TYPE::DNSCURVE, Message.c_str(), 0, nullptr, 0); } else { PrintError(LOG_LEVEL_TYPE::LEVEL_3, LOG_ERROR_TYPE::DNSCURVE, L"UDP get signature data error", 0, nullptr, 0); } //Send request again. memset(RecvBuffer.get(), 0, PACKET_NORMAL_MAXSIZE + MEMORY_RESERVED_BYTES); if (!Parameter.AlternateMultipleRequest) { if (ServerType == DNSCURVE_SERVER_TYPE::MAIN_IPV6) ++AlternateSwapList.TimeoutTimes.at(ALTERNATE_SWAP_TYPE_DNSCURVE_UDP_IPV6); else if (ServerType == DNSCURVE_SERVER_TYPE::MAIN_IPV4) ++AlternateSwapList.TimeoutTimes.at(ALTERNATE_SWAP_TYPE_DNSCURVE_UDP_IPV4); } //Next loop Sleep(SENDING_INTERVAL_TIME); } //Loop terminated SocketSetting(UDPSocketDataList.front().Socket, SOCKET_SETTING_TYPE::CLOSE, false, nullptr); if (!GlobalRunningStatus.IsNeedExit) PrintError(LOG_LEVEL_TYPE::LEVEL_2, LOG_ERROR_TYPE::SYSTEM, L"DNSCurve UDP Signature Request module Monitor terminated", 0, nullptr, 0); return true; }
//Transmission and reception of SOCKS protocol(UDP) size_t __fastcall SOCKSUDPRequest( 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, UDPSocketData(new SOCKET_DATA()), LocalSocketData; memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE); memset(UDPSocketData.get(), 0, sizeof(SOCKET_DATA)); if (!Parameter.SOCKS_UDP_NoHandshake) { std::shared_ptr<SOCKET_DATA> TCPSocketDataTemp(new SOCKET_DATA()), LocalSocketDataTemp(new SOCKET_DATA()); TCPSocketDataTemp.swap(TCPSocketData); LocalSocketDataTemp.swap(LocalSocketData); memset(TCPSocketData.get(), 0, sizeof(SOCKET_DATA)); memset(LocalSocketData.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 { 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 if (!Parameter.SOCKS_UDP_NoHandshake && !SocketSetting(TCPSocketData->Socket, SOCKET_SETTING_INVALID_CHECK, nullptr) || !SocketSetting(UDPSocketData->Socket, SOCKET_SETTING_INVALID_CHECK, nullptr)) { closesocket(UDPSocketData->Socket); if (!Parameter.SOCKS_UDP_NoHandshake) closesocket(TCPSocketData->Socket); PrintError(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, nullptr) || !SocketSetting(UDPSocketData->Socket, SOCKET_SETTING_NON_BLOCKING_MODE, nullptr)) { closesocket(UDPSocketData->Socket); if (!Parameter.SOCKS_UDP_NoHandshake) 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)); //UDP transmission of standard SOCKS protocol must connect with TCP to server first. if (!Parameter.SOCKS_UDP_NoHandshake) { //Selection exchange process if (!SOCKSSelectionExchange(TCPSocketData.get(), ReadFDS.get(), WriteFDS.get(), Timeout.get(), 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_ERROR_NETWORK, L"SOCKS connecting error", 0, nullptr, 0); return EXIT_FAILURE; } //Client command request process if (!SOCKSClientCommandRequest(IPPROTO_UDP, TCPSocketData->Socket, ReadFDS.get(), WriteFDS.get(), Timeout.get(), SendBuffer.get(), OriginalRecv, RecvSize, LocalSocketData.get())) { 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_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); *(PUINT16)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); *(PUINT16)SOCKS_Pointer = Parameter.SOCKS_TargetServer.IPv4.sin_port; } else if (Parameter.SOCKS_TargetDomain != nullptr && Parameter.SOCKS_TargetDomain_Length > 0) //Damain { ((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type = SOCKS5_ADDRESS_DOMAIN; SOCKS_Pointer = SendBuffer.get() + RecvLen; RecvLen += (SSIZE_T)sizeof(uint8_t); *(PUINT8)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, Parameter.SOCKS_TargetDomain_Length); RecvLen += (SSIZE_T)Parameter.SOCKS_TargetDomain_Length; SOCKS_Pointer = SendBuffer.get() + RecvLen; *(PUINT16)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; //Data exchange RecvLen = SOCKSSocketSelecting(UDPSocketData->Socket, ReadFDS.get(), WriteFDS.get(), Timeout.get(), SendBuffer.get(), RecvLen, OriginalRecv, RecvSize, sizeof(socks_udp_relay_request) + DNS_PACKET_MINSIZE); 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) { //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)) == EXIT_SUCCESS && *(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))); return RecvLen - (SSIZE_T)(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_un.S_addr == Parameter.SOCKS_TargetServer.IPv4.sin_addr.S_un.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))); return RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t)); } else if (Parameter.SOCKS_TargetDomain != nullptr && Parameter.SOCKS_TargetDomain_Length > 0) //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, Parameter.SOCKS_TargetDomain_Length) == EXIT_SUCCESS && *(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))); return RecvLen - (SSIZE_T)(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))); return RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t)); } // 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)); } } 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; }
//Windows Firewall Test bool __fastcall FirewallTest( const uint16_t Protocol) { //Initialization std::shared_ptr<sockaddr_storage> SockAddr(new sockaddr_storage()); memset(SockAddr.get(), 0, sizeof(sockaddr_storage)); SYSTEM_SOCKET FirewallSocket = 0; //Ramdom number distribution initialization std::uniform_int_distribution<int> RamdomDistribution(DYNAMIC_MIN_PORT, UINT16_MAX - 1U); //IPv6 if (Protocol == AF_INET6) { ((PSOCKADDR_IN6)SockAddr.get())->sin6_addr = in6addr_any; ((PSOCKADDR_IN6)SockAddr.get())->sin6_port = htons((uint16_t)RamdomDistribution(*GlobalRunningStatus.RamdomEngine)); SockAddr->ss_family = AF_INET6; FirewallSocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); //Bind local socket. if (!SocketSetting(FirewallSocket, SOCKET_SETTING_INVALID_CHECK, nullptr)) { return false; } else if (bind(FirewallSocket, (PSOCKADDR)SockAddr.get(), sizeof(sockaddr_in6)) == SOCKET_ERROR) { ((PSOCKADDR_IN6)SockAddr.get())->sin6_port = htons((uint16_t)RamdomDistribution(*GlobalRunningStatus.RamdomEngine)); size_t Index = 0; while (bind(FirewallSocket, (PSOCKADDR)SockAddr.get(), sizeof(sockaddr_in6)) == SOCKET_ERROR) { if (Index < LOOP_MAX_TIMES && WSAGetLastError() == WSAEADDRINUSE) { ((PSOCKADDR_IN6)SockAddr.get())->sin6_port = htons((uint16_t)RamdomDistribution(*GlobalRunningStatus.RamdomEngine)); ++Index; continue; } else { closesocket(FirewallSocket); return false; } } } } //IPv4 else { ((PSOCKADDR_IN)SockAddr.get())->sin_addr.s_addr = INADDR_ANY; ((PSOCKADDR_IN)SockAddr.get())->sin_port = htons((uint16_t)RamdomDistribution(*GlobalRunningStatus.RamdomEngine)); SockAddr->ss_family = AF_INET; FirewallSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //Bind local socket. if (!SocketSetting(FirewallSocket, SOCKET_SETTING_INVALID_CHECK, nullptr)) { return false; } else if (bind(FirewallSocket, (PSOCKADDR)SockAddr.get(), sizeof(sockaddr_in)) == SOCKET_ERROR) { ((PSOCKADDR_IN)SockAddr.get())->sin_port = htons((uint16_t)RamdomDistribution(*GlobalRunningStatus.RamdomEngine)); size_t Index = 0; while (bind(FirewallSocket, (PSOCKADDR)SockAddr.get(), sizeof(sockaddr_in)) == SOCKET_ERROR) { if (Index < LOOP_MAX_TIMES && WSAGetLastError() == WSAEADDRINUSE) { ((PSOCKADDR_IN)SockAddr.get())->sin_port = htons((uint16_t)RamdomDistribution(*GlobalRunningStatus.RamdomEngine)); ++Index; continue; } else { closesocket(FirewallSocket); return false; } } } } closesocket(FirewallSocket); return true; }
//Independent request process bool __fastcall EnterRequestProcess( DNS_PACKET_DATA Packet, const SOCKET_DATA LocalSocketData) { //Initialization(Send buffer part) std::shared_ptr<char> SendBuffer; if (Packet.Protocol == IPPROTO_UDP) { if (Parameter.CompressionPointerMutation) { if (Parameter.CPM_PointerToAdditional) { std::shared_ptr<char> SendBufferTemp(new char[Packet.Length + 2U + sizeof(dns_record_aaaa) + sizeof(uint16_t)]()); memset(SendBufferTemp.get(), 0, Packet.Length + 2U + sizeof(dns_record_aaaa) + sizeof(uint16_t)); SendBufferTemp.swap(SendBuffer); Packet.BufferSize = Packet.Length + 2U + sizeof(dns_record_aaaa) + sizeof(uint16_t); } else if (Parameter.CPM_PointerToRR) { std::shared_ptr<char> SendBufferTemp(new char[Packet.Length + 2U + sizeof(uint16_t)]()); memset(SendBufferTemp.get(), 0, Packet.Length + 2U + sizeof(uint16_t)); SendBufferTemp.swap(SendBuffer); Packet.BufferSize = Packet.Length + 2U + sizeof(uint16_t); } else { //Pointer to header std::shared_ptr<char> SendBufferTemp(new char[Packet.Length + 1U + sizeof(uint16_t)]()); memset(SendBufferTemp.get(), 0, Packet.Length + 1U + sizeof(uint16_t)); SendBufferTemp.swap(SendBuffer); Packet.BufferSize = Packet.Length + 1U + sizeof(uint16_t); } } else { std::shared_ptr<char> SendBufferTemp(new char[Packet.Length + sizeof(uint16_t)]()); //Reserved 2 bytes for TCP header length. memset(SendBufferTemp.get(), 0, Packet.Length + sizeof(uint16_t)); SendBufferTemp.swap(SendBuffer); Packet.BufferSize = Packet.Length + sizeof(uint16_t); } memcpy_s(SendBuffer.get(), Packet.BufferSize, Packet.Buffer, Packet.Length); Packet.Buffer = SendBuffer.get(); } //Initialization(Receive buffer part) std::shared_ptr<char> RecvBuffer; size_t RecvSize = 0; if (Parameter.RequestMode_Transport == REQUEST_MODE_TCP || Packet.Protocol == IPPROTO_TCP || //TCP request Parameter.LocalProtocol_Transport == REQUEST_MODE_TCP || //Local request Parameter.SOCKS_Proxy && Parameter.SOCKS_Protocol_Transport == REQUEST_MODE_TCP || //SOCKS TCP request Parameter.HTTP_Proxy //HTTP Proxy request #if defined(ENABLE_LIBSODIUM) || Parameter.DNSCurve && DNSCurveParameter.DNSCurveProtocol_Transport == REQUEST_MODE_TCP //DNSCurve TCP request #endif ) //TCP { std::shared_ptr<char> TCPRecvBuffer(new char[LARGE_PACKET_MAXSIZE + sizeof(uint16_t)]()); memset(TCPRecvBuffer.get(), 0, LARGE_PACKET_MAXSIZE + sizeof(uint16_t)); RecvBuffer.swap(TCPRecvBuffer); RecvSize = LARGE_PACKET_MAXSIZE; } else { //UDP std::shared_ptr<char> UDPRecvBuffer(new char[PACKET_MAXSIZE + sizeof(uint16_t)]()); memset(UDPRecvBuffer.get(), 0, PACKET_MAXSIZE + sizeof(uint16_t)); RecvBuffer.swap(UDPRecvBuffer); RecvSize = PACKET_MAXSIZE; } //Local request process if (Packet.IsLocal && LocalRequestProcess(Packet, RecvBuffer.get(), RecvSize, LocalSocketData)) { //Fin TCP request connection. if (Packet.Protocol == IPPROTO_TCP && SocketSetting(LocalSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr)) { shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); } return true; } //Compression Pointer Mutation if (Parameter.CompressionPointerMutation && ((pdns_hdr)Packet.Buffer)->Additional == 0) { auto DataLength = MakeCompressionPointerMutation(Packet.Buffer, Packet.Length); if (DataLength > Packet.Length) Packet.Length = DataLength; } //SOCKS proxy request process if (Parameter.SOCKS_Proxy) { //SOCKS request if (SOCKSRequestProcess(Packet, RecvBuffer.get(), RecvSize, LocalSocketData)) return true; //SOCKS Proxy Only mode if (Parameter.SOCKS_Only) { //Fin TCP request connection. if (Packet.Protocol == IPPROTO_TCP && SocketSetting(LocalSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr)) { shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); } return true; } } //HTTP proxy request process if (Parameter.HTTP_Proxy) { //HTTP request if (HTTPRequestProcess(Packet, RecvBuffer.get(), RecvSize, LocalSocketData)) return true; //HTTP Proxy Only mode if (Parameter.HTTP_Only) { //Fin TCP request connection. if (Packet.Protocol == IPPROTO_TCP && SocketSetting(LocalSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr)) { shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); } return true; } } //Direct Request request process if (Parameter.DirectRequest > DIRECT_REQUEST_MODE_NONE && DirectRequestProcess(Packet, RecvBuffer.get(), RecvSize, true, LocalSocketData)) { //Fin TCP request connection. if (Packet.Protocol == IPPROTO_TCP && SocketSetting(LocalSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr)) { shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); } return true; } //DNSCurve request process #if defined(ENABLE_LIBSODIUM) if (Parameter.DNSCurve) { //DNSCurve check if (DNSCurveParameter.IsEncryption && Packet.Length + DNSCRYPT_BUFFER_RESERVE_LEN > DNSCurveParameter.DNSCurvePayloadSize) goto SkipDNSCurve; //DNSCurve request if (DNSCurveRequestProcess(Packet, RecvBuffer.get(), RecvSize, LocalSocketData)) return true; //DNSCurve Encryption Only mode if (DNSCurveParameter.IsEncryptionOnly) { //Fin TCP request connection. if (Packet.Protocol == IPPROTO_TCP && SocketSetting(LocalSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr)) { shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); } return true; } } //Jump here to skip DNSCurve process. SkipDNSCurve: #endif //TCP request process if ((Parameter.RequestMode_Transport == REQUEST_MODE_TCP || Packet.Protocol == IPPROTO_TCP) && TCPRequestProcess(Packet, RecvBuffer.get(), RecvSize, LocalSocketData)) return true; //Direct request when Pcap Capture module is not available. #if defined(ENABLE_PCAP) if (!Parameter.PcapCapture) { #endif DirectRequestProcess(Packet, RecvBuffer.get(), RecvSize, false, LocalSocketData); //Fin TCP request connection. if (Packet.Protocol == IPPROTO_TCP && SocketSetting(LocalSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr)) { shutdown(LocalSocketData.Socket, SD_BOTH); closesocket(LocalSocketData.Socket); } return true; #if defined(ENABLE_PCAP) } //UDP request RecvBuffer.reset(); UDPRequestProcess(Packet, LocalSocketData); return true; #endif }