[ Прокси туннелирование ]

Прокси серверы представляют из себя компьютеры с установленным 
специализированным программным обеспечением и являются, по сути, 
обработчиками разнообразных запросов со стороны клиента и передачи 
их дальше по сети. Они играют большую роль в функционировании 
компьютерных сетей, как локальных, так и глобальной сети Интернет.


Различают следующие виды прокси серверов:

- шлюз(proxy-gate), основное назначение такого сервера, это 
подключение локальных сетей к Интернету используя один IP адрес;

- анонимный прокси(анонимайзер), служит для скрытия реального IP 
адрес компьютера, что дает возможность анонимной работы в сети;

- файрволы(firewall), защита локальных сетей от посягательств из вне;

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


В основном прокси серверы используются для скрытия собственного IP 
адреса клиента и замене его на свой, это происходит благодаря тому 
что, а прокси сервер изменяет заголовок приходящего пакета. 
Рассмотрим алгоритм работы связки host-proxy-target, где прокси 
работает по HTTP протоколу, например локальный хост хочет получить 
html страницу с хоста www.target.ru, для этого:

1. клиент устанавливает соединение с прокси сервером.

2. клиент посылает команду:

       CONNECT www.target.ru:port_target HTTP/1.0

       User-Agent: TestApp

3. Прокси сервер возвращает код состояния, либо запрос авторизации, 
либо код успешной обработки команды или ошибку.

4. Если нужна авторизация то команда примет следующий вид:

       CONNECT www.target.ru:port_target HTTP/1.0

       User-agent: TestApp

       Proxy-authorization: basic password

5. Если ошибок не было и соединение установлено успешно, то клиент 
посылает запрос:

       GET /index.htm HTTP/1.0

       Host: www.target.ru

6. Прокси сервер создает сокет и устанавливает соединение с 
www.target.ru и посылает запрос от клиента.

7. Прокси сервер получает ответ от www.target.ru и пересылает его 
клиенту.

 

Для более лучшего понимания алгоритма работы с прокси сервером, 
рассмотрим исходный текст программы, созданной в среде VC++ 6.0, тип 
приложения “Win32 Console Application”:

-------------[cut here]-------------------

//тип прокси сервера HTTP

#include <iostream.h>

#include <conio.h>

#include <stdio.h>

#include <windows.h>

//Подключение Winsock

#pragma comment(lib, "ws2_32.lib")

 

int main()

{

        WSADATA wsaData;

         //стартуем Winsock

        if(!WSAStartup(0x0202,&wsaData))

        {

                cout<<"WSAStartup is ok"<<endl;

                //создаем сокет через который будем

                //работать с прокси сервером

                SOCKET s_kproxy = socket(AF_INET,SOCK_STREAM,0);

                if(s_kproxy != SOCKET_ERROR)

                {

                        sockaddr_in proxy;

                        proxy.sin_family      = AF_INET;

                        //указываем порт прокси сервера

                        proxy.sin_port        = htons(8080);

                        //IP адрес прокси сервера

                        proxy.sin_addr.s_addr = inet_addr("*.*.*.*");

                        //конектимся к серверу

                        if(connect(s_kproxy,(PSOCKADDR)&proxy,sizeof(proxy)) != SOCKET_ERROR)

                        {

                                char szBuffer[10240];

                                sprintf(szBuffer,

                                "CONNECT %s:%d HTTP/1.0\r\nUser-Agent: TestApp\r\n\r\n",

                                "www.target.ru",80);

                                //посылаем команду CONNECT

                                if(send(s_kproxy,szBuffer,strlen(szBuffer),0))

                                {

                                        cout<<"Send - status ok"<<endl;

                                        memset(szBuffer,0,sizeof(szBuffer));

                                        //ждем ответа от прокси сервера

                                        if(recv(s_kproxy,szBuffer,10240,0))

                                        {

                                                cout<<"Buffer: "<<szBuffer<<endl;

                                                //В данном примере нету обработки

                                                //ответа от прокси сервера, предполагается

                                                //что авторизация не нужна и соединение установлено

                                                //успешно...

                                                ZeroMemory(szBuffer,sizeof(szBuffer));

                                                //формируем запрос

                                                lstrcpy(szBuffer,"GET /index.htm HTTP/1.0\r\n");

                                                lstrcat(szBuffer,"Host: www.target.ru\r\n");

                                                lstrcat(szBuffer,"User-Agent: TestApp\r\n\r\n");

                                                //посылаем запрос получения страницы    

                                                if(send(s_kproxy,szBuffer,strlen(szBuffer),0))

                                                {

                                                        cout<<"Send GET - status ok"<<endl;

                                                        ZeroMemory(szBuffer,sizeof(szBuffer));

                                                        //ждем саму страницу

                                                        if(recv(s_kproxy,szBuffer,10240,0))

                                                        {

                                                                cout<<"HTML: "<<endl<<szBuffer<<endl;

 

                                                        }else{cout<<"ERROR: recv 2"<<endl;}

                                                }else{cout<<"ERROR: send GET"<<endl;}

                                        }else{cout<<"ERROR: recv"<<endl;}

                                }else{cout<<"ERROR: send"<<endl;}

                        }else{cout<<"ERROR: connect"<<endl;}

                        //закрываем сокет

                        closesocket(s_kproxy);

                }else{cout<<"ERROR: socket"<<endl;}

                //прекращаем работу Winsock

                if(!WSACleanup())

                {cout<<"WSACleanup is ok"<<endl;}

                else{cout<<"ERROR: WSACleanup"<<endl;}

        }else{cout<<"ERROR: WSAStartup"<<endl;}

 

        cout<<"Press any key to exit"<<endl;

        while(!getch());

        return 0;

}

