{ Example Socks4 Proxy by Aphex Here is a perfect example of the small and stable applications that can be created using my units. This multithreaded Socks4 proxy server covers the entire Socks4 protocol and is only 11KB compressed. } program Socks4; {..$APPTYPE CONSOLE} uses Windows, Winsock, type TSocks4Header = packed record bVn: byte; bCd: byte; wPort: word; dIP: in_addr; end; const ServerPort: integer = 6699; var Application: TApplication; ServerSocket: TServerSocket; threadvar ClientSocket: TClientSocket; Socks4Header: TSocks4Header; procedure RelayData(Socket1, Socket2: TClientSocket); var Buffer: array [0..32767] of byte; BytesReceived: integer; Nonblocking: integer; begin //put sockects into nonblocking mode ioctlsocket(Socket1.Socket, FIONBIO, Longint(Nonblocking)); ioctlsocket(Socket2.Socket, FIONBIO, Longint(Nonblocking)); while ((Socket1.Connected) and (Socket2.Connected)) do begin //try to receive some data from the first socket BytesReceived := Socket1.ReceiveBuffer(Buffer, 32768); if BytesReceived > 0 then begin //loop until we can successfully relay to the second while Socket2.SendBuffer(Buffer, BytesReceived) = -1 do Sleep(1); end; //try to receive some data from the second socket BytesReceived := Socket2.ReceiveBuffer(Buffer, 32768); if BytesReceived > 0 then begin //loop until we can successfully relay to the first while Socket1.SendBuffer(Buffer, BytesReceived) = -1 do Sleep(1); end; Sleep(1); end; end; procedure ProxyConnection(Address: in_addr; Port: word); var ProxyClientSocket: TClientSocket; begin { The first type of connection is like a simple port redirect. The remote client requests us to make a connection on their behalf, we make the connection and then begin relaying traffic between the two. } ProxyClientSocket := TClientSocket.Create; ProxyClientSocket.Connect(string(inet_ntoa(Address)), ntohs(Port)); Socks4Header.bVn := 0; if ProxyClientSocket.Connected then begin Socks4Header.bCd := 90; end else begin Socks4Header.bCd := 91; ProxyClientSocket.Disconnect; ProxyClientSocket.Free; Exit; end; ClientSocket.SendBuffer(Socks4Header, sizeof(Socks4Header)); RelayData(ClientSocket, ProxyClientSocket); ProxyClientSocket.Disconnect; ProxyClientSocket.Free; end; procedure ProxyBinding(Address: in_addr; Port: word); var ProxyClientSocket: TClientSocket; ProxyServerSocket: TServerSocket; begin { The second is more complex, it binds a local port to the remote client and waits for an incomming connection. Once the connection is made traffic begins relaying as normally. We can reuse the same relay for both types of connections. } ProxyServerSocket := TServerSocket.Create; ProxyServerSocket.Listen(0); Socks4Header.bVn := 0; Socks4Header.bCd := 90; Socks4Header.dIP := TInAddr(inet_addr(pchar(ProxyServerSocket.LocalAddress))); Socks4Header.wPort := htons(ProxyServerSocket.LocalPort); ClientSocket.SendBuffer(Socks4Header, sizeof(Socks4Header)); ProxyServerSocket.Idle; ProxyClientSocket := ProxyServerSocket.Accept; if ProxyClientSocket.Connected then begin if ProxyClientSocket.RemoteAddress = string(inet_ntoa(Address)) then begin Socks4Header.bCd := 90; end else begin Socks4Header.bCd := 91; ProxyClientSocket.Disconnect; ProxyClientSocket.Free; Exit; end; end else begin Socks4Header.bCd := 91; ProxyClientSocket.Disconnect; ProxyClientSocket.Free; Exit; end; Socks4Header.dIP := TInAddr(inet_addr(pchar(ProxyClientSocket.LocalAddress))); Socks4Header.wPort := htons(ProxyClientSocket.LocalPort); ClientSocket.SendBuffer(Socks4Header, sizeof(Socks4Header)); RelayData(ClientSocket, ProxyClientSocket); ProxyClientSocket.Disconnect; ProxyClientSocket.Free; ProxyServerSocket.Free; end; procedure Client(Thread: TThread); var UserID: string; begin Thread.Lock; try //accept the new connection ClientSocket := ServerSocket.Accept; finally Thread.Unlock; end; //receive header ClientSocket.ReceiveBuffer(Socks4Header, sizeof(Socks4Header)); //only handle version 4 if Socks4Header.bVn = 4 then begin //receive userid UserID := ClientSocket.ReceiveString; if Socks4Header.bCd = 1 then begin //handle connect ProxyConnection(Socks4Header.dIP, Socks4Header.wPort); end else if Socks4Header.bCd = 2 then begin //handle bind ProxyBinding(Socks4Header.dIP, Socks4Header.wPort); end; end; ClientSocket.Disconnect; Thread.Free; end; procedure Startup; begin ServerSocket := TServerSocket.Create; ServerSocket.Listen(ServerPort); end; procedure Main; begin //wait for incomming connections ServerSocket.Idle; //create a new thread for each new connection TThread.Create(Client); end; procedure Shutdown; begin ServerSocket.Free; end; begin Application := TApplication.Create; Application.Startup := Startup; Application.Main := Main; Application.Shutdown := Shutdown; Application.StayResident; Application.Free; end.
Only Delphi source code is included in the archive. |
Delphi Basics - Free Delphi Source Code - Ultimate Programming Resource > Delphi Basics Snippets >