Send and receive via SOCKS5 C ++

I play with the SOCKS5 proxy (TOR). I can establish a connection, but now I do not know how to send and receive data to / from the destination. Thanks for the help. The code:

#include <stdio.h> #include <WinSock2.h> #include <stdlib.h> #pragma comment(lib,"ws2_32.lib") #define PUT_BYTE(ptr,data) (*(unsigned char*)ptr = data) int main() { WORD wVersionRequested = MAKEWORD(2,0); WSADATA wsaData; if(WSAStartup(wVersionRequested,&wsaData) != 0 ) { return 1; } int fd = socket( AF_INET, SOCK_STREAM, 0); if (fd < 0) return 1; struct sockaddr_in destaddr; destaddr.sin_addr.s_addr = inet_addr("xx.xx.xx.xx"); int dest_port = 80; struct sockaddr_in saddr; saddr.sin_port = htons(9150); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); int rv = connect( fd, (struct sockaddr *)&saddr, sizeof(saddr)); if(rv < SOCKET_ERROR) return 1; char buf[256], *ptr; ptr = buf; PUT_BYTE( ptr++,5); PUT_BYTE( ptr++,1); PUT_BYTE(ptr++,0x00); send(fd,buf,ptr-buf,0); recv(fd,buf,2,0); if ( (buf[0] != 5) || buf[1] == 0xFF ) { return 1; } ptr = buf; PUT_BYTE(ptr++,5); PUT_BYTE(ptr++,1); PUT_BYTE(ptr++,0); PUT_BYTE(ptr++,1); memcpy( ptr, &destaddr.sin_addr.s_addr,sizeof(destaddr.sin_addr)); ptr += sizeof(destaddr.sin_addr); PUT_BYTE(ptr++,dest_port>>8); PUT_BYTE(ptr++,dest_port&0xFF); send(fd,buf,ptr-buf,0); recv(fd,buf,4,0); if(buf[1] != 0x00) { return 1; } ptr = buf + 4; switch ( buf[3] ) { case 1: recv( fd, ptr, 4+2,0 ); break; case 3: recv( fd, ptr, 1 ,0); recv( fd, ptr+1, *(unsigned char*)ptr + 2,0); break; case 4: recv( fd, ptr, 16+2,0 ); break; } printf("Succes!"); //How to send and receive data now? Now we are connected on port 80 and for example I want to send http get request and receive the answer. return 0; } 

How to send and receive data now? Now we are connected to port 80 and, for example, I want to send an http get request and get a response.

+4
source share
2 answers

After you have successfully authenticated using a proxy server and told with which connection, you simply send / return the necessary data (in this case, HTTP data) using the existing connection with the proxy server, as if you were connecting to the target server directly, not to the proxy. After establishing a proxy session, all subsequent sending / receiving are transparent to your application.

