Search code examples
csocketsproxywebproxy

How to create a simple Proxy to access web servers in C


I’m trying to create an small Web Proxy in C. First, I’m trying to get a webpage, sending a GET frame to the server. I don’t know what I have missed, but I am not receiving any response. I would really appreciate if you can help me to find what is missing in this code.

int main (int argc, char** argv) {
   int cache_size,     //size of the cache in KiB
       port,
       port_google = 80,
       dir,
       mySocket,
       socket_google;

   char google[] = "www.google.es", ip[16];
   struct sockaddr_in socketAddr;
   char buffer[10000000];

   if (GetParameters(argc,argv,&cache_size,&port) != 0)
       return -1;

   GetIP (google, ip);
   printf("ip2 = %s\n",ip);

   dir = inet_addr (ip);
   printf("ip3 = %i\n",dir);

   /* Creation of a socket with Google */
   socket_google = conectClient (port_google, dir, &socketAddr);
   if (socket_google < 0) return -1;
   else printf("Socket created\n");

   sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
   if (write(socket_google, (void*)buffer, MESSAGE_LENGTH+1) < 0 )
       return 1;
   else printf("GET frame sent\n");

   strcpy(buffer,"\n");
   read(socket_google, buffer, sizeof(buffer));

   // strcpy(message,buffer);
   printf("%s\n", buffer);

   return 0;
}

And this is the code I use to create the socket. I think this part is OK, but I copy it just in case.

int conectClient (int puerto, int direccion, struct sockaddr_in *socketAddr) {
   int mySocket;
   char error[1000];

   if ( (mySocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
       printf("Error when creating the socket\n");
       return -2;
   }

   socketAddr->sin_family = AF_INET;
   socketAddr->sin_addr.s_addr = direccion;
   socketAddr->sin_port = htons(puerto);

   if (connect (mySocket, (struct sockaddr *)socketAddr,sizeof (*socketAddr)) == -1) {
       snprintf(error, sizeof(error), "Error in %s:%d\n", __FILE__, __LINE__);
       perror(error);
       printf("%s\n",error);
       printf ("-- Error when stablishing a connection\n");
       return -1;
   }
   return mySocket;
}

Thanks!


Solution

  • Since you didn't post the GetIP routine, I am not certain that your hostname lookup is correct, as from the looks of it, I am not sure that you are using inet_addr function correctly.

    Nikolai has pointed out some very good points (and I fully agree). In fact you GET request is actually broken, and while I was testing it on my own local Apache web server on my system, it didn't work.

    sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
    if (write(socket_google, (void*)buffer, LONGITUD_MSJ+1) < 0 )
        return 1;
    else printf("GET frame sent\n");
    ...
    
    strcpy(buffer,"\n");
    read(socket_google, buffer, sizeof(buffer));
    

    should be replaced with

      snprintf(buffer, sizeof(buffer), 
          "GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: TEST 0.1\r\n\r\n", 
          google);
    
      if (write(socket_google, buffer, strlen(buffer)+1) < 0 ) {
          close(socket_google);
          return 1;
      } else 
          printf("GET frame sent\n");
      ...
    
      buffer[0] = '\0';
      /* Read message from socket */
      bytes_recv = read(socket_google, buffer, sizeof(buffer));
      if (bytes_recv < 0) {
           fprintf(stderr, "socket read error: %s\n", strerror(errno));
           close(socket_google);
           exit(10);
      }
    
      buffer[bytes_recv] = '\0';    /* NUL character */
    
      /* strcpy(message,buffer); */
      printf("%s\n", buffer);
    
      ...
    

    You should also close the socket before exiting the program. Enable standard C89/90 or C99 mode of your compiler (e.g. -std=c99 for gcc) and enable warnings (e.g. -Wall for gcc), and read them. And #include the necessary header files (assuming Linux in my case) for function prototypes:

     #include <stdio.h>
     #include <stdlib.h>
     #include <string.h>
     #include <unistd.h>
     #include <errno.h>
     #include <sys/types.h>
     #include <sys/socket.h>
     #include <netinet/in.h>
     #include <arpa/inet.h>
     #include <netdb.h>      /* for gethostbyname() */
    

    There is some casting of pointers and structs in regards to the hostname / IP address resolving, which can be confusing and easy place to make a mistake, so verify that is working as you expect it is.

     in_addr_t ip;
     ...
    
     GetIP(google, &ip);   /* I changed the parameters */
     printf("IP address = %x (%s)\n", 
         ip, 
         inet_ntoa(*((struct in_addr*)&ip)));