当TIdHTTPProxyServer尝试将请求转发给大多数代理服务器时,为什么它返回403?

时间:2012-08-06 04:16:10

标签: delphi proxy c++builder indy

这个问题延伸到我之前提到的the question

目前,我可以让我的TIdHTTPProxyServer代理服务器将请求转发给另一个也使用TIdHTTPProxyServer的代理服务器。但当我试图让它从Web上的免费代理服务器列表转发请求到其他代理服务器时。可以通过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命令,对CONNECT请求使用HTTPS命令。并且大多数代理服务器在非HTTPS请求时阻止Connect命令(例如,CONNECT www.google.com.tw:80 HTTP / 1.0)。这就是为什么TIdConnectThroughHttpProxy总是不起作用的原因。

以下是我的解决方法,我在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,并希望有更好的解决方案。

1 个答案:

答案 0 :(得分:1)

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

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

不要使用“透明代理”类。 使用常规HTTP代理,例如How to download a file over HTTPS using Indy 10 and OpenSSL?

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