Тунель через Socks5

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by slesh, 6 Jun 2007.

  1. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Народ. Уже в который раз я выкладываю исходники некоторых своих разработак. Мож комунить понадобится в дальнейшем :)
    Короче это простенькая программа которая создает цепочку socks5 прокси. Работает кое как. Но всеже работает. Сильно не обращайте на его кривизну и недоделки, т.к. писался он мною давно. Хотя отсутсвует поддержка работы с DNS именами и только частичная реализация RFC. Но этого уже достаточно для того чтобы понять как самому работать серез SOCKS5.
    Пока что там реализовано тока:
    1) многопоточность
    2) SOCKS5 connect
    3) обычная аутентификация.

    Вот исходник дельфяный. Сори что почти нет коментов, просто и так понятно будет если взять RFC
    Code:
    program Tunnel;
    
    {$APPTYPE CONSOLE}
    
    uses
      Windows,winsock2;
    
    type
    proxy=record
     ip:string;
     port:word;
     login:string;
     password:string;
    end;
    tsocks_query_method=record
     VER,LEN,MTD:byte;
    end;
    tsocks_reply_method=record
     VER,MTD:byte;
    end;
    tsocks_query=record
     VER,CMD,RSV,ATYP:byte;
     ip:array[0..3] of byte;
     port:array[0..1] of byte;
     reserv:array[0..65536] of byte;
    end;
    tsocks_reply=record
     VER,REP,RSV,ATYP:byte;
     ip:array[0..3] of byte;
     port:array[0..1] of byte;
    end;
    tsocks_pass=record
    VER,ULEN:byte;
    UNAME:array of char;
    PLEN:byte;
    PASSWD:array of char;
    end;
    
    var
     ts1,ts2:tsocket;
     WSData:TWSAData;
     f:textfile;
     s:string;
     proxy_mas:array of proxy;
     proxy_count:integer=0;
     csocket,lsocket:tsocket;
     laddr,caddr:sockaddr_in;
     thid:dword;
     size_caddr:integer;
     ID:integer;
    
    function StrToInt(const s:string):integer;
    var
    i:integer;
    begin
    Val(s,result,i);
    end;
    
    function IntTostr(i:integer):string;
    begin
    str(i,result);
    end;
    
    function fileexists(s:string):boolean;
    var
    FindData:TWin32FindData;
    Handle:integer;
    begin
    Handle:=FindFirstFile(PChar(s),FindData);
    if Handle<0 then result:=false else result:=true;
    end;
    
    
    function GetErrorText(err:integer):string;
    begin
    case err of
    $1:result:='SOCKS-server error';
    $2:result:='Connect forbidden';
    $3:result:='Network is not accessible';
    $4:result:='Host is not accessible';
    $5:result:='Refusal in connection';
    $6:result:='TTL timeout';
    $7:result:='Command not support';
    $8:result:='Address type not support';
    -1,$9..$FF:result:='Unknown error';
    -2:result:='Socks-server RFC error';
    -3:result:='Socks-server requires authorized';
    -4:result:='Login or Password incorrect';
    end;
    
    end;
    
    function GetProxy(s:string):proxy;
    begin
    while pos(' ',s)<>0 do delete(s,pos(' ',s),1);
    result.ip:=copy(s,1,pos(':',s)-1);
    delete(s,1,pos(':',s));
    result.port:=strtoint(copy(s,1,pos(':',s)-1));
    delete(s,1,pos(':',s));
    result.login:=copy(s,1,pos(':',s)-1);
    delete(s,1,pos(':',s));
    result.password:=s;
    end;
    
    function ConnectToProxy(ip:string;port:word;login,password:string;sock:tsocket):integer;
    var
    sqm:tsocks_query_method;
    srm:tsocks_reply_method;
    sq:tsocks_query;
    sr:tsocks_reply;
    sp:array[0..512] of char;
    s:string;
    auth:boolean;
    x:integer;
    begin
    if (login<>'') and (password<>'') then auth:=true else auth:=false;
    result:=-1;
    sqm.VER:=$05;
    sqm.LEN:=$01;
    if auth=true then sqm.MTD:=$2 else sqm.MTD:=$00;
    send(sock,sqm,3,0);
    recv(sock,srm,2,0);
    
    if srm.VER<>$05 then
     begin
     result:=-2;
     exit;
     end;
    if auth=true then
     begin
      if srm.MTD<>$2 then
       begin
        result:=-3;
        exit;
       end;
      end else
      begin
       if srm.MTD<>$0 then
        begin
         result:=-3;
         exit;
        end;
      end;
    
    if auth=true then
     begin
      s:=#01+chr(length(login))+login+chr(length(password))+password;
      for x:=0 to length(s)-1 do sp[x]:=s[x+1];
      send(sock,sp,length(s),0);
      recv(sock,srm,sizeof(srm),0);
      if srm.VER<>$01 then
       begin
        result:=-2;
        exit;
       end;
      if srm.MTD<>00 then
       begin
        result:=-4;
        exit;
       end;
     end;
    sq.VER:=$05;
    sq.CMD:=$01;
    sq.RSV:=$00;
    sq.ATYP:=$01;
    s:=ip;
    sq.ip[0]:=strtoint(copy(s,1,pos('.',s)-1));
    delete(s,1,pos('.',s));
    sq.ip[1]:=strtoint(copy(s,1,pos('.',s)-1));
    delete(s,1,pos('.',s));
    sq.ip[2]:=strtoint(copy(s,1,pos('.',s)-1));
    delete(s,1,pos('.',s));
    sq.ip[3]:=strtoint(s);
    sq.port[0]:=port div 256;
    sq.port[1]:=port-sq.port[0]*256;
    send(sock,sq,10,0);
    recv(sock,sr,sizeof(sr),0);
    if sr.VER<>$05 then
     begin
      result:=-2;
      exit;
     end;
    result:=sr.REP;
    end;
    
    
    procedure client(sock:tsocket);stdcall;
    var
    mysock,proxy_sock:tsocket;
    caddr:sockaddr_in;
    sqm:tsocks_query_method;
    srm:tsocks_reply_method;
    sq:tsocks_query;
    sr:tsocks_reply;
    ip:string;
    buf:array[0..65535] of char;
    buf_len:integer;
    thid:dword;
    Myid:integer;
    x:integer;
    r:integer;
    
    procedure reads;
    var
    read_sock,write_sock:tsocket;
    buf:array[0..65535] of char;
    buf_len:integer;
    begin
    read_sock:=ts1;
    write_sock:=ts2;
    repeat
    buf_len:=recv(read_sock,buf,sizeof(buf),0);
    send(write_sock,buf,buf_len,0);
    until buf_len<=0;
    closesocket(read_sock);
    closesocket(write_sock);
    end;
    
    
    begin
    inc(id);
    MyID:=id;
    writeln('[+] Client ID #',myid);
    mysock:=sock;
    recv(mysock,sqm,3,0);
    if sqm.VER<>$5 then
     begin
      writeln('[-] ID #',myid,' Client RFC error');
      closesocket(mysock);
      exit;
     end;
    if sqm.LEN<>$1 then // если длинна !=1
     begin
      writeln('[-] ID #',myid,' Client RFC error');
      closesocket(mysock);
      exit;
     end;
    if sqm.MTD<>$0 then // если просит аутентификацию
     begin
      srm.VER:=$5;
      srm.MTD:=$FF;
      writeln('[-] ID #',myid,' Client requires authorized');
      send(mysock,srm,2,0); // послать данные
      closesocket(mysock); // закрыть соединение
      exit;
     end;
    
    srm.VER:=$5;
    srm.MTD:=$0;
    send(mysock,srm,2,0); // послать данные
    
    recv(mysock,sq,sizeof(sq),0);
    if sq.VER<>$5 then
     begin
      writeln('[-] ID #',myid,' Client RFC error');
      closesocket(mysock); // закрыть соединение
      exit;
     end;
    
    if sq.CMD<>$1 then
     begin
       sr.VER:=$5;
       sr.REP:=$2;
       sr.RSV:=$0;
       sr.ATYP:=sq.ATYP;
       writeln('[-] ID #',myid,' Client command not support');
       send(mysock,sr,sizeof(sr),0); // послать данные
       closesocket(mysock); // закрыть соединение
       exit;
     end;
    if sq.ATYP<>$1 then
     begin
       sr.VER:=$5;
       sr.REP:=$8;
       sr.RSV:=$0;
       sr.ATYP:=sq.ATYP;
       writeln('[-] ID #',myid,' Client address type not support');
       send(mysock,sr,sizeof(sr),0); // послать данные
       closesocket(mysock); // закрыть соединение
       exit;
     end;
    
    proxy_sock:=socket(AF_INET, SOCK_STREAM, 0);
    caddr.sin_family:=AF_INET;
    caddr.sin_port:=htons(proxy_mas[0].port);
    caddr.sin_addr.s_addr:=inet_addr(Pansichar(proxy_mas[0].ip));
    if connect(proxy_sock,@caddr,sizeof(caddr))=-1 then
     begin
      sr.VER:=$5;
      sr.REP:=$4;
      sr.RSV:=$0;
      sr.ATYP:=sq.ATYP;
      writeln('[-] ID #',myid,' Not Connect to first proxy');
      send(mysock,sr,sizeof(sr),0); // послать данные
      closesocket(mysock); // закрыть соединение
      exit;
    end;
    
    for x:=1 to proxy_count-1 do begin
    r:=ConnectToProxy(proxy_mas[x].ip,proxy_mas[x].port,proxy_mas[x-1].Login,proxy_mas[x-1].password,proxy_sock);
    if r<>0 then
     begin
      sr.VER:=$5;
      sr.REP:=$4;
      sr.RSV:=$0;
      sr.ATYP:=sq.ATYP;
      writeln('[-] ID #',myid,' Proxy ',x,':',GetErrorText(r));
      send(mysock,sr,sizeof(sr),0); // послать данные
      closesocket(proxy_sock); // закрыть соединение
      closesocket(mysock); // закрыть соединение
      exit;
     end;
    end;
    ip:=inttostr(sq.ip[0])+'.'+inttostr(sq.ip[1])+'.'+inttostr(sq.ip[2])+'.'+inttostr(sq.ip[3]);
    r:=ConnectToProxy(ip,sq.port[0]*256+sq.port[1],proxy_mas[proxy_count-1].Login,proxy_mas[proxy_count-1].password,proxy_sock);
    if r<>0 then
     begin
      sr.VER:=$5;
      sr.REP:=$4;
      sr.RSV:=$0;
      sr.ATYP:=sq.ATYP;
      writeln('[-] ID #',myid,' Proxy ',proxy_count,':',GetErrorText(r));
      send(mysock,sr,sizeof(sr),0); // послать данные
      closesocket(proxy_sock); // закрыть соединение
      closesocket(mysock); // закрыть соединение
      exit;
     end;
    
    writeln('[+] ID #',myid,' Tunnel is constructed');
    sr.VER:=$5;
    sr.REP:=$0;
    sr.RSV:=$0;
    sr.ATYP:=sq.ATYP;
    ts1:=proxy_sock;
    ts2:=mysock;
    ThID:=CreateThread(nil, 0, @reads,nil, 0, ThID); // установка потока
    send(mysock,sr,sizeof(sr),0); // послать данные
    repeat
    buf_len:=recv(mysock,buf,sizeof(buf),0);
    send(proxy_sock,buf,buf_len,0);
    until buf_len<=0;
    windows.TerminateThread(ThID,0);
    writeln('[+] ID #',myid,' Client disconnect');
    closesocket(proxy_sock);
    closesocket(mysock);
    end;
    
    begin
    if paramstr(1)='' then
     begin
      writeln('SocksTunnel (C) SLESH 2006 ([email protected])');
      writeln('USAGE: Tunnel.exe [proxy_list_file]');
      exit;
    end;
    if not fileexists(paramstr(1)) then
     begin
      writeln('[-] FILE: ',paramstr(1),' not found');
      exit;
     end;
    assignfile(f,paramstr(1));
    
    reset(f);
    while not eof(f) do
     begin
     readln(f,s);
     if length(s)>8 then
      begin
       inc(proxy_count);
       setlength(proxy_mas,proxy_count);
       proxy_mas[proxy_count-1]:=GetProxy(s);
      end;
     end;
    closefile(f);
    if proxy_count=0 then
     begin
      writeln('[-] PROXY LIST EMPTY');
      exit;
     end;
    writeln('[+] LOAD ',proxy_count,' PROXY');
    size_caddr:=sizeof(caddr);
    if WSAStartup($202, WSData)=-1 then
     begin
      writeln('[-] WSAStartup');
      exit;
     end;
    lsocket:=socket(AF_INET, SOCK_STREAM, 0);
    laddr.sin_family:=AF_INET;
    laddr.sin_port:=htons(1080);
    laddr.sin_addr.s_addr:=INADDR_ANY;
    if bind(lsocket,@laddr, sizeof(laddr))<>0 then
     begin
      writeln('[-] Bind');
      exit;
     end;
    if listen(lsocket, $100)<>0 then
     begin
      writeln('[-] Listen');
      exit;
     end;
    writeln('[+] Waiting connection');
    while 1=1 do begin
    csocket:=accept(lsocket,caddr,size_caddr);
    writeln('[+] Client connected. IP=',inet_ntoa(caddr.sin_addr));
    CreateThread(nil, 0, @Client, pointer(csocket), 0, ThID); // установка потока
    end;
    
    end.
    
    
     
    #1 slesh, 6 Jun 2007
    Last edited: 6 Jun 2007
    2 people like this.
  2. Alexsize

    Alexsize Fail

    Joined:
    17 Sep 2005
    Messages:
    1,771
    Likes Received:
    1,221
    Reputations:
    704
    Мне, как новичку в кодинге, очень интересна данная тема. Усовершенствуй код и все будет просто отлично.
     
    #2 Alexsize, 7 Jun 2007
    Last edited: 7 Jun 2007