Конференция "Сети" » Прокси в моей программе [D7, WinXP]
 
  • Сергей М. © (24.09.10 13:29) [20]

    > Sanprof   (24.09.10 13:16) [19]


    Ну зайди да посмотри, к примеру, в настройках своего браузера..
    HTTP(S)-прокси наверняка там фигурирует.
    А вот доступны ли SOCKS-прокси в вашей корп.сети - это уже вопрос к админу, если конечно же настройки сокс-прокси не фигурируют в кач-ве активных и используемых, к примеру, в разного рода мессенджерах типа аськи и т.п.
  • Sanprof (24.09.10 14:07) [21]
    короче на работе работает только HTTP(S).
    Значит Synapse мне в помощь?
  • Сергей М. © (24.09.10 14:26) [22]

    > Значит Synapse мне в помощь?


    Угу.
  • Slym © (27.09.10 15:03) [23]
    а при чем тут набор каких либо компонент?
    я спросил какой протокол! наиболее распространенный HTTP прокси заточен именно под HTTP протокол и ничего кроме не поддерживает (FTP не всчет)...
    Можно воспользоваться фичей HTTPS - Connect, но одмины не дураки и разрешено зачастую только на 443 и 8443 порты, т.к. в незакрытом состоянии это большая дыра...
    затачивать только SOCKS - глупо т.к. большинство HTTPProxy

    по сабжу: HTTPS Connect дописать на TClientSocket дело 5 мин...
  • Sanprof (28.09.10 11:32) [24]

    > Slym ©   (27.09.10 15:03) [23]
    >
    > по сабжу: HTTPS Connect дописать на TClientSocket дело 5
    > мин...

    Slym, не подскажите, где можно почитать, чтоб можно было за 5 мин...???
    Очень надо.
  • Сергей М. © (28.09.10 13:36) [25]
  • Sanprof (28.09.10 13:54) [26]
    Сергей М., спасибо за ссылку, только вот я так и не понял как мне реализовать тунелирование на делфи с помощью TClient~ServerSocket?
  • Сергей М. © (28.09.10 14:04) [27]
    Ну там же черным по белому написано - послать прокси-серверу то-то, принять от него ответ.. Если принято то-то, значит сё-то, иначе так-то ..

    Ну так вот твой TClientSocket как раз и нужен чтобы посылать прокси-серверу то-то и получать от него сё-то.

    А TServerSocket тут вообще не при делах.
  • Sanprof (28.09.10 14:45) [28]

    > Сергей М. ©   (28.09.10 14:04) [27]
    >
    > Ну там же черным по белому написано - послать прокси-серверу
    > то-то, принять от него ответ.. Если принято то-то, значит
    > сё-то, иначе так-то ..
    >
    > Ну так вот твой TClientSocket как раз и нужен чтобы посылать
    > прокси-серверу то-то и получать от него сё-то.
    >
    > А TServerSocket тут вообще не при делах.

    Ок, попробую может че и получится, если че сюда отпишусь.
  • Slym © (28.09.10 14:55) [29]
    надергал из разных месть так что выглядит довольно криво

    unit Unit1;

    interface

    uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
     Dialogs, ScktComp, StdCtrls;

    type
     TForm1 = class(TForm)
       Button1: TButton;
       ClientSocket1: TClientSocket;
       procedure Button1Click(Sender: TObject);
     private
       { Private declarations }
     public
       { Public declarations }
     end;

    var
     Form1: TForm1;

    implementation
    uses WinSock,RTLConsts;
    {$R *.dfm}

    const
     LF = #10; CR = #13;
     EOL = CR + LF;
    const
     DefTimeout:Longint=60000;
     DefMaxLineLength:integer=MaxWord;

    function SockWaitForData(ASocket:TSocket; ATimeout: Longint): Boolean;
    var
     FDSet: TFDSet;
     TimeVal: TTimeVal;
    begin
     if ATimeout=-1 then ATimeout:=DefTimeout;
     TimeVal.tv_sec := ATimeout div 1000;
     TimeVal.tv_usec := (ATimeout mod 1000) * 1000;
     FD_ZERO(FDSet);
     FD_SET(ASocket, FDSet);
     Result := select(0, @FDSet, nil, nil, @TimeVal) > 0;
    end;

    function LCharPos(Str:PChar;char:char;Size:integer): Integer;
    asm  {Str - EAX, char - DL (EDX), Size - ECX}
           PUSH    EDI
           MOV     EDI, EAX { Point EDI to str}

           MOV     AL,DL        { AL = Search char}
           MOV     EDX,ECX   {remember Length}

           REPNE   SCASB
           JNE     @@fail
           MOV     EAX,EDX { Calc offset }
           SUB     EAX,ECX
           JMP     @@fin
    @@fail:
           XOR     EAX,EAX
    @@fin:
           POP     EDI
    end;

    function CharPos(const str:string;char:char): Integer;
    asm
           TEST    EAX, EAX
           JE     @@exit
           MOV     ECX, [EAX-4]
           call    LCharPos
    @@exit:
    end;

    function Fetch(var AInput:string;const ADelim:char):string;
    var LPos: Integer;
    begin
     LPos:=CharPos(AInput,ADelim);
     if LPos=0 then
     begin
       Result:=AInput;
       AInput:='';
     end else
     begin
       Result:=Copy(AInput,1,LPos-1);
       AInput:=Copy(AInput,LPos+1,MaxInt);
     end;
    end;

    function SockReadLn(ASocket:TSocket;ATerminator:char=LF;AMaxLineLength:integer=MaxWord;AT imeOut:Longint=0):string;
    var
     Buf:array[byte] of char;
     SizeBuf:integer;
     r,i:integer;
     s:string;
    begin
     if ATimeout=0 then ATimeout:=DefTimeout;
     SizeBuf:=SizeOf(Buf);
     result:='';
     while SockWaitForData(ASocket,ATimeOut) do
     begin
       r:=recv(ASocket, Buf, SizeBuf, MSG_PEEK);
       if r=0 then Break;
       if r=SOCKET_ERROR then Raise Exception.Create('recv');

       i:=LCharPos(@Buf,ATerminator,r);
       if i<>0 then r:=i;

       r:=recv(ASocket, Buf, r, 0);
       if r=0 then Break;
       if r=SOCKET_ERROR then Raise Exception.Create( 'recv');

       SetString(s,Buf,r);
       result:=result+s;
       if i<>0 then Break;
     end;
     if length(result)=0 then exit;
     i:=length(result)-1;
     if (ATerminator=LF) and (result[i]=CR) then Dec(i);
     SetLength(result,i);
    end;

    procedure WriteBuffer(ASocket:TSocket; const Buffer; Count: Longint;ATimeout:Longint=0);
    var
     Overlapped: TOverlapped;
     ErrorCode,Result: Integer;
    begin
     if ATimeout=0 then ATimeout:=DefTimeout;
     FillChar(OVerlapped,SizeOf(Overlapped),0);
     Overlapped.hEvent:=CreateEvent(nil,True,False,'');
     try
       if not WriteFile(ASocket, Buffer, Count, DWORD(Result),
         @Overlapped) and (GetLastError <> ERROR_IO_PENDING) then
       begin
         ErrorCode := GetLastError;
         raise ESocketError.CreateResFmt(@sSocketIOError, [sSocketWrite, ErrorCode,
           SysErrorMessage(ErrorCode)]);
       end;
       if WaitForSingleObject(Overlapped.hEvent, ATimeout)<>WAIT_OBJECT_0 then
         Result := 0
       else GetOverlappedResult(ASocket, Overlapped, DWORD(Result), False);
     finally
       CloseHandle(Overlapped.hEvent);
     end;
    end;

    procedure SockWriteLn(ASocket:TSocket;const AOut:string='');
    begin
     if Length(AOut)>0 then
       WriteBuffer(ASocket,Pointer(AOut)^, Length(AOut));
     WriteBuffer(ASocket,EOL,Length(EOL));
    end;

    const
     ProxyHost='192.168.14.2';
     ProxyPort=3128;

     RemoteHost='www.ya.ru';
     RemotePort=80;
     proxy=true;

    procedure TForm1.Button1Click(Sender: TObject);
    var
     s:string;
     Code,i:integer;
    begin
     ClientSocket1.ClientType:=ctBlocking;
     if proxy then
     begin
       ClientSocket1.Host:=ProxyHost;
       ClientSocket1.Port:=ProxyPort;
     end else
     begin
       ClientSocket1.Host:=RemoteHost;
       ClientSocket1.Port:=RemotePort;
     end;
     ClientSocket1.Open;
     if proxy then
     begin
       SockWriteLn(ClientSocket1.Socket.SocketHandle,format('CONNECT %s:%d HTTP/1.1'#13#10,[RemoteHost,RemotePort]));
       s:=SockReadLn(ClientSocket1.Socket.SocketHandle);
       if Length(s)=0 then raise Exception.Create('Bad HTTP respond');
       Fetch(s,' ');// to remove the http/1.0 or http/1.1
       Code:=StrToIntDef(Fetch(s,' '),200); // if invalid response then we assume it succeeded
       if Code<>200 then raise Exception.CreateFmt('Bad HTTP status code: %d %s',[Code,s]);
       i:=128;
       repeat dec(i) until
         (SockReadLn(ClientSocket1.Socket.SocketHandle) = '') or (i<=0);
       if i<=0 then
         raise Exception.Create('Too many headers or wrong protocol');
     end;

     DOWORK;

    end;

    end.


  • Sanprof (30.09.10 13:56) [30]
    1. вот руки у меня добрались до этого кода, Slym, хотелось бы знать, что каждая функция и процедура выполняет, если вас не затруднит хоть какое нибудь описание, я думаю будет полезным и для других, читающих эту тему (это ж как база знаний).
    2. Код отрабатывает все ок, получаю ответ от прокси (код 200). Если мне надо приконектиться к своей машине (как я уже и говорил статический ИП), на которой программа с настроенным TServerSocket (допустим Host - 109.87.123.1, Port - 7777), как мне это сделать, допустим отослать серверу текст "Hello", и получить ответ "Hello"??? Зарание спасибо.
  • Сергей М. © (30.09.10 14:14) [31]

    > Sanprof   (30.09.10 13:56) [30]


    > как мне это сделать, допустим отослать серверу текст "Hello",
    >  и получить ответ "Hello"?


    Точно так же как ты это делал до тех пор пока не озадачился работой через прокси.
    Только в случае с примером от Slym © место, где следует это делать, помечено как "DOWORK"
  • Sanprof (30.09.10 14:46) [32]

    > Сергей М. ©   (30.09.10 14:14) [31]
    >
    > Точно так же как ты это делал до тех пор пока не озадачился
    > работой через прокси.
    > Только в случае с примером от Slym © место, где следует
    > это делать, помечено как "DOWORK"

    Э-э-э-м немного не пойму, ведь я до этого в настройках TClientSocket вводил Address - 109.87.123.1, Host - 109.87.123.1, Port - 7777, а теперь как я понял в коде получается
    ClientSocket1.Host:=ProxyHost;
    ClientSocket1.Port:=ProxyPort;


    тоесть Host - 192.168.14.2, Port - 3128, как же мне тогда указать куда коннектиться???
  • Сергей М. © (30.09.10 15:47) [33]

    > как же мне тогда указать куда коннектиться???


    Вот строка, которую получает прокси:

    format('CONNECT %s:%d HTTP/1.1'#13#10,[RemoteHost,RemotePort]));

    в ней ты и указываешь прокси-серверу куда ему нужно коннектиться от твоего имени.
  • Sanprof (30.09.10 15:55) [34]
    только хотел отписаться по этому поводу, что мол вот же [RemoteHost,RemotePort], и как я мог это пропустить, просто банальность - этот кусок кода вылез за пределы редактора кода в делфи, вот я его и не заметил.
    :)Большое спасибо Slym © за код, и Сергей М. © за отзывчивость и помощь.:)
    Сегодня протестировать не получится, но завтра обязательно, о результате сюда отпишусь.
  • Slym © (01.10.10 06:19) [35]
    Sanprof   (30.09.10 13:56) [30]
    наиболее важная часть в [29] помечена жирным
    из неродного: SockWriteLn, SockReadLn и Fetch
    SockWriteLn, SockReadLn - понятно из названий
    Fetch - взят из Indy работа со строками, но заточен под поиск одного символа. Это связка pos и copy
    найти символ и вернуть часть строки до него, исходную строку урезать...

    остальной asm бред для работоспособности этих функций
  • Sanprof (01.10.10 10:05) [36]
    такой еще вопрос, у нас на работе доступ в интернет при помощи авторизации, код выше будет работать в такой ситуации, а то я получаю (Code = 200), дальше делаю как делал раньше ClientSocket1.Socket.SendText('служебный текст на подключение'), сервер в ответ должен выслать тоже определенный текст, но событие OnRead клиента даже не возникает, хотя сегодня утром проверял на одной машине работоспособность клиента и сервера. С работы мой комп пингуется, и в интернете проверил открыт ли порт, на котором сидит сервер - Открыт. Что не так не пойму.
  • Slym © (01.10.10 11:42) [37]
    читай Proxy-Authorization
    function BasicAuthentication(const Username,Password:string): String;
    begin
     with TIdEncoderMIME.Create do try
       Result := 'Basic ' + Encode(Username + ':' + Password); {do not localize}
     finally Free; end;
    end;

    SockWriteLn(ClientSocket1.Socket.SocketHandle,format('CONNECT %s:%d HTTP/1.1',[RemoteHost,RemotePort]));
    SockWriteLn(ClientSocket1.Socket.SocketHandle,format('Proxy-Authorization: %s'#13#10,[BasicAuthentication(Username,Password)]));

  • Sanprof (05.10.10 12:54) [38]
    Вобщем получилось следующее, достал на время ноутбук приконктил к пркси на моей машине(интернет и т.п. работает), и стал тестить, прописал ИП, порт прокси и ИП, порт удаленной машины, тоесть моей, прокси стоит 3proxy (там можно посмотреть лог отправки запросов с клиентов к прокси), так вот клиент открыл порт 11622 в логах посмотрел, и коннект к серверу на порт 5364 не происходил, потом я поменял порт на сервере с 5364 на 11622, при этом клиент законнектился к серверу, но я же не должен менять порт на сервере. Как обойти ситуацию не знаю???
  • Сергей М. © (05.10.10 13:28) [39]
    У тебя ошибка в программе.
 
Конференция "Сети" » Прокси в моей программе [D7, WinXP]
Есть новые Нет новых   [119355   +74][b:0][p:0.003]