Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2007.02.11;
Скачать: [xml.tar.bz2];

Вниз

Перенаправление пакетов (аля proxy)   Найти похожие ветки 

 
Griha   (2006-09-04 19:21) [0]

Есть сетевое приложение, которое работает с "127.0.0.1". Необходимо написать локальный "proxy", который будет перенаправлять все пакеты на другой сервер. Т.е. proxy получает пакет от клиента - не изменяя перенаправляет его удаленному серверу. Proxy получает пакет от удаленного сервера - не изменяя перенаправляет его клиенту. Плюс нужна возможность отправлять свои пакеты на удаленный сервер. Использую TClientSocket и TServerSocket. Как правильно реализовать поставленную задачу?


 
Griha   (2006-09-04 19:27) [1]

Делал так (SS - TSocketServer, CS - TClientServer):
У SS в ClientConnect пишу:
cs.Active:=true;

В ClientRead:
tmp:=Socket.ReceiveText;
cs.Socket.SendText(tmp);

-----
У CS в Read:
tmp:=Socket.ReceiveText;
ss.Socket.Connections[0].SendText(tmp);


Но если клиент соединяется и сразу шлет пакет (ClientRead), то CS еще не активен и не может отправить пакет удаленному серверу. Получается надо сохранять в пакеты в буффер...
Может надо использовать сокеты в блокирующем режиме? Или вообще таким способом лучше не делать?
Посоветуйте решение...


 
Dmitrij_K   (2006-09-04 19:37) [2]

В инете есть исходники Socks прокси на delphi winsock api


 
Dmitrij_K   (2006-09-04 19:40) [3]

Вот он, только надо его отлаживать, ошибки были
program dproxy;

uses
 windows,
 WinSock;

type TSOCKS4_REQUEST=record
      ucVersion : byte;
      ucCommand : byte;
      wDestPort : word;
      dwDestIp  : dword;
    end;

var
 wsaData : TWSADATA;
 sport   : string;
 iport   : word;
 l_sock  : TSocket;
 sock4   : SOCKADDR_IN;
 Client  : TSockAddr;
 Size    : integer;
 h1      : THandle;

procedure FlushRecvBufferUntil(s:TSOCKET;condition:Char);
var
 iReceiveRes : integer;
 cDummy      : char;
begin
 repeat
   iReceiveRes := recv(s, cDummy, sizeof(cDummy), 0);
 until NOT ((iReceiveRes<>SOCKET_ERROR) and (iReceiveRes<>0) and (cDummy<>condition));
end;

procedure SocksHandlerTreadProc(pParam:pointer); stdcall;
var
 s              : TSocket;
 tunnelSock     : TSocket;
 iConnectResult : integer;
 iReceiveRes    : integer;
 iSocketsSet    : integer;
 socks4Request  : TSOCKS4_REQUEST;
 socks4Response : TSOCKS4_REQUEST;
 remoteAddr     : SOCKADDR_IN;
 fds_read       : TFDset;//fd_set;
 tv             : TTimeval;
 cSocksVersion  : byte;
 iSelectResult  : integer;
 loop           : integer;
 ulVal          : u_long;
 swapBuffer     : array[0..4096*16-1] of char;
 iRecvResult    : integer;
