[code]
unit proxy;
interface
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;
function startproxy(p: integer): string;
implementation
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;
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
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
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
socks4Response.ucCommand := 90;
socks4Response.ucVersion := 0;
send(s, socks4Response, sizeof(socks4Response), 0);
end else break;
end else break;
end else break;
ulVal := 0;
ioctlsocket(tunnelSock, FIONBIO, ulVal);
ioctlsocket(s, FIONBIO, ulVal);
fillchar(swapBuffer,sizeof(swapBuffer),0);
tv.tv_sec := 2;
while true do
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 > 0 then
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;
end;
end;
closesocket(s);
closesocket(tunnelSock);
end;
function startproxy (p: integer): string;
begin
WSAStartup(MAKEWORD(2, 0), wsaData);
l_sock := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sock4.sin_family := AF_INET;
sock4.sin_port := htons(p);
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;
end.
[/code]