Last active
July 8, 2021 05:44
-
-
Save shiponcs/9ac5e77a54efbd8a88844aa78cdff0e2 to your computer and use it in GitHub Desktop.
It simply sends an encoded STUN Bind request, and parse the Bind response to find the public IP and port. And, the Sender mimics the way a STUN server sends a Bind Response. These both file can be used together to achieve the goal of getting the public IP and port, but the server file must run in any remote host.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <sys/socket.h> | |
| #include <arpa/inet.h> | |
| #include <sys/types.h> | |
| #include <netinet/in.h> | |
| #include <string> | |
| void printMsg(std::string msg) | |
| { | |
| std::cout << msg << std::endl; | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| int socket_fd = socket(AF_INET, SOCK_DGRAM, 0); | |
| sockaddr_in destination, myself; | |
| //init this client | |
| // myself.sin_family = AF_INET; | |
| // myself.sin_addr.s_addr = INADDR_ANY; | |
| // myself.sin_port = htons(atoi(argv[3])); | |
| // int bind_status = bind(socket_fd, (sockaddr *)&myself, sizeof(myself)); | |
| // if (bind_status < 0) | |
| // printMsg("Bindng failed"); | |
| // init destination i.e. host | |
| destination.sin_family = AF_INET; | |
| //destination.sin_addr.s_addr = inet_addr(argv[1]); // old way | |
| int presentation_to_network = inet_pton(AF_INET, argv[1], &(destination.sin_addr)); // new way | |
| if (presentation_to_network <= 0) | |
| { | |
| printMsg("Something wrong with the given ip address"); | |
| } | |
| destination.sin_port = htons(atoi(argv[2])); | |
| int destination_len = sizeof(destination); | |
| static const unsigned char header[] = { | |
| 0x00, 0x01, 0x00, 0x00, 0x21, 0x12, | |
| 0xa4, 0x42, 0x35, 0x68, 0x38, 0x7a, 0x6a, 0x63, | |
| 0x4a, 0x2f, 0x72, 0x4f, 0x53, 0x4b}; | |
| int send_status = sendto(socket_fd, &header, sizeof(header), 0, (sockaddr *)&destination, sizeof(destination)); | |
| if (send_status < 0) | |
| printMsg("Sending failed"); | |
| char buffer[1024] = {0}; | |
| int receive_status = recvfrom(socket_fd, buffer, 1024, 0, (sockaddr *)&destination, (socklen_t *)&destination_len); | |
| std::cout << receive_status << std::endl; | |
| if (receive_status < 0) | |
| printMsg("receivng failed"); | |
| int stun_method, msg_length; | |
| short attr_type; | |
| short attr_length; | |
| short port; | |
| short n; | |
| unsigned short return_port=0; | |
| char return_ip[32]; | |
| int i; | |
| if (*(short *)(&buffer[0]) == htons(0x0101)) | |
| { | |
| printMsg("STUN binding resp: success !\n"); | |
| // parse XOR | |
| n = htons(*(short *)(&buffer[2])); | |
| i = 20; | |
| while (i < sizeof(buffer)) | |
| { | |
| attr_type = htons(*(short *)(&buffer[i])); | |
| attr_length = htons(*(short *)(&buffer[i + 2])); | |
| std::cout << attr_length << std::endl; | |
| if (attr_type == 0x0020) | |
| { | |
| // parse : port, IP | |
| port = ntohs(*(short *)(&buffer[i + 6])); | |
| port ^= 0x2112; | |
| printf("port = %d\n",(unsigned short)port); | |
| printf("ip = %u.", (unsigned char)(buffer[i+8] ^ 0x21)); | |
| printf("%u.",(unsigned char)(buffer[i+9] ^ 0x12)); | |
| printf("%u.",(unsigned char)(buffer[i+10] ^ 0xA4)); | |
| printf("%u\n",(unsigned char)(buffer[i+11] ^ 0x42)); | |
| break; | |
| } | |
| i += (4 + attr_length); | |
| std::cout << i << std::endl; | |
| } | |
| } | |
| return 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <sys/socket.h> | |
| #include <sys/types.h> | |
| #include <netinet/in.h> | |
| #include <arpa/inet.h> | |
| #include <string> | |
| #include <string.h> | |
| void printMsg(std::string msg) | |
| { | |
| std::cout << msg << std::endl; | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| int socket_fd = socket(AF_INET, SOCK_DGRAM, 0); | |
| sockaddr_in | |
| source_addr, | |
| client_addr; | |
| source_addr.sin_family = AF_INET; | |
| source_addr.sin_port = htons(atoi(argv[1])); | |
| source_addr.sin_addr.s_addr = INADDR_ANY; | |
| int bind_status = bind(socket_fd, (sockaddr *)&source_addr, sizeof(source_addr)); | |
| if (bind_status < 0) | |
| printMsg("binding failed"); | |
| socklen_t client_len = sizeof client_addr; | |
| while ((true)) | |
| { | |
| char buffer[1024] = {0}; | |
| int receive_status = recvfrom(socket_fd, buffer, sizeof(buffer), 0, (sockaddr *)&client_addr, &client_len); | |
| if (receive_status < 0) | |
| printMsg("Reading error"); | |
| else | |
| printMsg(buffer); | |
| //print client info | |
| // std::cout << "received from: " << inet_ntoa(client_addr.sin_addr) << ":" << ntohs(client_addr.sin_port) << std::endl; // old fashion | |
| char client_ip[INET_ADDRSTRLEN]; | |
| inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, INET_ADDRSTRLEN); // new fashion | |
| std::cout << "received from: " << client_ip << ":" << ntohs(client_addr.sin_port) << std::endl; | |
| unsigned short oct1, oct2, oct3, oct4; | |
| sscanf(client_ip, "%hu.%hu.%hu.%hu", &oct1, &oct2, &oct3, &oct4); | |
| // it's a demo response, we will edit by time | |
| static unsigned char response[] = {0x01, 0x01, 0x00, 0x44, 0x21, 0x12, | |
| 0xa4, 0x42, 0x35, 0x68, 0x38, 0x7a, 0x6a, 0x63, | |
| 0x4a, 0x2f, 0x72, 0x4f, 0x53, 0x4b, 0x00, 0x20, | |
| 0x00, 0x08, 0x00, 0x01, 0xEE, 0x85, 0xfb, 0xa8, | |
| 0x2d, 0x20, 0x80, 0x2c, 0x00, 0x08, 0x00, 0x01, | |
| 0x0d, 0x97, 0x34, 0xbb, 0x93, 0x3b, 0x80, 0x22, | |
| 0x00, 0x27, 0x45, 0x79, 0x65, 0x62, 0x61, 0x6c, | |
| 0x6c, 0x5f, 0x41, 0x6e, 0x79, 0x46, 0x69, 0x72, | |
| 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x53, 0x65, 0x72, | |
| 0x76, 0x65, 0x72, 0x5f, 0x76, 0x31, 0x30, 0x2e, | |
| 0x33, 0x2e, 0x32, 0x35, 0x38, 0x61, 0x36, 0x31, | |
| 0x64, 0x03}; | |
| // the transaction id must be same in the response, so copy it from received packet- buffer | |
| // transation id is 128-bit long identifier, it lies index 4 - 19 | |
| for (int i = 4; i <= 19; i++) | |
| { | |
| response[i] = buffer[i]; | |
| } | |
| // std::cout << htons(61061) << "**" << std::endl; | |
| int port = htons((ntohs)(client_addr.sin_port) ^ 0x2112); | |
| response[26] = (port & 0xff); | |
| response[27] = (port & 0xff00) >> 8; | |
| response[28] = (oct1 ^ buffer[4]); | |
| response[29] = (oct2 ^ buffer[5]); | |
| response[30] = (oct3 ^ buffer[6]); | |
| response[31] = (oct4 ^ buffer[7]); | |
| // std::cout << *(unsigned short *)(&response[26]) << "*" << std::endl; | |
| int send_status = sendto(socket_fd, response, sizeof(response), 0, (sockaddr *)&client_addr, sizeof client_addr); | |
| if (send_status < 0) | |
| printMsg("can't send"); | |
| // std::cout << send_status << std::endl; | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment