C SOCKS5 代理接口未从代理服务器接收任何内容。

Posted

技术标签:

【中文标题】C SOCKS5 代理接口未从代理服务器接收任何内容。【英文标题】:C SOCKS5 proxy interface not receiving anything from proxy server. 【发布时间】:2014-11-20 02:54:47 【问题描述】:

我制作了一个简单的 SOCKS5 代理 RFC 1928 实现,使用 C 套接字与在 localhost:9050 上运行的我的 Tor 守护程序进行通信。它可以编译并且工作正常,但是由于它没有 recv() 任何东西,所以它被阻塞了。

代码如下:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int main(int argc, char** argv) 

    struct addrinfo hints, *res;
    int sockfd;
    memset(&hints,0,sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo("localhost","9050",&hints,&res);

    sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
    int connected = connect(sockfd,res->ai_addr,res->ai_addrlen);
    if (connected == -1) 
        perror("Error");
    
    char buffer[256];
    char msginit[256];
    msginit[0] = '\5'; //Protocol number
    msginit[1] = '\2'; //# of authentication methods
    msginit[2] = '\0'; //no authentication 
    msginit[3] = '\2'; //user+pass auth

    //get dest
    memset(&hints,0,sizeof hints);
    memset(res,0,sizeof *res);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo("duckduckgo.com","80",&hints,&res);
    struct sockaddr_in *ip = (struct sockaddr_in *)res->ai_addr;
    uint32_t* addr=&(ip->sin_addr.s_addr);

    //copy dest to request
    memcpy (msginit+4,addr,sizeof (uint32_t)); 

    send(sockfd, (void *)msginit, (size_t)strlen(msginit),0);
    printf("Sent.\n");
    recv(sockfd,buffer,256,0); //This is where it gets stuck!
    printf("%s\n",buffer);

【问题讨论】:

它没有被卡住......你只是收到了 1 次,因为你调用了一次 recv。将 recv 函数放在一个循环中,它会打印你发送的消息多次。 我只尝试接收一次。它甚至没有这样做。 strace 显示它在调用 recv() 时卡住了。 【参考方案1】:

我在下面的回答是错误的。更深入地研究它,有一个握手过程,还有更多需要发生的事情。我会在接下来的几天内回复我的想法。 (这也是我正在为自己做的事情)


就您的代码而言,您只会从响应中提取前 256 个字节。

有几个选项,具体取决于您需要多快的数据。最后,您可能不会看到太多差异(如果有的话)。但你确实有选择。

1 - 发出 立即 的 recv 调用开始一个循环,该循环一直运行,直到您获得整个响应。如果您尽快需要数据,我建议您使用此方法。确保在那里有一个 sleep/usleep 调用,否则你会很难在 CPU 上旋转。

它可能看起来像这样:

send(sockfd, (void *)msginit, (size_t)strlen(msginit),0);
printf("Sent.\n");
while (len_recv = recv(sockfd,buffer,256,0))
    if (len_recv > 0)
        // there was an error. handle it here.
     
    // copy your buffer if you need to, otherwise...
    printf("%s",buffer);
    usleep(10000);

2 - 使用 MSG_WAITALL 选项,它将阻塞接收调用,直到它从请求的服务器接收到整个消息,然后从套接字中提取所有数据。这就是我每天处理数百万个套接字请求的方式。

len_recv = recv(sockfd,buffer,256,MSG_WAITALL);
if (len_recv > 0)
    // start a while loop like above
    // copy the buffer if you need to, or...
    printf("%s",buffer);

就我个人而言,在我的代码运行速度非常快(每天数亿个请求)中,我使用了 MSG_WAITALL 选项和足够大的缓冲区来满足我的需要,这样我就不会循环我的 recv 调用。这可能对您不起作用,但好处是您不必在循环中考虑额外的 cpu 周期。如果您正在执行大量请求或需要解析数据而不仅仅是转储输出,这将特别方便。

如果您能提供更多关于您如何使用它的详细信息,我可以整理出更完整和经过测试的代码示例,并提供更直接的建议。

【讨论】:

以上是关于C SOCKS5 代理接口未从代理服务器接收任何内容。的主要内容,如果未能解决你的问题,请参考以下文章

frp通过socks5二层代理,访问内网三层网站

HTTP代理怎么转到SOCKS5代理?

ew通过socks5一层代理-访问内网二层网络-实战篇

ew通过socks5一层代理-访问内网二层网络-实战篇

FRP和MSF搭建socks5代理&fscan扫描内网漏洞

Qt WebEngine设置socks5代理