Текущий архив: 2007.02.11;
Скачать: CL | DM;
ВнизПеренаправление пакетов (аля 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;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.132 c