Skip to content

Instantly share code, notes, and snippets.

@shiponcs
Last active July 8, 2021 05:44
Show Gist options
  • Select an option

  • Save shiponcs/9ac5e77a54efbd8a88844aa78cdff0e2 to your computer and use it in GitHub Desktop.

Select an option

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.
#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;
}
#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