Sunteți pe pagina 1din 8

{$APPTYPE CONSOLE}

uses
SysUtils,
Windows,
WinSock,
Classes,
synautil;
type
TSocks5Config = record
Port
: Dword;
Listen : string;
UserName : String;
Password : String;
sockstype: string;
proxytype: string;
ProxyHost: string;
ProxyPort: Integer;
end;
type
TSocks5MethodSel = record
Version : Byte;
nMethods : Byte;
Methods : array[0..255] of Byte;
end;
type TSocks5Request = record
ucVersion : byte;
ucCommand : byte;
ucRzv : byte;
ucAtyp : byte;
dwDestIp : dword;
wDestPort : word;
end;
var
config: TSocks5Config;
function RecvBuffer(sock : Cardinal; var Buffer; BufferSize: Integer):Integer;
begin
if BufferSize = -1 then
begin
if ioctlsocket(sock, FIONREAD, Longint(Result)) = SOCKET_ERROR then
begin
Result := SOCKET_ERROR;
closesocket(sock);
end;
end
else begin
Result := WinSock.recv(sock,Buffer,BufferSize,0);
if Result = 0 then
Exit;
if Result = SOCKET_ERROR then begin
Result := WSAGetLastError;
if Result = WSAEWOULDBLOCK then

Result := 0;
end;
end;
end;
function ReceiveString(sock: Cardinal): AnsiString;
var
lCount: Integer;
Buffer: array[0..4095] of Byte;//4kb
begin
SetLength(Result,lCount);
if lCount = -1 then
begin
if ioctlsocket(sock, FIONREAD, Longint(lCount)) = SOCKET_ERROR then
begin
closesocket(sock);
end;
end
else begin
lCount := winsock.recv(sock, Buffer, SizeOf(Buffer),0);
if lCount > 0 then begin
Result := string(pchar(@buffer));
end
else
Result := '';
end;
end;
function SendBuffer(sock: Cardinal; var Buffer; BufferSize: integer): integer;
var
ErrorCode: integer;
begin
Result := send(sock, Buffer, BufferSize, 0);
if Result = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if (ErrorCode = WSAEWOULDBLOCK) then
begin
Result := -1;
end
else
begin
closesocket(sock);
end;
end;
end;
function SendString(sock: Cardinal; const Buffer: string): integer;
begin
Result := SendBuffer(sock, pointer(Buffer)^, Length(Buffer));
end;
function RelayData(recvsock, tunnelsock: TSocket):Boolean;
var
buffer
: array[0..4095] of Byte;//4kb
recv_len : Integer;
tv
: Ttimeval;
fset
: tfdset;

