Решил написать собственный прокси сервер SOCKS4. Написал два потока: Code: type TSocksMethodSel = record Version : Byte; nMethods : Byte; Methods : array [0..255] of Byte; end; type TSocks4Request = record ucVersion : Byte; ucCommand : Byte; wDestPort : Word; dwDestIp : DWORD; end; Listener: Code: function ListenerExecute(Parametr: Pointer): Integer; var _listenSock, _clientSock : TSocket; _listenAddr, _clientAddr : sockaddr_in; _size : Integer; _ExeceuteHandle : DWORD; _ClientIP : String; begin Result := 0; try _listenSock := socket(AF_INET, SOCK_STREAM, 0); try if _listenSock <> INVALID_SOCKET then begin ZeroMemory(@_listenAddr, SizeOf(_listenAddr)); _listenAddr.sin_family := AF_INET; _listenAddr.sin_port := htons(CONTROL_PORT); _listenAddr.sin_addr.S_addr := htonl(INADDR_ANY); if (bind (_listenSock, _listenAddr, SizeOf(_listenAddr)) <> INVALID_SOCKET) AND (listen (_listenSock, SOMAXCONN) <> INVALID_SOCKET) then begin while 1 = 1 do begin _size := SizeOf(_clientAddr); _clientSock := accept(_listenSock, @_clientAddr, @_size); if _clientSock <> INVALID_SOCKET then begin _ExeceuteHandle := BeginThread(nil, 0, @ConnectExecute, Pointer(_clientSock), 0, _ExeceuteHandle); if _ExeceuteHandle <> 0 then CloseHandle(_ExeceuteHandle); end; // _clientSock <> INVALID_SOCKET Sleep(300); end; // while 1 = 1 end; // bind, listen end; // _listenSock <> INVALID_SOCKET finally closesocket(_listenSock); end; finally ExitThread(0); end; end; Connect: Code: function ConnectExecute(Parametr: Pointer): Integer; var _m : TSocksMethodSel; _req4 : TSocks4Request; _clientSock, _tunnelSock : TSocket; _tunnelAddr : sockaddr_in; _tv : TTimeVal; _fset : TFDSet; _recv_len : Integer; _buffer : array [0..8191] of Byte; // 8Kb _mode : Integer; begin Result := 0; _clientSock := Integer(Parametr); try if recv(_clientSock, _m, 2, MSG_PEEK) > 0 then begin if _m.Version = 4 then begin recv(_clientSock, _req4, SizeOf(TSocks4Request), 0); if _req4.ucCommand = 1 then begin ZeroMemory(@_tunnelAddr, SizeOf(_tunnelAddr)); _tunnelAddr.sin_port := _req4.wDestPort; Move(_req4.dwDestIp, _tunnelAddr.sin_addr, SizeOf(_tunnelAddr.sin_addr)); _tunnelAddr.sin_family := AF_INET; _tunnelSock := socket(AF_INET, SOCK_STREAM, 0); // Connect _tunnelSock if connect(_tunnelSock, _tunnelAddr, SizeOf(_tunnelAddr)) <> INVALID_SOCKET Then begin // success _req4.ucCommand := $5A; // success end else begin _req4.ucCommand := $5B; // General Failure reporting in end; _req4.ucVersion := $00; // null-байт _req4.wDestPort := $00; _req4.dwDestIp := $00; // поле 1: null-байт, 1 байт // поле 2: код ответа, 1 байт: // - 0x5a = запрос предоставлен // - 0x5b = запрос отклонён или ошибочен // поле 3: 2 произвольных байта, должны быть проигнорированы // поле 4: 4 произвольных байта, должны быть проигнорированы send(_clientSock, _req4, SizeOf(TSocks4Request), 0); // 8 byte return _mode := 1; setsockopt(_tunnelSock, IPPROTO_IP, TCP_NODELAY, @_mode, SizeOf(Integer)); // now tunneling everythink _tv.tv_sec := 5000; _tv.tv_usec := 0; try while 1 = 1 do begin Sleep(100); // zzzzz.... // waiting for incoming data FD_ZERO(_fset); FD_SET(_clientSock, _fset); FD_SET(_tunnelSock, _fset); if select(0, @_fset, nil, nil, nil) <> SOCKET_ERROR then begin if FD_ISSET(_tunnelSock, _fset) then begin // data on the recvsock ZeroMemory(@_buffer, SizeOf(_buffer)); _recv_len := recv(_tunnelSock, _buffer, SizeOf(_buffer), 0); if _recv_len = SOCKET_ERROR then break; // error ? if (_recv_len <> SOCKET_ERROR) and (_recv_len > 0) then send(_clientSock, _buffer, _recv_len, 0) else break; end; if FD_ISSET(_clientSock, _fset) then begin //data on the recvsock ZeroMemory(@_buffer, SizeOf(_buffer)); _recv_len := recv(_clientSock, _buffer, SizeOf(_buffer), 0); if _recv_len = SOCKET_ERROR then break; // error ? if (_recv_len <> SOCKET_ERROR) and (_recv_len > 1) then if _buffer[0] = $00 then send(_tunnelSock, _buffer[1], _recv_len - 1, 0) else send(_tunnelSock, _buffer, _recv_len, 0) else break; end; end; // if select(0... end; finally if _req4.ucCommand = 90 then begin _mode := 0; setsockopt(_tunnelSock, IPPROTO_TCP, TCP_NODELAY, @_mode, sizeof(integer)); // close closesocket(_tunnelSock); end; end; end; // if _req4.unCommand = 1 end; // if _m.Version = 4 -> SOCKS4 end; // if recv(_clientSock....) > 0 finally ZeroMemory(@_buffer, SizeOf(_buffer)); closesocket(_clientSock); ExitThread(0); end; end; Всё вроде бы ничего, только работает как то странно. Сам сервер под debug работает вроде бы нормально, отсылает байты клиенту, но например клиент почему-то их не получает. Клиент создал на Overbytes ICS. Очень конечно интересует как бы выявить этот баг!? Так же интересует вопрос по утечке памяти, как бы проверить его на утечку памяти?! P.S. Вообще хотелось бы послушать замечания. Может кто-то подскажет где я накосячил здесь?! Где-то может неправильно работаю с Socket.