Я играю с SOCKS5 прокси (TOR). Я могу установить соединение, но теперь я не знаю, как отправлять и получать данные в / из пункта назначения. Спасибо за помощь. Код:
#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;}
Как отправить и получить данные сейчас? Теперь мы подключены к порту 80 и, например, я хочу отправить http запрос на получение и получить ответ.
После того, как вы успешно прошли проверку подлинности с прокси-сервером и указали, к чему подключаться, вы просто отправляете / извлекаете нужные данные (в данном случае HTTP-данные), используя существующее подключение к прокси-серверу, как если бы вы подключились к цели. сервер напрямую, а не прокси. Как только сеанс прокси установлен, все последующие отправки / получения будут прозрачны для вашего приложения.
Обновить: Возможно, вы также захотите очистить свой код, чтобы его было легче читать, исправить существующую неисправную обработку ошибок и добавить некоторую дополнительную обработку ошибок, которая отсутствует:
#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;
}
Олоф, рутины, которыми ты пользуешься, чрезвычайно сложны. Если ваша цель — заставить что-то работать, я бы порекомендовал вам использовать инструмент, созданный поверх этих низкоуровневых подпрограмм.
Лучший из них — локон. На сайте curl они сравнивают себя с другими инструментами, которые вы могли бы рассмотреть: http://curl.haxx.se/docs/comparison-table.html
Изменить: хорошо, так что вы проголосовали за мой ответ. Пойдите и посмотрите на исходный код торсов, который пытается использовать эти подпрограммы. Скомпилируйте и попробуйте запустить. Это работает? Посмотрите на исходный код. Попробуйте запустить набор тестов. Это работает? Посмотрите на рутины, которые они вызывают. Многие устарели. Вы можете даже выяснить, какие процедуры устарели?
Если вы посмотрите вокруг, вы увидите, что люди, которые действительно могут передавать данные через Tor, используют curl.