-------------[cut here]-------------------

Также можно создать цепочку из нескольких прокси серверов, для 
того чтобы максимально скрыть ваш реальный IP адрес. Изменим выше 
приведенный пример для работы цепочки host-proxy-proxy-target:

-------------[cut here]-------------------
...

connect(…);

char szBuffer[10240];

//формируем команду к прокси №1, для соединения с прокси №2

sprintf(szBuffer,       "CONNECT %s:%d HTTP/1.0\r\nUser-Agent: TestApp\r\n\r\n","192.168.0.155",8080);

                                

if(send(s_kproxy,szBuffer,strlen(szBuffer),0))

{

        cout<<"Send - status ok"<<endl;

        memset(szBuffer,0,sizeof(szBuffer));

        //ждем ответа от прокси №1

        if(recv(s_kproxy,szBuffer,10240,0))

        {

                cout<<"Buffer: "<<szBuffer<<endl;

                memset(szBuffer,0,sizeof(szBuffer));

                //формируем команду к прокси №2 для соединения с целью

                sprintf(szBuffer,

                                        "CONNECT %s:%d HTTP/1.0\r\nUser-Agent: TestApp\r\n\r\n",

                            "www.code.hut1.ru",80);

                if(send(s_kproxy,szBuffer,strlen(szBuffer),0))

                {

                        cout<<"Send - status ok"<<endl;

                        memset(szBuffer,0,sizeof(szBuffer));

                        if(recv(s_kproxy,szBuffer,10240,0))

                        {

                                cout<<"Buffer: "<<szBuffer<<endl;

                                ZeroMemory(szBuffer,sizeof(szBuffer));

                                //запрос

                                lstrcpy(szBuffer,"GET /test.htm HTTP/1.0\r\n");

                                lstrcat(szBuffer,"Host: www.code.hut1.ru\r\n");

                                lstrcat(szBuffer,"User-Agent: TestApp\r\n\r\n");

                                if(send(s_kproxy,szBuffer,strlen(szBuffer),0))

                                {

                                        cout<<"Send GET - status ok"<<endl;

                                        ZeroMemory(szBuffer,sizeof(szBuffer));

                                        if(recv(s_kproxy,szBuffer,10240,0))

                                        {cout<<"HTML: "<<endl<<szBuffer<<endl;}

                                        else{cout<<"ERROR: recv 2"<<endl;}

                                                                

                                }else{cout<<"ERROR: send GET"<<endl;}

                             }else{cout<<"ERROR: recv CONNECT"<<endl;}

                      }else{cout<<"ERROR: send CONNECT"<<endl;}

                }else{cout<<"ERROR: recv"<<endl;}

}else{cout<<"ERROR: send"<<endl;}

closesocket(…);

...
-------------[cut here]-------------------

На этом пока все, надеюсь, вам пригодится выше изложенное.

(c) Lazy_elf