【发布时间】:2016-02-22 18:51:39
【问题描述】:
我正在开发一个类似于浏览器 pac 文件的代理切换系统。我已经设法过滤并将大多数请求重定向到正确的 IOhandlers 和 Socks 代理。
我在 Firefox 中使用的连接设置是
“手动代理配置:”
“HTTP 代理 127.0.0.1 端口 8080”
勾选“将此代理服务器用于所有协议”。“远程 DNS”打勾。
我很确定远程 DNS 不是问题,因为如果我将 Firefox 的 HTTP 端口设置为 4444。I2P 工作正常。
问题似乎出在 ChainProxy 函数中。而不是将标头从 HTTPProxyServer: TIdHTTPProxyServer 代理主机 '127.0.0.1' 代理端口 '8080' 传递给 Chain: 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;
【问题讨论】:
-
在
OnBeforeCommand事件中,OutboundClient.IOHandler属性尚未分配。如果SwitchProxy()返回 2 或 3,则您的代码依赖编译器在访问OutboundClient.Socket属性之前调用SocksProxy()或ChainProxy()。这是一个危险的假设。更安全的设计是更改SocksProxy()和ChainProxy()以返回一个新的TIdIOHandler,其中附加了所需的TransparentProxy,然后将其分配给OutboundClient.IOHandler,就像案例0和1一样。
标签: delphi proxy indy freepascal indy10