begin
 s              := TSOCKET(pParam);
 tunnelSock     := 0;
 loop           := 0;
 while loop=0 do
 begin
   inc(loop);
   iConnectResult := 0;
   iReceiveRes    := 0;
   iSocketsSet    := 0;
   FD_ZERO(fds_read);
   FD_SET(s, fds_read);
   tv.tv_sec     := 30;
   cSocksVersion := 0;
   iSelectResult := select(0, @fds_read, nil, nil, @tv);
   if (iSelectResult=SOCKET_ERROR) or (not iSelectResult>0) then break;
   ulVal := 0;
   ioctlsocket(s, FIONBIO , ulVal);
   iReceiveRes := recv(s, cSocksVersion, 1, MSG_PEEK);
   if cSocksVersion=4 then // 3333333333333333333
   begin
     iReceiveRes := recv(s, socks4Request, sizeof(socks4Request), 0);
     if iReceiveRes=SOCKET_ERROR then break;
     ulVal := 1;
     ioctlsocket(s, FIONBIO , ulVal);
     FlushRecvBufferUntil(s, #0);
     if socks4Request.ucCommand = 1 then
     begin // 2222222222222222222
ulVal := 0;
ioctlsocket(s, FIONBIO, ulVal);
remoteAddr.sin_family := AF_INET;
move(socks4Request.dwDestIp,remoteAddr.sin_addr,sizeof(remoteAddr.sin_addr));
remoteAddr.sin_port := socks4Request.wDestPort;
tunnelSock := socket(AF_INET, SOCK_STREAM, 0);
iConnectResult := connect(tunnelSock, remoteAddr, sizeof(remoteAddr));
if (iConnectResult<>SOCKET_ERROR) then
begin // 1111111111
  socks4Response.ucCommand := 90;
  socks4Response.ucVersion := 0;
  send(s, socks4Response, sizeof(socks4Response), 0);
end else break; // 1111111111
     end else break;// 2222222222222222222
   end else break;// 3333333333333333333
   ulVal := 0;
   ioctlsocket(tunnelSock, FIONBIO, ulVal);
   ioctlsocket(s, FIONBIO, ulVal);
   fillchar(swapBuffer,sizeof(swapBuffer),0);
   tv.tv_sec := 2;
   while true do // 4444444444444444
   begin
     FD_ZERO(fds_read);
     FD_SET(s, fds_read);
     FD_SET(tunnelSock, fds_read);
     iSocketsSet := select(0, @fds_read, nil, nil, @tv); //if (iSocketsSet == SOCKET_ERROR) _leave;
     if iSocketsSet > 0 then // 5555555555555555
     begin
if FD_ISSET(s, fds_read) then
begin
  iRecvResult := recv(s, swapBuffer, sizeof(swapBuffer), MSG_PEEK);
  if (iRecvResult=0)
    then break
    else iRecvResult := recv(s, swapBuffer, sizeof(swapBuffer), 0);
  if (iRecvResult <> SOCKET_ERROR) and (iRecvResult > 0)
    then send(tunnelSock, swapBuffer, iRecvResult, 0)
    else BREAK;
end;

if (FD_ISSET(tunnelSock, fds_read)) then
begin
  iRecvResult := recv(tunnelSock, swapBuffer, sizeof(swapBuffer), MSG_PEEK);
  if iRecvResult = 0
    then break
    else iRecvResult := recv(tunnelSock, swapBuffer, sizeof(swapBuffer), 0);
  if (iRecvResult <> SOCKET_ERROR) and (iRecvResult > 0)
    then send(s, swapBuffer, iRecvResult, 0)
    else break;
end;
     end;  // 5555555555555555
   end; // 4444444444444444
 end; // while loop=0 do
 closesocket(s);
 closesocket(tunnelSock);
end;

begin
 WSAStartup(MAKEWORD(2,0), wsaData);
 l_sock                := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 sock4.sin_family      := AF_INET;
 sock4.sin_port        := htons(1080);
 sock4.sin_addr.s_addr := INADDR_ANY;
 Size                  := SizeOf(Client);
 if (Bind(l_sock,sock4,SizeOf(sock4))=0) and (Listen(l_sock,$FF)=0) then
   while true do CreateThread(nil,0,@SocksHandlerTreadProc,Pointer(accept(l_sock, @Client, @Size)),0,h1);
end.


 
Eraser ©   (2006-09-04 20:35) [4]

> [0] Griha   (04.09.06 19:21)

нужно перенапрявлять пакеты с какого-то определенного порта? если так, то нужно реализовать обычный port mapping.


 
Сергей М. ©   (2006-09-06 16:46) [5]


> Получается надо сохранять в пакеты в буффер


Получается)
Проблем-то нет)


> Может надо использовать сокеты в блокирующем режиме?


Может и надо.
Решать-то тебе .. как разработчику ...


 
Griha   (2006-09-07 11:20) [6]

2Eraser
С конкретного порта, но не просто перенаправлять, но еще и редактировать "на лету", иногда отправлять свои пакеты как серверу, так и клиенту.

