C SOCKS5 proxy interface not receiving anything from proxy server.

733 views Asked by At

I've made a simple SOCKS5 proxy RFC 1928 implementation using C sockets to communicate with my tor daemon running on localhost:9050. It compiles and works fine, but it is stuck blocking as it does not recv() anything.

The code is as follows:

#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

There are 1 answers

0
benwills On

My response below is wrong. Looking more into it, there's a handshake process and more that needs to happen. I'll respond back in the next couple days with what I come up with. (this is something I'm working on for myself as well)


As it stands with your code, you will only be pulling the first 256 bytes from the response.

There are a couple of options, depending on how quickly you want your data. In the end, you will likely not see much, if any, difference. But you do have options.

1 - Place recv calls that immediately begin a loop that runs until you have the entire response. I would suggest this method if you need your data as quickly as possible. Be sure to have a sleep/usleep call in there, or you'll spin on CPU pretty hard.

It might look something like this:

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 - Use the MSG_WAITALL option, which will block on the receive call until it has received the entire message from the requested server, then pull all the data from the socket. This is how I do it for millions of socket requests a day.

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

Personally, in my code that runs quite fast (hundreds of millions of requests a day), I use the MSG_WAITALL option with a large enough buffer for my needs so that I don't loop my recv call. That may not work for you, but the benefit is that you don't have to think about extra cpu cycles in a loop. This is especially handy if you're doing a lot of requests or need to parse your data rather than just dumping the output.

If you can give me more details on how you're using this, I can put together more complete and tested code samples, and a more direct suggestion.