3

这个问题是从我之前提出的问题延伸而来的。

目前我可以让我的代理服务器使用 TIdHTTPProxyServer 将请求转发到另一个也使用 TIdHTTPProxyServer 的代理服务器。但是当我试图让它从网络上的免费代理服务器列表中将请求转发到其他代理服务器时。大多数可以通过 IE 代理设置使用的服务器都会向我的代理服务器返回 403 错误消息。事实上,我已经尝试了大约 20 个有效的代理服务器,但只有两个可以接受来自我的代理服务器的请求。我不知道为什么会这样。

下面是我在 TIdHTTPProxyServer 的 HTTPBeforeCommand 中使用的代码。

    TIdIOHandlerStack* tempIO = new TIdIOHandlerStack(AContext->OutboundClient);

    TIdConnectThroughHttpProxy* tempProxy = new TIdConnectThroughHttpProxy(AContext->OutboundClient);
    tempProxy->Enabled = true;
    tempProxy->Host = ProxyServerAddress;
    tempProxy->Port = ProxyServerPort ;
    tempIO->TransparentProxy  =  tempProxy;
    AContext->OutboundClient->IOHandler =  tempIO;

在使用wireshark监控TIdHTTPProxyServer的行为后,我发现TIdHTTPProxyServer总是先向其他代理服务器发送CONNECT请求,然后才是真正的请求(浏览器不这样做)。然后收到大多数代理服务器的 403 响应。但仍然不知道如何使它工作。


更新于 2012/08/07

你好,我对那些HTTP的东西不是很熟悉,所以我只是把我在wireshark中看到的记录在这里。似乎 IE 对请求使用GET/POST命令,对请求HTTP使用命令。并且大多数代理服务器在它们不是 HTTPS 请求时会阻止连接命令(例如,CONNECT www.google.com.tw:80 HTTP/1.0)。这就是为什么总是不起作用。 CONNECTHTTPSTIdConnectThroughHttpProxy

下面是我的解决方法,我在 IdHTTPProxyServer.pas 中做了一些更改。希望它对遇到相同问题的其他人有用。

对于 CONNECT 命令,仍然使用TIdConnectThroughHttpProxy

之内TIdHTTPProxyServer.CommandCONNECT

if UseProxy = True then
begin
     tempIO := TIdIOHandlerStack.Create(LContext.FOutboundClient);
     tempProxy := TIdConnectThroughHttpProxy.Create(LContext.FOutboundClient);
     tempProxy.Enabled := True;
       tempProxy.Host := UseProxyAddr;
       tempProxy.Port := UseProxyPort ;
       tempIO.TransparentProxy  :=  tempProxy;
       LContext.FOutboundClient.IOHandler :=  tempIO;
end;

对于GET/POST命令,我应该直接将 GET www.google.com.tw:80 HTTP/1.0 发送到其他代理服务器,而不是首先发送 CONNECT www.google.com.tw:80 HTTP/1.0。

之内TIdHTTPProxyServer.CommandPassThrough

  if UseProxy = True then
  begin
     TIdTCPClient(LContext.FOutboundClient).Host := UseProxyAddr;
     TIdTCPClient(LContext.FOutboundClient).Port := UseProxyPort;
  end else
  begin
     TIdTCPClient(LContext.FOutboundClient).Host := LURI.Host;
     TIdTCPClient(LContext.FOutboundClient).Port := IndyStrToInt(LURI.Port, 80);
  end;

同样在里面TIdHTTPProxyServer.CommandPassThrough,我应该让标题Proxy-Connection = close

LContext.Connection.IOHandler.Capture(LContext.Headers, '', False);      
LContext.Headers.Values['Proxy-Connection'] := 'close';

终于在TIdHTTPProxyServer.TransferData

if AContext.TransferSource = tsClient then 
begin

  if UseProxy = True then
  begin
     ADest.IOHandler.WriteLn(AContext.Command + ' ' + AContext.Target + ' HTTP/1.0'); 
  end else
  begin
      ADest.IOHandler.WriteLn(AContext.Command + ' ' + AContext.Document + ' HTTP/1.0'); 
  end;
end;

这是我第一次实现delphi,希望有更好的解决方案。

4

1 回答 1

1

我相信你不应该使用针孔 - http://www.indyproject.org/docsite/html/TIdConnectThroughHttpProxy.html

CONNECT 命令不是 WWW 的工作方式。没有浏览器使用它。这就是非 WWW 程序试图突破防火墙并打开对 WWW 以外的所有 Internet 区域的直接访问的方式。

不要使用“透明代理”类。使用常规 HTTP 代理,例如如何使用 Indy 10 和 OpenSSL 通过 HTTPS 下载文件?

顺便说一句,没有像你这样的事件处理程序名称“HTTPBeforeCommand” http://www.indyproject.org/docsite/html/!!MEMBEROVERVIEW_TIdHTTPProxyServer.html

于 2012-08-06T09:07:21.723 回答