We don't display ads so we rely on your Bitcoin donations to 1KWEk9QaiJb2NwP5YFmR24LyUBa4JyuKqZ
Post date: Aug 20, 2010 1:28:35 AM
{
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,
ApplicationUnit,
SocketUnit,
ThreadUnit;
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.