首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Indy i2p故障连接到TIdHTTPProxyServer站点

使用Indy i2p故障连接到TIdHTTPProxyServer站点
EN

Stack Overflow用户
提问于 2015-11-20 10:12:48
回答 1查看 621关注 0票数 1

我正在开发一个有点像浏览器pac文件的代理切换系统。我已经成功地过滤和重定向了大多数请求到正确的IOhandlers和Socks代理。

我在Firefox中使用的连接设置是 手动代理配置: HTTP代理127.0.0.1端口8080 勾选“对所有协议使用此代理服务器”。 “远程DNS”被勾选。

我很确定远程DNS不是问题,因为如果我将Firefox的HTTP端口设置为4444。I2P工作得很好。

问题似乎是在ChainProxy函数中。而不是将头从HTTPProxyServer: TIdHTTPProxyServer代理主机'127.0.0.1‘代理端口'8080’传递到链: TIdConnectThroughHttpProxy;代理主机'127.0.0.1‘代理端口'4444’。它对i2p网站名称进行DNS请求,当然失败。我做错了什么?谢谢。

代码语言:javascript
复制
function Standard_IO(AContext: TIdHTTPProxyServerContext): TIdIOHandler;
var
  StackIO: TIdIOHandlerStack;
begin
  StackIO:=TIdIOHandlerStack.Create(AContext.OutboundClient);
  Result:=StackIO;
end;

function SSL_IO(AContext: TIdHTTPProxyServerContext): TIdIOHandler;
var
  SSLStackIO: TIdSSLIOHandlerSocketOpenSSL;
begin
  SSLStackIO:=TIdSSLIOHandlerSocketOpenSSL.Create(AContext.OutboundClient);
  SSLStackIO.SSLOptions.Mode:=sslmUnassigned;
  SSLStackIO.SSLOptions.Method:=sslvTLSv1_2;
  SSLStackIO.SSLOptions.SSLVersions:=[sslvSSLv2,sslvSSLv3,sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2];
  SSLStackIO.SSLOptions.VerifyMode:=[];
  SSLStackIO.PassThrough:=True;
  Result:=SSLStackIO;
end;

function SocksProxy(AContext: TIdHTTPProxyServerContext; Host: String; Port: TIdPort; Version: TSocksVersion):  TIdCustomTransparentProxy;
var
  Socks: TIdSocksInfo;
begin
  AContext.OutboundClient.IOHandler:=Standard_IO(AContext);
  Socks:=TIdSocksInfo.Create(AContext.OutboundClient);
  Socks.Host:=Host;
  Socks.Port:=Port;
  Socks.Authentication:=saNoAuthentication;
  Socks.Version:=Version;
  Result:=Socks;
end;

function ChainProxy(AContext: TIdHTTPProxyServerContext; Host: String; Port: TIdPort): TIdCustomTransparentProxy;
var
  Chain: TIdConnectThroughHttpProxy;
begin
   AContext.OutboundClient.IOHandler:=Standard_IO(AContext);
   Chain:=TIdConnectThroughHttpProxy.Create(AContext.OutboundClient);
   Chain.Host:=Host;
   Chain.Port:=Port;
   Chain.Enabled:=True;
   Result:=Chain;
end;  

procedure TForm1.HTTPProxyServerHTTPBeforeCommand(AContext: TIdHTTPProxyServerContext);
begin
  case SwitchProxy(AContext) of
    0: AContext.OutboundClient.IOHandler:=Standard_IO(AContext);  // http://*
    1: AContext.OutboundClient.IOHandler:=SSL_IO(AContext);       // https://*:443
    2: AContext.OutboundClient.Socket.TransparentProxy:=SocksProxy(AContext, '127.0.0.1', 9150, svSocks5);  // *.onion
    3: AContext.OutboundClient.Socket.TransparentProxy:=ChainProxy(AContext, '127.0.0.1', 4444);            // *.i2p
   end;
end;     
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-21 04:04:46

如果连接到您的TIdHTTPProxyServer的HTTP请求一个.i2p主机名(这大概是SwitchProxy()返回3时所查找的),那么OutboundClient.IOHandler将要求TIdConnectThroughHttpProxy与运行在127.0.0.1:4444的HTTP代理建立套接字连接,并向它发送一个命令,从HTTP的原始.i2p请求连接到主机名和端口。然后,HTTP代理必须使用DNS将.i2p主机名解析为IP,然后才能将套接字连接到该主机并向TIdConnectThroughHttpProxy返回答复。TIdSocksInfo以同样的方式运行。

Remote DNS选项在FireFox中控制FireFox本身是否在连接到代理之前将主机名解析为IP,还是要求代理执行解析:

  • 如果Remote DNS关闭,FireFox将在本地解析IP,然后要求代理连接到该IP (Indy在连接到主机名时不会这样做)。
  • 如果Remote DNS打开,FireFox将向代理发送主机名,并要求它解析IP (Indy在连接到主机名时会这样做)。

由于SOCKS/HTTP与TIdHTTPProxyServer运行在同一台机器上,如果机器无法将.i2p主机名解析为IP,则这是计算机的DNS问题,或代理的配置。这不是TIdHTTPProxyServer代码的问题。

也就是说,您可以模仿FireFox在关闭Remote DNS时所做的事情。在本地将主机名解析为IP的最简单方法是在GIdStack.ResolveHost()单元中使用Indy的IdStack函数。这依赖于本地操作系统来执行实际的DNS查找。如果您希望使用您选择的外部DNS服务器(例如公共Internet上任意数量的免费开放DNS服务器,比如Google的DNS服务器8.8.8.8或8.8.4.4)执行DNS查找,则可以为此使用Indy的TIdDNSResolver组件。

无论哪种方法,您都可以让OnBeforeCommand处理程序检索TIdTCPClient(OutboundClient).Host属性的值(该属性是从HTTP原始请求中的URL初始化的),如果它还不是IP地址,则在退出处理程序之前手动将其解析为IP并将其分配回TIdTCPClient(OutboundClient).Host属性。所有随后的链接代理请求都将跳过服务器端DNS查找,并按原样连接到IP。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33824057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档