Send and receive via SOCKS5 c++

南楼画角 提交于 2019-12-04 10:38:21

Once you have successfully authenticated with the proxy and told it where to connect to, then you simply send/recv your desired data (in this case, the HTTP data) using the existing connection to the proxy, as if you had connected to the target server directly and not to a proxy. Once the proxy session is established, all subsequent sends/receives are transparent to your app.

Update: You might also want to clean up your code so it is easier to read, fix your existing broken error handling, and add some additional error handling that is missing:

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

Olof, the routines you are using are notoriously difficult. If your goal is to actually get something working, I would recommend that you use a tool that has been built on top of these low-level routines.

The best one is curl. At the curl website, they compare themselves with the other tools you could consider: http://curl.haxx.se/docs/comparison-table.html

Edit: all right, so you voted down my answer. Go and look at the source code for torsocks, which tries to use these routines. Compile it and try to run it. Does it work? No. Look at the source code. Try to run the test suite. Does it work? No. Look at the routines they call. Many are deprecated. Can you even figure out which routines are deprecated?

If you look around, you will see that the people who are able to actually transfer data over Tor are using curl.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!