[ Прокси туннелирование ]
Прокси серверы представляют из себя компьютеры с установленным
специализированным программным обеспечением и являются, по сути,
обработчиками разнообразных запросов со стороны клиента и передачи
их дальше по сети. Они играют большую роль в функционировании
компьютерных сетей, как локальных, так и глобальной сети Интернет.
Различают следующие виды прокси серверов:
- шлюз(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