Update:. You can also clear your code to make it easier to read, correct existing broken error handling, and add additional error handling:

 #include <stdio.h> #include <WinSock2.h> #include <stdlib.h> #pragma comment(lib,"ws2_32.lib") #include <pshpack1.h> struct socks5_ident_req { unsigned char Version; unsigned char NumberOfMethods; unsigned char Methods[256]; }; struct socks5_ident_resp { unsigned char Version; unsigned char Method; }; struct socks5_req { unsigned char Version; unsigned char Cmd; unsigned char Reserved; unsigned char AddrType; union { in_addr IPv4; in6_addr IPv6; struct { unsigned char DomainLen; char Domain[256]; }; } DestAddr; unsigned short DestPort; }; struct socks5_resp { unsigned char Version; unsigned char Reply; unsigned char Reserved; unsigned char AddrType; union { in_addr IPv4; in6_addr IPv6; struct { unsigned char DomainLen; char Domain[256]; }; } BindAddr; unsigned short BindPort; }; #include <poppack.h> bool sendData(SOCKET fd, void *data, int len) { char *ptr = (char *) data; while (len > 0) { int sent = send(fd, ptr, len, 0); if (sent <= 0) { printf("send() error: %d", WSAGetLastError()); return false; } ptr += sent; len -= sent; } return true; } int recvData(SOCKET fd, void *data, int len, bool disconnectOk = false) { char *ptr = (char *) data; int total = 0; while (len > 0) { int recvd = recv(fd, ptr, len, 0); if (recvd < 0) { printf("recv() error: %d", WSAGetLastError()); return -1; } if (recvd == 0) { if (disconnectOk) break; printf("disconnected"); return -1; } ptr += recvd; len -= recvd; total -= recvd; } return total; } bool socksLogin(SOCKET fd) { socks5_ident_req req; socks5_ident_req resp; req.Version = 5; req.NumberOfMethods = 1; req.Methods[0] = 0x00; // add other methods as needed... if (!sendData(fd, &req, 2+req.NumberOfMethods)) return false; if (recvData(fd, &resp, sizeof(resp)) == -1) return false; if (resp.Version != 5) { printf("SOCKS v5 identification failed"); return false; } if (resp.Method == 0xFF) { printf("SOCKS v5 authentication failed"); return false; } /* if (resp.Method != 0x00) { // authenticate as needed... } */ return true; } bool socksRequest(SOCKET fd, const socks5_req &req, socks5_resp &resp) { memset(&resp, 0, sizeof(resp)); if (!sendData(fd, &req, 4)) return false; switch (req.AddrType) { case 1: { if (!sendData(fd, &(req.DestAddr.IPv4), sizeof(in_addr))) return false; break; } case 3: { if (!sendData(fd, &(req.DestAddr.DomainLen), 1)) return false; if (!sendData(fd, req.DestAddr.Domain, req.DestAddr.DomainLen)) return false; break; } case 4: { if (!sendData(fd, &(req.DestAddr.IPv6), sizeof(in6_addr))) return false; break; } default: { printf("SOCKS 5 requesting unknown address type"); return false; } } unsigned short port = htons(req.DestPort); if (!sendData(fd, &port, 2)) return false; if (recvData(fd, &resp, 4) == -1) return false; switch (resp.AddrType) { case 1: { if (recvData(fd, &(resp.BindAddr.IPv4), sizeof(in_addr)) == -1) return false; break; } case 3: { if (recvData(fd, &(resp.BindAddr.DomainLen), 1) == -1) return false; if (recvData(fd, resp.BindAddr.Domain, resp.BindAddr.DomainLen) == -1) return false; break; } case 4: { if (recvData(fd, &(resp.BindAddr.IPv6), sizeof(in6_addr)) == -1) return false; break; } default: { printf("SOCKS 5 bound to unknown address type"); return false; } } if (recvData(fd, &port, 2, 0) == -1) return false; resp.BindPort = ntohs(port); return true; } bool socksConnect(SOCKET fd, const in_addr &dest, unsigned short port) { socks5_req req; socks5_resp resp; req.Version = 5; req.Cmd = 1; req.Reserved = 0; req.AddrType = 1; req.DestAddr.IPv4 = dest; req.DestPort = port; if (!socksRequest(fd, req, resp)) return false; if (resp.Reply != 0x00) { printf("SOCKS v5 connect failed, error: 0x%02X", resp.Reply); return false; } return true; } int main() { WSADATA wsaData; int rv = WSAStartup(MAKEWORD(2,0), &wsaData); if (rv != 0) { printf("WSAStartup() error: %d", rv); return 1; } SOCKET fd = socket( AF_INET, SOCK_STREAM, 0); if (fd == INVALID_SOCKET) { printf("socket() error: %d", WSAGetLastError()); return 1; } struct sockaddr_in saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = inet_addr("127.0.0.1"); saddr.sin_port = htons(9150); if (connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)) != 0) { printf("connect() error: %d", WSAGetLastError()); return 1; } if (!socksLogin(fd)) return 1; if (!socksConnect(fd, inet_addr("xx.xx.xx.xx"), 80)) return 1; printf("Success!"); // now send/receive desired data as needed using existing fd ... return 0; } 
+9
source

Olof, the procedures you use are known to be complicated. If your goal is to actually get something useful, I would recommend that you use a tool that was built on top of these low-level procedures.

The best of them is curl. On the curl site, they are compared with other tools you might consider: http://curl.haxx.se/docs/comparison-table.html

Edit: everything is in order, so you voted for my answer. Go and look at the source code for torsos that tries to use these routines. Compile it and try to run it. It works? Not. Look at the source code. Try running the test suite. It works? Not. Look at the routines that they call. Many of them are outdated. Can you determine which routines are out of date?

If you look around you will see that people who can actually transfer data through Tor use curl.

-one
source

Source: https://habr.com/ru/post/1496184/


All Articles