在Safari,IE和iOS设备上使用Fiddler信任证书并捕获流量

Cos*_*min 7 c# ssl fiddler ios fiddlercore

我已经在这里设置了我的Fiddler代理.

码:

public class ProxyConfig
    {
        private readonly string _secureEndpointHostname = IPAddress.Any.ToString();
        private readonly int _secureEndpointPort = 4555;
        private readonly int _port = 18882;

        private static readonly ICollection<Session> AllSessions = new List<Session>();

        private static Fiddler.Proxy _secureEndpoint;

        private static readonly LoggerCnx Logger = new LoggerCnx();
        private Action<string> onRequest;

        public ProxyConfig()
        {
        }

        public ProxyConfig(Action<string> onRequest)
        {
            this.onRequest = onRequest;
        }

        public void SetupProxyListener()
        {
            FiddlerApplication.SetAppDisplayName("FiddlerCoreProxyApp");

            // This is a workaround for known issue in .NET Core - https://github.com/dotnet/coreclr/issues/12668
            CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US");

            // Simply echo notifications to the console.  Because Fiddler.CONFIG.QuietMode=true 
            // by default, we must handle notifying the user ourselves.
            //Fiddler.FiddlerApplication.OnNotification += delegate (object sender, NotificationEventArgs oNEA) { System.Diagnostics.Debug.WriteLine("** NotifyUser: " + oNEA.NotifyString); };
            FiddlerApplication.Log.OnLogString += delegate (object sender, LogEventArgs oLEA) { Logger.Info("** LogString: " + oLEA.LogString); };

            FiddlerApplication.BeforeRequest += delegate (Session session)
            {

                if (!CertMaker.rootCertIsTrusted())
                {
                    CertMaker.trustRootCert();
                }

                if (onRequest != null)
                {
                    onRequest(session.fullUrl);
                }

                // In order to enable response tampering, buffering mode MUST
                // be enabled; this allows FiddlerCore to permit modification of
                // the response in the BeforeResponse handler rather than streaming
                // the response to the client as the response comes in.
                session.bBufferResponse = false;
                lock (AllSessions)
                {
                    AllSessions.Add(session);
                    Logger.Info("Session: " + session.fullUrl);
                }
                session["X-AutoAuth"] = "(default)";

                if ((session.oRequest.pipeClient.LocalPort == _secureEndpointPort) && (session.hostname == _secureEndpointHostname))
                {
                    session.utilCreateResponseAndBypassServer();
                    session.oResponse.headers.SetStatus(200, "OK");
                    session.oResponse["Content-Type"] = "text/html; charset=UTF-8";
                    session.oResponse["Cache-Control"] = "private, max-age=0";
                    session.utilSetResponseBody("<html><body>Request for httpS://" + _secureEndpointHostname + ":" + _secureEndpointPort.ToString() + " received. Your request was:<br /><plaintext>" + session.oRequest.headers.ToString());
                }
            };

            Logger.Info($"Starting {FiddlerApplication.GetVersionString()}...");
            CONFIG.IgnoreServerCertErrors = true;
            CONFIG.bCaptureCONNECT = true;

            FiddlerApplication.Prefs.SetBoolPref("fiddler.network.streaming.abortifclientaborts", true);

            FiddlerCoreStartupFlags startupFlags = FiddlerCoreStartupFlags.Default;

            startupFlags = (startupFlags | FiddlerCoreStartupFlags.DecryptSSL);
            startupFlags = (startupFlags | FiddlerCoreStartupFlags.AllowRemoteClients);
            startupFlags = (startupFlags & ~FiddlerCoreStartupFlags.MonitorAllConnections);
            startupFlags = (startupFlags & ~FiddlerCoreStartupFlags.CaptureLocalhostTraffic);

            FiddlerApplication.Startup(_port, startupFlags);

            Logger.Info("Created endpoint listening on port {0}", _port);

            Logger.Info("Starting with settings: [{0}]", startupFlags);
            Logger.Info("Gateway: {0}", CONFIG.UpstreamGateway.ToString());

            // Create a HTTPS listener, useful for when FiddlerCore is masquerading as a HTTPS server
            // instead of acting as a normal CERN-style proxy server.
            _secureEndpoint = FiddlerApplication.CreateProxyEndpoint(_secureEndpointPort, true, _secureEndpointHostname);
            if (null != _secureEndpoint)
            {
                Logger.Info("Created secure endpoint listening on port {0}, using a HTTPS certificate for '{1}'", _secureEndpointPort, _secureEndpointHostname);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

其目的是捕获和分析来自Windows,Mac OS X,Android和iOS浏览器(主要是桌面和移动设备上的Chrome,Firefox和Safari)的流量.

到目前为止,似乎正在努力:

  • Windows浏览器:Chrome,Firefox.不适用于IE和Edge
  • Android:Chrome
  • Mac OS:Chrome,Firefox.Safari无法正常工作
  • iOS:没有

在我的日志文件中,我看到Fiddler在浏览器无法正常工作时记录以下错误(适用于所有设备).HTTPS请求的示例:

2018-02-14 17:25:50.3860 | 信息|**LogString:!SecureClientPipeDirect失败:System.IO.IOException身份验证失败,因为远程方已关闭传输流.for pipe(CN =*.optimizely.com,O = DO_NOT_TRUST_BC,OU =由http://www.fiddler2.com创建 )

从我在过去几天读到的试图为此找到解决方案的内容来看,原因是设备上不信任的证书.

这些测试使用他们提供的名为BrowserStack Local的功能在BrowserStack上运行.有关它的详细信息在这里这里.

现在我的问题可以分为桌面和移动:

  • 为什么Chrome和Firefox能够在IE,Edge和Safari无法做到的情况下发出HTTPS请求?
  • 对于iOS,特别是这里有一个Fiddler for iOS文档,指定了配置设备所需的步骤.但是,正如我已经提到的,我不使用内部iOS设备,而是使用BrowserStack提供的物理设备.有没有办法以编程方式信任iOS设备(iOS 9.x,iOS 10.x,iOS 11.x)上的证书?

我可以使用任何变通方法吗?

编辑: FiddlerCore和BrowserStack本地日志在这里.

Bar*_*r J 4

从你的第二个问题开始, Telerik官方论坛上有一个关于 IOS 设备的讨论,指出:

SSL2 永远不应该启用,并且在 Fiddler 中也不会启用它,除非您特意搬起石头砸自己的脚。

如果您已正确配置 iOS 设备以信任 Fiddler 的根证书,则 HTTPS 拦截将在客户端中正常工作,除非使用证书固定。虽然 Chrome 中的证书固定在桌面上无关紧要,但在 iOS 上,它们会忽略受信任的证书存储,因此 Fiddler 拦截将不起作用。但大多数网站和应用程序不使用固定。如果网站或应用程序使用固定,则除了越狱设备之外没有其他解决方法。这并不是 Fiddler 独有的限制——每个 HTTPS 解密代理都有完全相同的限制。

我想这会回答你的第一个答案,而且 IE 正在使用证书固定,正如我记得的那样。