我正在开发一个类似于浏览器pac文件的代理交换系统。我设法过滤并将大多数请求重定向到正确的IOhandler和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;
答案 0 :(得分:0)
如果连接到TIdHTTPProxyServer
的HTTP客户端请求.i2p
主机名(并且可能是SwitchProxy()
在返回3时查找的内容),则{{1}将要求OutboundClient.IOHandler
与运行在127.0.0.1:4444的HTTP代理建立套接字连接,并向其发送命令以从HTTP客户端的原始TIdConnectThroughHttpProxy
请求连接到主机名和端口。然后,HTTP代理必须先使用DNS将.i2p
主机名解析为IP,然后才能与该主机建立套接字连接并返回.i2p
的回复。 TIdConnectThroughHttpProxy
以相同的方式运作。
FireFox中的TIdSocksInfo
选项控制FireFox本身在连接到代理之前是否将主机名解析为IP,或者它是否要求代理执行解析:
如果Remote DNS
关闭,FireFox将在本地解析IP,然后要求代理连接到该IP(Indy在连接到主机名时不会执行此操作)。
如果启用Remote DNS
,FireFox会将主机名发送给代理并要求其解析IP(Indy在连接主机名时执行此操作)。
由于您的SOCKS / HTTP代理与Remote DNS
在同一台计算机上运行,如果计算机无法将TIdHTTPProxyServer
主机名解析为IP,则说明您的计算机存在DNS问题,或者代理的配置。这不是您的.i2p
代码的问题。
话虽这么说,你可以模仿FireFox在TIdHTTPProxyServer
关闭时所做的事情。将主机名本地解析为IP的最简单方法是在Remote DNS
单元中使用Indy的GIdStack.ResolveHost()
函数。这依赖于本地操作系统来执行实际的DNS查找。如果您想使用您选择的外部DNS服务器(例如公共互联网上的任意数量的免费开放DNS服务器,如8.8.8.8或8.8.4.4的Google的DNS服务器)执行DNS查找,您可以使用Indy的{ {1}}组件。
无论哪种方式,您都可以让IdStack
处理程序检索TIdDNSResolver
属性的值(从HTTP客户端的原始请求中的URL初始化),如果它不是IP然后手动将其解析为IP并在退出处理程序之前将其分配回OnBeforeCommand
属性。所有后续链式代理请求都将跳过服务器端DNS查找并按原样连接到IP。