我正在开发一个有点像浏览器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请求,当然失败。我做错了什么?谢谢。
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; 发布于 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。
https://stackoverflow.com/questions/33824057
复制相似问题