begin
//now tunneling everything!
tv.tv_sec := 5;
while 1 =1 Do begin
//waiting for incoming data
FD_ZERO(fset);
FD_SET(recvsock,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));
MessageBoxa(0,'Data from the tunnelsock!','FF',0);
recv_len := recv(tunnelsock, buffer,sizeof(buffer),0);
if recv_len = SOCKET_ERROR Then break; //error?
messagebox(0,PChar('tunnel' + #13#10 + pchar(@buffer)),0

//
//
,0);

send(recvsock,buffer,recv_len,0);
end;
if FD_ISSET(recvsock,fset) THEN begin //data on the recvsock
ZeroMemory(@buffer,sizeof(buffer));
MessageBoxa(0,'Data from the recvsock!','FF',0);
recv_len := recv(recvsock, buffer,sizeof(buffer),0);
if recv_len = SOCKET_ERROR Then break; //error?
messagebox(0,PChar('recv' + #13#10 + pchar(@buffer)),0,0

//
//
);
//

Writeln(string(pchar(@buffer)));
send(tunnelsock,buffer,recv_len,0);
end;
end;
Sleep(150); //zzZZzzZZZZzz
end;
// MessageBox(0,PChar('Error Code: ' + inttostr(WSAGetLastError)),'Error!',0);
end;
function sockConnect(var sock: TSocket; ProxyHost,ProxyPort: string):Boolean;
var
tunneladdr_in: TSockAddrIn;
HostEnt: PHostEnt;
begin
Result := False;
if (ProxyPort <> '') and (ProxyHost <> '') then begin
tunneladdr_in.sin_port := htons(StrToInt(ProxyPort));
tunneladdr_in.sin_family := AF_INET;
tunneladdr_in.sin_addr.S_addr := inet_addr(PChar(ProxyHost));
if tunneladdr_in.sin_addr.s_addr = INADDR_NONE then begin
HostEnt := gethostbyname(PChar(ProxyHost));
if HostEnt = nil then
begin
Exit;
end;
tunneladdr_in.sin_addr.s_addr := Longint(PLongint(HostEnt^.h_addr_list^)^)
;
end;
sock := socket(PF_INET, SOCK_STREAM, 0);
if connect(sock,tunneladdr_in,sizeof(tunneladdr_in)) = 0 Then
Result := True;
end;

end;
procedure SocksProc(sock : Cardinal); stdcall;
var
m : TSocks5MethodSel;
req : TSocks5Request;
auth :array[0..600] of Byte;
buf :array[0..500] of Byte;
buffer : array[0..4095] of Byte;//4kb
recv_len : Integer;
i,p : Integer;
recvsock : TSocket;
UserName, password : String;
tunneladdr_in : sockaddr_in;
tunneldomain : String;
tunnelsock : TSocket;
hostent : PHostEnt;
self_addr : sockaddr_in;
self_Len : Integer;
s: string;
method,uri,proto,host,port,server: string;
Prot, User, Pass, Path, Para: string;
desthost, destport: string;
payload: string;
headers: TStringList;
begin
headers:= TStringList.Create;
recvsock := sock;
if config.sockstype = 'socks5' then begin
if recv(recvsock,m,2,MSG_PEEK) > 0 then begin
if m.Version = 5 then begin
//it is socks5
recv(recvsock,m, 2 + m.nMethods,0); //request complete Header
for i := 0 to m.nMethods - 1 Do begin
if (m.Methods[i] = 2) then begin
//password auth
if (config.UserName = '') and (config.Password = '') then begin
m.nMethods := $00;
send(recvsock, m,2,0);
end else begin
m.nMethods := 2;
send(recvsock, m,2,0);
recv(recvsock, auth,SizeOf(auth),0);
if auth[0] = 1 Then begin
//get username
SetString(username,Pchar(@auth[2]),auth[1]);
//get password
SetString(password,Pchar(Cardinal(@auth) + 3 + auth[1]),auth[2 + a
uth[1]]);
if (config.UserName = UserName) and (config.Password = password) t
hen begin //auth successful!
auth[1] := 0;
send(recvsock,auth,2,0);
end else begin
MessageBox(0,'auth fail','fffuuuuuuu-',0);
auth[1] := $FF; //nothing but fail
send(recvsock,auth,2,0);
break;
end;
end;

end;
end else if (m.Methods[i] = 0) Then begin
if (config.password = '') and (config.UserName = '') Then begin
m.nMethods := 0;
send(recvsock,m,2,0);
end else begin
m.nMethods := $FF;
send(recvsock,m,2,0);
break;
end;
end else if i = m.nMethods then begin
m.nMethods := $FF;
send(recvsock,m,2,0);
Break;
end;
recv(recvsock, req, sizeof(Tsocks5Request), MSG_PEEK);
if req.ucCommand = 1 then begin
//TCP Verbindung, ok
Zeromemory(@tunneladdr_in,sizeof(tunneladdr_in));
if req.ucAtyp = 1 Then begin //ip4
recv(recvsock, req, sizeof(Tsocks5Request), 0);
tunneladdr_in.sin_addr.S_addr := req.dwDestIp;
desthost := inet_ntoa(tunneladdr_in.sin_addr);
destport := IntToStr(ntohs(req.wDestPort));
server
:= desthost;
port
:= destport;
if (config.ProxyHost <> '') and (config.ProxyPort <> 0) then begin
server := config.ProxyHost;
Port := IntToStr(config.ProxyPort);
end;
end else if req.ucAtyp = 3 Then begin //domain name
ZeroMemory(@buf,SizeOf(buf));
recv(recvsock,buf,7 + Byte(req.dwDestIp),0);
SetString(tunneldomain,PChar(Cardinal(@buf) + 5),Integer(Byte(req.dw
DestIp)));
hostent := gethostbyname(PChar(tunneldomain));
PInteger(@tunneladdr_in.sin_addr.S_addr)^:=PInteger(HostEnt.h_addr^)
^;
tunneladdr_in.sin_port := htons(Word(Pointer(Cardinal(@buf) + 6 + By
te(req.dwDestIp))^));
end; //todo: PIv6
req.ucCommand := 0;
req.ucVersion := 5;
req.ucRzv := 0;
req.ucAtyp := 1;
ZeroMemory(@self_addr,SizeOf(sockaddr_in));
self_Len := SizeOf(sockaddr_in);
getsockname(tunnelsock,self_addr,self_len);
CopyMemory(@req.dwDestIp,@self_addr.sin_addr,sizeof(self_addr.sin_addr
));
req.wDestPort := self_addr.sin_port;
send(recvsock,req,10,0);
if sockConnect(tunnelsock,server,port) Then begin//success!
if server <> desthost then
Writeln('Connecting to ' + desthost +':'+ destport +' through '+
config.ProxyHost +':'+ IntToStr(config.ProxyPort))
else

Writeln('Connecting to ' + desthost +':'+ destport)


end else begin
Writeln('Failed connecting to server ' + desthost +':'+ destport);
closesocket(recvsock);
closesocket(tunnelsock);
end;
payload := ReceiveString(recvsock);
if (Pos('GET',payload) <> 0) or
(Pos('HEAD',payload) <> 0) or
(Pos('PUT',payload) <> 0) or
(Pos('POST',payload) <> 0) or
(Pos('DELETE',payload) <> 0) or
(Pos('LINK',payload) <> 0) or
(Pos('UNLINK',payload) <> 0) then
begin
headers.Text := payload;
s := Headers[0];
if s = '' then
Exit;
method := fetch(s, ' ');
if (s = '') or (method = '') then
Exit;
uri := fetch(s, ' ');
if uri = '' then
Exit;
proto := fetch(s, ' ');
ParseURL(uri, Prot, User, Pass, Host, Port, Path, Para);
if (Host = 'localhost')and (Headers.Count > 1) then begin
for p:=0 to headers.Count - 1 do begin
if Pos('host',LowerCase(headers[p])) <> 0 then begin
Host := Copy(Headers[p], Pos(':', Headers[p]) + 1, Length(Head
ers[p]));
uri := Prot + '://' + Trim(Host) + uri;
end;
end;
end;
s := ParseURL(uri, Prot, User, Pass, Host, Port, Path, Para);
Headers[0] := method + ' ' + uri + ' ' + proto;
payload := headers.Text;
end;
if payload <> '' then begin
Writeln(payload);
SendString(tunnelsock, payload);
end;
SendString(tunnelsock, payload);
RelayData(recvsock,tunnelsock);
end;
Break;
end;
end;
end;
end;
// MessageBox(0,PChar('Error Code: ' + inttostr(WSAGetLastError)),'Error!',0);
closesocket(recvsock);

closesocket(tunnelsock);
end;
function sockBinding(var sock: TSOCKET; Listen, Port:string) : Boolean;
var
wsaData : TWSAData;
SockAddr: TSockAddrIn;
size : Integer;
begin
result := False;
WSAStartup($0101, wsaData);
sock := Winsock.socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
ZeroMemory(@SockAddr, sizeof(SockAddr));
sockaddr.sin_family := AF_INET;
sockaddr.sin_port := htons(StrToInt(Port));
sockaddr.sin_addr.S_addr := inet_addr(PChar(Listen));
if (Winsock.bind(sock, sockaddr, SizeOf(sockaddr)) = 0) and
(Winsock.listen(sock, SOMAXCONN) = 0) then
Result := True;
end;
function StartSocks5 : Boolean; stdcall;
var
wsaData : TWSAData;
sock
: TSOCKET;
sockaddr: SockAddr_in;
conn
: Integer;
client : TSockAddr;
tid : Cardinal;
size : Integer;
begin
result := False;
WSAStartup($0101, wsaData);
sock := socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
ZeroMemory(@SockAddr, sizeof(SockAddr));
sockaddr.sin_family := AF_INET;
sockaddr.sin_port := htons(config.Port);
sockaddr.sin_addr.S_addr := inet_addr(PChar(config.Listen));
if (bind (sock ,sockaddr,SizeOf(sockaddr)) = 0) AND
(listen(sock,SOMAXCONN)
= 0) then begin
while 1 = 1 Do begin
size := SizeOf(client);
conn := accept(sock,@client,@size);
if conn <> SOCKET_ERROR then begin
CreateThread(nil,0,@SocksProc,Pointer(conn),0,tid);
end;
Sleep(100);
end;
end;
end;
var
cmd : string;
i : Integer;
tid: Cardinal;
httpsock: TSocket;
begin
config.sockstype := 'socks5';
config.Port := 8877;

config.Listen := '0.0.0.0';
config.UserName := '';
config.Password := '';
config.ProxyHost:= ''; // http proxy address
config.ProxyPort:= 0; // http proxy port
for i := 0 to ParamCount do begin
if (i = 1) and (Pos('-', ParamStr(i)) = 0) then begin
if Pos('socks5', LowerCase(ParamStr(i))) <> 0 then
config.sockstype := 'socks5';
if Pos('http', LowerCase(ParamStr(i))) <> 0 then
config.sockstype := 'http';
//

Writeln(PChar(ParamStr(i)));
end;

if Pos('@', LowerCase(ParamStr(i))) <> 0 then begin


config.UserName := Copy(ParamStr(i), 0, Pos('@',ParamStr(i)) - 1);
config.Listen := Copy(ParamStr(i), Pos('@',ParamStr(i)) + 1, Length(ParamS
tr(i)));
end;
if Pos('-l', ParamStr(i)) <> 0 then
config.Password := ParamStr(i + 1);
if Pos('-p', ParamStr(i)) <> 0 then begin
config.Port := StrToInt(ParamStr(i + 1));
end;
if Pos('-Ph', ParamStr(i)) <> 0 then
config.ProxyHost := LowerCase(ParamStr(i + 1));
if Pos('-Pp', ParamStr(i)) <> 0 then
config.ProxyPort := StrToInt(ParamStr(i + 1));
if Pos('-Pt', ParamStr(i)) <> 0 then
config.proxytype := LowerCase(ParamStr(i + 1));
end;
Writeln('Listen '#9#9':' + PChar(config.Listen));
Writeln('Port '#9#9':' + PChar(IntToStr(config.Port)));
Writeln('Type '#9#9':' + PChar(config.sockstype));
Writeln('ProxyHost '#9':' + PChar(config.ProxyHost));
Writeln('ProxyPort '#9':' + PChar(IntToStr(config.ProxyPort)));
Writeln('ProxyType '#9':' + PChar(config.proxytype));
Writeln('==================================================');
StartSocks5;
{ TODO -oUser -cConsole Main : Insert code here }
end.

S-ar putea să vă placă și