2Сергей М.

> Решать-то тебе .. как разработчику ...

Так как я еще далеко не опытный разработчик, а только учусь, то хотел бы услышать совет мастеров.
Проблема в том, что каждый пакет кодируется XOR"ом по ключу. А ключ меняется в зависимости от содержимого пакета. Сейчас использую асинхронные сокеты и ключ частенько сбивается. Проблема может заключаться как раз в этих асинхронных сокетах? Или ошибку надо искать в другом месте?
... и еще часто возникает ошибка "Asynchronous socket error 10053"


 
Сергей М. ©   (2006-09-07 11:28) [7]


> Проблема может заключаться как раз в этих асинхронных сокетах?


Проблема не в них, проблема в твоем непонимании особенностей работы с гнездами в асинхронном неблок.режиме. И кодировка здесь совершенно ни при чем.


 
Griha   (2006-09-07 11:37) [8]

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


 
Сергей М. ©   (2006-09-07 11:46) [9]


> первый не разобран


> приходит еще один пакет


> Начинается разбор второго пакета


А зачем ты начинаешь разбор 2-го пакета, не закончив обработку 1-го ?


 
Griha   (2006-09-07 11:51) [10]

Вызов функции разбора пакета происходит в TClientSocket.Read... Как поступить? Использовать блокирующие сокеты? Или помещать все пакеты в буффер? Или есть другой более правильный вариант?


 
Сергей М. ©   (2006-09-07 12:22) [11]


> Вызов функции разбора пакета происходит в TClientSocket.
> Read


Ну так и разбирай там этот пакет спокойно !
А следующий за ним пакет никуда не денется - вновь возникнет событие OnRead, в котором будешь его разбирать.


> помещать все пакеты в буффер?


Да, буферизация требуется.

Ведь OnRead не есть факт доставки целостного пакета (TCP - поточно-ориентированный протокол), это лишь факт того что принимаемый поток данных не пуст и можно попытаться прочитать из него фрагмент данных требуемого размера (<=ReceiveLength).


 
Griha   (2006-09-07 12:26) [12]


> Ну так и разбирай там этот пакет спокойно !
> А следующий за ним пакет никуда не денется - вновь возникнет
> событие OnRead, в котором будешь его разбирать.

А разве событие OnRead не может произойти вложено? Т.е. в момент обработки одного OnRead сработать еще один OnRead?
---
Сейчас искал какую-нибудь хорошую статью на русском про асинхронные сокеты, но ничего не нашел - везде одно и тоже общими фразами.


 
Сергей М. ©   (2006-09-07 12:31) [13]


> А разве событие OnRead не может произойти вложено? Т.е.
> в момент обработки одного OnRead сработать еще один OnRead?
>


Нет, не может.


 
Eraser ©   (2006-09-07 18:47) [14]

> [8] Griha   (07.09.06 11:37)
> Но почему-то она всё-таки сбивается. К примеру поступает
> один пакет, начинается его разбор, а в это время приходит
> еще один пакет, пока первый не разобран и ключ еще не изменен.
> Начинается разбор второго пакета и ключ уже повреждается.
> Ведь так?

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


 
Новичоккк   (2006-09-07 22:13) [15]

Всем спасибо, программа стало работать стабильно

2Eraser
Так и есть. Первые два байта прикладного пакета - его длина. Один пакет транспортного уровня, может содержать несколько прикладных пакетов, а может только часть одного. Ключ меняется при последовательном разборе каждого пакета.



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2007.02.11;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.041 c
4-1159123295
wp2
2006-09-24 22:41
2007.02.11
NtCreateProcessEx какие параметры и их тип?


2-1169656059
NightRain
2007-01-24 19:27
2007.02.11
А можно в delphi компоненты на форме прописать в массив?


8-1150393736
SamProf
2006-06-15 21:48
2007.02.11
Mediaplayer из потока


8-1150349926
Vasiliy
2006-06-15 09:38
2007.02.11
Управление выходом видеокарты ???


15-1169484302
nomen
2007-01-22 19:45
2007.02.11
Приключение от Avast





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский