Как подключить сокет к HTTP-серверу через прокси?

Недавно я написал программу, использующую сокеты в C, для подключения к HTTP-серверу, работающему локально, и тем самым делать запросы к этому.

Это сработало для меня. После этого я попробовал тот же код для подключения к другому серверу в Интернете (например, www.google.com), но я не смог подключиться и получал еще один html-ответ от прокси-сервера в моей сети.

  • Мой локальный IP: 10.0.2.58
  • IP-адрес прокси-сервера: 10.0.0.1

Это ответ, который я получил:

HTTP/1.1 302 Found
Expires: Fri, 10 Feb 2012 12:47:35 GMT
Expires: 0
Cache-Control: max-age=180000
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Connection: close
Location: http://10.0.0.1:8000/index.php?redirurl=http%3A%2F%2F10.0.2.58%2F
Content-type: text/html
Content-Length: 0
Date: Wed, 08 Feb 2012 10:47:35 GMT
Server: lighttpd/1.4.29

Как я могу обойти этот прокси для подключения к внешним серверам?


Ответ получен при попытке с помощью CONNECT

HTTP/1.1 302 Found
Expires: Fri, 10 Feb 2012 13:37:58 GMT
Expires: 0
Cache-Control: max-age=180000
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Connection: close
Location: http://10.0.0.1:8000/index.php?redirurl=http%3A%2F%2F10.0.2.58http%3A%2F%2Fwww.google.com%2F
Content-type: text/html
Content-Length: 0
Date: Wed, 08 Feb 2012 11:37:58 GMT
Server: lighttpd/1.4.29

Рабочий код, который подключается к моему локальному apache

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

#define MAX_BUFFER_SIZE 1024

int main(int argc,char *argv[])
{
  int clsd,ssd,status;
  char buffer[1024];
  char request[]="GET / HTTP/1.1\r\nHost:10.0.2.58\r\n\r\n";
  struct sockaddr_in srvr_addr;

  struct addrinfo hints,*res;

  srvr_addr.sin_family=AF_INET;
  srvr_addr.sin_port=htons(80);
  srvr_addr.sin_addr.s_addr=inet_addr("10.0.2.58");//Local server

  clsd =socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  if(clsd<=0)
  {
        perror("Socket init failed..\n");return 1;
  }
  ssd=connect(clsd,(struct sockaddr *)&srvr_addr,(socklen_t)(sizeof srvr_addr));
  if(clsd<=0)
  {
        perror("Socket connect failed..\n");return 1;
  }
  write(clsd,request,strlen(request));
  memset((void *)&request,0x00,strlen(request));
  memset(&buffer,0x00,MAX_BUFFER_SIZE);

 do
 {
  status=read(clsd,&buffer,MAX_BUFFER_SIZE);
  write(1,&buffer,status);
 memset((void *)&request,0x00,strlen(request));
  memset(&buffer,0x00,MAX_BUFFER_SIZE);

 do
 {
  status=read(clsd,&buffer,MAX_BUFFER_SIZE);
  write(1,&buffer,status);
 }while(status>0);
 close(clsd); 
 return 0;
}

Ответ 1

Чтобы использовать подключения через прокси (или если они неявно прокси-фид), сначала вы должны подключиться к прокси, отправить сообщение "CONNECT" с целевым хостом; прокси установит соединение и вернет вам данные.

Вот шаги:

  • открыть сокет для прокси-хоста
  • отправить ' CONNECT http://www.google.com:80 HTTP/1.0\r\n\r\n' строка
  • ждать recv

Вы должны указать протокол (в нашем случае это HTTP 1.0, non-chunked) с окончанием символов новой строки, поэтому прокси-сервер знает, как связаться с конечной точкой.

Подробные сведения о методе CONNECT можно найти в http://www.ietf.org/rfc/rfc2817.txt

Ответ 2

Если вы специально пытаетесь обойти прокси-сервер, вам следует поговорить с тем, кто администрирует вашу сеть, чтобы узнать, возможно ли это. Если ваш первый блок вывода - это попытка подключения к Google, то мне кажется, что в вашей сети есть какой-то прозрачный прокси-сервер, который вам придется выполнять специальные (и сетевые) шаги для обхода.

Конечно, если вы просто заинтересованы в получении данных, вы можете попробовать выполнить перенаправление...