I was shocked at the almost complete lack of online code samples for establishing connections through a SOCKS proxy with network sockets in C. SOCKS protocol is specified in
RFC 1928.
Here is code I have used successfully to connect to a locally installed Tor SOCKS proxy:
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
exit(1);
}
struct sockaddr_in s;
s.sin_family = AF_INET;
s.sin_port = htons(9050);
s.sin_addr.s_addr = inet_addr("127.0.0.1");
eid = connect(fd, (struct sockaddr *) &s, sizeof s); //Connect to Tor Proxy
if (eid < 0)
{
exit(3);
}
//SOCKS 5 protocol stuff starts here
////////////////////////////////////////////////////////////////////////////////////////////////
char sbuffer[256];
char *ptrBuff;
ptrBuff = sbuffer;
*(ptrBuff++) = 0x05; //socks protocol version 5
*(ptrBuff++) = 0x01; // supporting 1 auth method, 1) no auth 2) user pass auth
*(ptrBuff++) = 0x00;
send(fd, sbuffer, ptrBuff - sbuffer, 0);
recv(fd, sbuffer, 2, 0);
if (sbuffer[1] == 0xFF || sbuffer[1] != 0x00)
{
exit(1);
}
ptrBuff = sbuffer;
*(ptrBuff++) = 0x05; // socks version
*(ptrBuff++) = 0x01; // sending CONNECT command
*(ptrBuff++) = 0x00; // Reserved
*(ptrBuff++) = 0x03; // address type - 1 for IPV4, 3 for domain name
char* dest_addr = "irc.whatever.com";
*(ptrBuff++) = strlen(dest_addr); //first byte records length of domain name string (without the terminating NULL)
memcpy(ptrBuff, dest_addr, strlen(dest_addr));
ptrBuff += strlen(dest_addr);
unsigned int dest_port = 6667;
*(ptrBuff++) = (dest_port >> 8); //port in network byte order - reverse lil endian bytes in int
*(ptrBuff++) = (dest_port & 0xFF);
send(fd, sbuffer, ptrBuff - sbuffer, 0);
recv(fd, sbuffer, 3, 0);
if (sbuffer[1] != 0x00)
{
exit(2);
}
//////////////////////////////////////////////////////////////////////////////////
// From here on write/read from the socket as if you were directly connected to
// the desired server