I have set-up my Fiddler Proxy like in the gist here.
Code:
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);
}
}
}
Its purpose is to capture and analyze traffic from Windows, Mac OS X, Android and iOS browsers (Chrome, Firefox and Safari mostly, on both Desktop and Mobile devices).
So far, it seems to be working on:
- Windows browsers: Chrome, Firefox. Not working on IE and Edge
- Android: Chrome
- Mac OS: Chrome, Firefox. Safari is not working
- iOS: none
In my logs files I'm seeing the following errors logged by Fiddler on browsers not working (for all devices). Example for an HTTPS request:
2018-02-14 17:25:50.3860 | INFO | ** LogString: !SecureClientPipeDirect failed: System.IO.IOException Authentication failed because the remote party has closed the transport stream. for pipe (CN=*.optimizely.com, O=DO_NOT_TRUST_BC, OU=Created by http://www.fiddler2.com)
From what I read in the last couple of day trying to figure out a solution for this, the reason would be the certificates that are not trusted on the device.
The tests are being ran on BrowserStack using the feature they provide called BrowserStack Local. Details about it are here and here.
Now my questions could be split between Desktop and Mobile:
- Why is Chrome and Firefox able to make HTTPS requests while IE, Edge and Safari fails to do so?
- For iOS specifically, there's a Fiddler for iOS documentation here specifying the steps required in order to configure the device. However, as I already mentioned, I'm not using in-house iOS devices, but physical ones provided by BrowserStack. Is there a way to programatically trust a certificate on an iOS device (iOS 9.x, iOS 10.x, iOS 11.x)?
Are there any workarounds that I could use?
session.oRequest["User-Agent"] = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0_1 like Mac OS X) AppleWebKit/604.2.10 (KHTML, like Gecko) Version/11.0 Mobile/15A8391 Safari/604.1"; session.oRequest["Connection"] = "keep-alive";
– Dori