Прокси туннелирование. Часть 2 . Прокси серверы представляют из себя компьютеры с установленным специализированным программным обеспечением и являются, по сути, обработчиками разнообразных запросов со стороны клиента и передачи их дальше по сети. Они играют большую роль в функционировании компьютерных сетей, как локальных, так и глобальной сети Интернет.
Различают следующие виды прокси серверов:
- шлюз(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”:
//тип прокси сервера 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; }
Также можно создать цепочку из нескольких прокси серверов, для того чтобы максимально скрыть ваш реальный IP адрес. Изменим выше приведенный пример для работы цепочки host-proxy-proxy-target:
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(…);
На этом пока все, надеюсь, вам пригодится выше изложенное.