Exemple #1
0
        public void Start()
        {
            if (IsEnabled)
            {
                Port = GetFreeTcpPort();
                var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, Port);

                ProxyServer.AddEndPoint(explicitEndPoint);
                ProxyServer.Start();

                ProxyServer.BeforeRequest  += OnRequestCaptureTrafficEventHandler;
                ProxyServer.BeforeResponse += OnResponseCaptureTrafficEventHandler;
                ProxyServer.BeforeRequest  += OnRequestBlockResourceEventHandler;
                ProxyServer.BeforeRequest  += OnRequestRedirectTrafficEventHandler;
                ProxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
                ProxyServer.ClientCertificateSelectionCallback  += OnCertificateSelection;
            }
        }
Exemple #2
0
        public EtpSelfHostedProxyWebServer(int port, IEtpSelfHostedWebServer proxiedServer)
        {
            _proxiedServer = proxiedServer;
            _proxyServer   = new ProxyServer();

            var uri     = proxiedServer.Uri;
            var builder = new UriBuilder(uri.Scheme, uri.Host, port, uri.AbsolutePath, uri.Query);

            ProxyUri = builder.Uri;

            var endPoint = new ExplicitProxyEndPoint(IPAddress.Loopback, ProxyUri.Port, false);

            endPoint.GenericCertificate = new System.Security.Cryptography.X509Certificates.X509Certificate2();

            _proxyServer.ProxyBasicAuthenticateFunc = HandleBasicAuthentication;

            _proxyServer.AddEndPoint(endPoint);
        }
Exemple #3
0
        public static void Main(string[] args)
        {
            var proxyServer = new ProxyServer();

            proxyServer.CertificateManager.EnsureRootCertificate();
            proxyServer.CertificateManager.TrustRootCertificate();
            proxyServer.BeforeRequest += OnRequest;

            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 1234);

            proxyServer.AddEndPoint(explicitEndPoint);
            proxyServer.Start();
            proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
            proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);

            Console.Read();
            proxyServer.Stop();
        }
Exemple #4
0
        public void StartProxy()
        {
            proxyServer.BeforeRequest += OnRequest;
            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true);//listen on port 8000

            proxyServer.AddEndPoint(explicitEndPoint);
            proxyServer.Start();


            foreach (var endPoint in proxyServer.ProxyEndPoints)
            {
                Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
                                  endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
            }

            //Only explicit proxies can be set as system proxy!
            proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
            proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
        }
Exemple #5
0
        public ProxyTorController(ConfigProxy config)
        {
            Task.Run(() => listenToConsole());

            _proxyServer = new ProxyServer();


            _proxyServer.ExceptionFunc = async exception =>
            {
                if (exception is ProxyHttpException phex)
                {
                    WriteToConsole(exception.Message + ": " + phex.InnerException?.Message, ConsoleColor.Red);
                }
                else
                {
                    WriteToConsole(exception.Message, ConsoleColor.Red);
                }
            };

            _proxyServer.TcpTimeWaitSeconds       = 60;
            _proxyServer.ConnectionTimeOutSeconds = 65;
            _proxyServer.ReuseSocket              = false;
            _proxyServer.EnableConnectionPool     = true;
            _proxyServer.ForwardToUpstreamGateway = true;

            _proxyServer.CertificateManager.SaveFakeCertificates = true;


            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, config.Port, false);

            _proxyServer.AddEndPoint(explicitEndPoint);

            _tors = new List <TorInfo>();

            for (var i = config.Tor.PortFrom; i <= config.Tor.PortTo; i++)
            {
                _tors.Add(new TorInfo
                {
                    HostName = config.Tor.HostName,
                    Port     = i
                });
            }
        }
Exemple #6
0
        public void StartProxy(int proxyPort)
        {
            proxyServer.BeforeRequest  += OnRequest;
            proxyServer.BeforeResponse += OnResponse;
            proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
            proxyServer.ClientCertificateSelectionCallback  += OnCertificateSelection;

            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, proxyPort, true);

            //An explicit endpoint is where the client knows about the existance of a proxy
            //So client sends request in a proxy friendly manner
            proxyServer.AddEndPoint(explicitEndPoint);
            proxyServer.Start();

            foreach (var endPoint in proxyServer.ProxyEndPoints)
            {
                Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
                                  endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
            }
        }
Exemple #7
0
        static void Main(string[] args)
        {
            _Config = GetConfig();

            var port        = _Config.GetValue <int>("Proxy:Port");
            var proxyServer = new ProxyServer();

            proxyServer.BeforeRequest += OnRequest;

            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, port, false);

            proxyServer.AddEndPoint(explicitEndPoint);
            proxyServer.Start();

            Console.WriteLine($"** Logging proxy listening on port: {port} **");
            _ResetEvent.WaitOne();

            proxyServer.BeforeRequest -= OnRequest;
            proxyServer.Stop();
        }
Exemple #8
0
        static void Main(string[] args)
        {
            var proxyServer = new ProxyServer();

            var httpEP  = new ExplicitProxyEndPoint(IPAddress.Any, 14300, false);
            var httpsEP = new ExplicitProxyEndPoint(IPAddress.Any, 14301, true);

            proxyServer.AddEndPoint(httpEP);
            proxyServer.AddEndPoint(httpsEP);

            proxyServer.BeforeRequest += OnRequest;

            proxyServer.Start();

            Console.WriteLine("Press a key when you're done.");
            Console.Read();

            proxyServer.BeforeRequest -= OnRequest;
            proxyServer.Stop();
        }
Exemple #9
0
        private static void Main(string[] args)
        {
#if DEBUG
            Debug.Listeners.Add(new ConsoleTraceListener());
#endif

            PrintLogo();

#if !NO_PLUGINS
            Console.WriteLine("Loading plugins");
            Manager.LoadPlugins();
            foreach (IHopePlugin plugin in Manager.Plugins)
            {
                plugin.Load();
            }
            Console.WriteLine($"Loaded {Manager.Plugins.Count} Plugin{(Manager.Plugins.Count == 1 ? "" : "s")}!");
#else
#warning Plugin support disabled!
            Console.WriteLine("Warning: This build does not support plugins.");
#endif

            Console.WriteLine("Preparing proxy server...");
            var proxyServer = new ProxyServer();
            proxyServer.TrustRootCertificate = true;    //this is needed for decrypting SSL traffic
            proxyServer.BeforeRequest       += OnRequest;
            proxyServer.BeforeResponse      += OnResponse;

            var endpoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true);

            proxyServer.AddEndPoint(endpoint);

            Console.WriteLine("Starting proxy server...");
            proxyServer.Start();

            Console.WriteLine("Setting as system proxy...");
            proxyServer.SetAsSystemHttpProxy(endpoint);
            proxyServer.SetAsSystemHttpsProxy(endpoint);

            Console.WriteLine("Waiting...");
            Console.ReadLine();
        }
Exemple #10
0
        public void Start()
        {
            Log("Start");

            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
            {
                ExcludedHttpsHostNameRegex = new List <string>
                {
                    "player.com",
                    "dropbox.com"
                }
            };

            _proxyServer.AddEndPoint(explicitEndPoint);
            _proxyServer.Start();

            _proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
            _proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);

            OnStarted?.Invoke(this, EventArgs.Empty);
        }
Exemple #11
0
        public void StartProxy()
        {
            _proxyServer.BeforeRequest += OnRequest;
            _proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
            _proxyServer.ClientCertificateSelectionCallback  += OnCertificateSelection;

            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true);

            _proxyServer.AddEndPoint(explicitEndPoint);
            _proxyServer.Start();


            foreach (var endPoint in _proxyServer.ProxyEndPoints)
            {
                Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
                                  endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
            }

            _proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
            _proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
        }
        /// <summary>
        /// Set the given explicit end point as the default proxy server for current machine
        /// </summary>
        /// <param name="endPoint"></param>
        public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint)
        {
            if (RunTime.IsRunningOnMono())
            {
                throw new Exception("Mono Runtime do not support system proxy settings.");
            }

            ValidateEndPointAsSystemProxy(endPoint);

            //clear any settings previously added
            ProxyEndPoints.OfType <ExplicitProxyEndPoint>().ToList().ForEach(x => x.IsSystemHttpProxy = false);

            systemProxySettingsManager.SetHttpProxy(
                Equals(endPoint.IpAddress, IPAddress.Any) | Equals(endPoint.IpAddress, IPAddress.Loopback) ? "127.0.0.1" : endPoint.IpAddress.ToString(), endPoint.Port);

            endPoint.IsSystemHttpProxy = true;
#if !DEBUG
            firefoxProxySettingsManager.AddFirefox();
#endif
            Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System HTTP Proxy", endPoint.IpAddress, endPoint.Port);
        }
Exemple #13
0
        public static void Start()
        {
            string certName     = "rootCert.pfx";
            string certPassword = "******";

            proxyServer.ForwardToUpstreamGateway = true;
            proxyServer.CertificateManager.SaveFakeCertificates = true;

            proxyServer.CertificateManager.PfxPassword = certPassword;
            proxyServer.CertificateManager.EnsureRootCertificate();
            proxyServer.CertificateManager.TrustRootCertificate(true);
            proxyServer.CertificateManager.TrustRootCertificateAsAdmin(true);

            if (!File.Exists(certName))
            {
                proxyServer.CertificateManager.CreateRootCertificate(true);
            }

            proxyServer.CertificateManager.RootCertificate = new X509Certificate2(certName, certPassword, X509KeyStorageFlags.Exportable);

            proxyServer.BeforeRequest  += OnRequest;
            proxyServer.BeforeResponse += OnResponse;

            //proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
            //proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;

            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8080);

            proxyServer.AddEndPoint(explicitEndPoint);

            // Fired when a CONNECT request is received
            explicitEndPoint.BeforeTunnelConnectRequest  += OnBeforeTunnelConnectRequest;
            explicitEndPoint.BeforeTunnelConnectResponse += OnBeforeTunnelConnectResponse;

            proxyServer.Start();

            //Only explicit proxies can be set as system proxy!
            proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
            proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
        }
        public void Start()
        {
            // Link up handlers
            _proxyServer.BeforeRequest  += OnRequest;
            _proxyServer.BeforeResponse += OnResponse;
            _proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
            _proxyServer.ClientCertificateSelectionCallback  += OnCertificateSelection;

            // Set ip and port to monitor
            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Parse(ip), Port, true);

            _proxyServer.AddEndPoint(explicitEndPoint);

            // Start proxy server
            _proxyServer.Start();

            if (Out != StreamWriter.Null)
            {
                Out.WriteLine($"[+++] Proxy started: listening at {explicitEndPoint.IpAddress}:{explicitEndPoint.Port} ");
                Out.WriteLine();
            }
        }
Exemple #15
0
        public void StartProxy(int port, SafeNode[] nodes)
        {
            this.nodes = nodes;
            var PEP = new ExplicitProxyEndPoint(IPAddress.Any, port, false)
            {
            };

            proxyServer.TrustRootCertificate = true;
            proxyServer.BeforeRequest       += OnRequest;
            proxyServer.BeforeResponse      += OnResponse;
            proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
            proxyServer.ClientCertificateSelectionCallback  += OnCertificateSelection;
            proxyServer.AddEndPoint(PEP);
            proxyServer.Start();
            foreach (var endPoint in proxyServer.ProxyEndPoints)
            {
                Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
                                  endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
            }
            proxyServer.SetAsSystemHttpProxy(PEP);
            proxyServer.SetAsSystemHttpsProxy(PEP);
        }
Exemple #16
0
        private void LoadingForm_Shown(object sender, EventArgs e)
        {
            internalSetupLbl.CurrentStatus = StatusLabel.Status.Current;
            mainForm = new MainForm();
            //explicitEndpoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true);
            explicitEndpoint = new ExplicitProxyEndPoint(IPAddress.Parse("127.0.0.1"), 8000, true);
            proxyServer      = new ProxyServer("Test cert", "Test cert issuer");
            proxyServer.ForwardToUpstreamGateway = true;
            mainForm.proxyServer = proxyServer;
            proxyServer.AddEndPoint(explicitEndpoint);

            proxyServer.BeforeRequest  += mainForm.ProxyServer_BeforeRequest;
            proxyServer.BeforeResponse += mainForm.ProxyServer_BeforeResponse;
            proxyServer.AfterResponse  += mainForm.ProxyServer_AfterResponse;
            explicitEndpoint.BeforeTunnelConnectRequest  += mainForm.ExplicitEndpoint_BeforeTunnelConnectRequest;
            explicitEndpoint.BeforeTunnelConnectResponse += mainForm.ExplicitEndpoint_BeforeTunnelConnectResponse;
            proxyServer.ClientConnectionCountChanged     += mainForm.ProxyServer_ClientConnectionCountChanged;
            proxyServer.ServerConnectionCountChanged     += mainForm.ProxyServer_ServerConnectionCountChanged;

            internalSetupLbl.CurrentStatus = StatusLabel.Status.Done;

            injectDetour();
        }
Exemple #17
0
        public void StartProxy()
        {
            newEndPoint = new ExplicitProxyEndPoint(IPAddress.Loopback, _portNumber, true);

            SetRequestConfiguration(); //set actual blocking methods

            StartProxyWithEndPoint();

            if (_isSystemProxy)
            {
                _proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
                _proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
            }

            foreach (var endPoint in _proxyServer.ProxyEndPoints)
            {
                Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
                                  endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
            }

            ProxyRunning   = _proxyServer.ProxyRunning;
            ProxyIsEnabled = _proxyServer.ProxyRunning;
        }
Exemple #18
0
        /// <summary>
        /// Set the given explicit end point as the default proxy server for current machine
        /// </summary>
        /// <param name="endPoint"></param>
        public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint)
        {
            if (RunTime.IsRunningOnMono)
            {
                throw new Exception("Mono Runtime do not support system proxy settings.");
            }

            ValidateEndPointAsSystemProxy(endPoint);

            if (!endPoint.EnableSsl)
            {
                throw new Exception("Endpoint do not support Https connections");
            }

            //clear any settings previously added
            ProxyEndPoints.OfType <ExplicitProxyEndPoint>()
            .ToList()
            .ForEach(x => x.IsSystemHttpsProxy = false);

            EnsureRootCertificate();

            //If certificate was trusted by the machine
            if (CertificateManager.CertValidated)
            {
                systemProxySettingsManager.SetHttpsProxy(
                    Equals(endPoint.IpAddress, IPAddress.Any) |
                    Equals(endPoint.IpAddress, IPAddress.Loopback) ? "127.0.0.1" : endPoint.IpAddress.ToString(),
                    endPoint.Port);
            }


            endPoint.IsSystemHttpsProxy = true;

            firefoxProxySettingsManager.UseSystemProxy();

            Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System HTTPS Proxy", endPoint.IpAddress, endPoint.Port);
        }
Exemple #19
0
        /// <summary>
        /// Fonction qui va démarrer le proxy.
        /// Elle va ajouter des évènement pour les requêtes et réponses HTTP
        /// Elle va ajouter des certificat pour le HTTPS
        /// </summary>
        public void StartProxy()
        {
            proxyServer.BeforeRequest  += OnRequest;
            proxyServer.BeforeResponse += OnResponse;
            proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
            proxyServer.ClientCertificateSelectionCallback  += OnCertificateSelection;

            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
            {
            };

            proxyServer.AddEndPoint(explicitEndPoint);
            proxyServer.Start();

            var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
            {
                GenericCertificateName = "google.com"
            };

            proxyServer.AddEndPoint(transparentEndPoint);

            proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
            proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
        }
        public void StartProxy()
        {
            proxyServer.BeforeRequest  += OnRequest;
            proxyServer.BeforeResponse += OnResponse;

            proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
            proxyServer.ClientCertificateSelectionCallback  += OnCertificateSelection;

            //proxyServer.EnableWinAuth = true;

            explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
            {
                //You can set only one of the ExcludedHttpsHostNameRegex and IncludedHttpsHostNameRegex properties, otherwise ArgumentException will be thrown

                //Use self-issued generic certificate on all https requests
                //Optimizes performance by not creating a certificate for each https-enabled domain
                //Useful when certificate trust is not required by proxy clients
                //GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
            };

            //Fired when a CONNECT request is received
            explicitEndPoint.BeforeTunnelConnect += OnBeforeTunnelConnect;


            explicitEndPoint.TunnelConnectRequest  += OnTunnelConnectRequest;
            explicitEndPoint.TunnelConnectResponse += OnTunnelConnectResponse;

            //An explicit endpoint is where the client knows about the existence of a proxy
            //So client sends request in a proxy friendly manner
            proxyServer.AddEndPoint(explicitEndPoint);
            proxyServer.Start();

            //Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
            //A transparent endpoint usually requires a network router port forwarding HTTP(S) packets or DNS
            //to send data to this endPoint
            //var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 443, true)
            //{
            //    //Generic Certificate hostname to use
            //    //When SNI is disabled by client
            //    GenericCertificateName = "google.com"
            //};

            //proxyServer.AddEndPoint(transparentEndPoint);

            //proxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
            //proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };

            foreach (var endPoint in proxyServer.ProxyEndPoints)
            {
                Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ", endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
            }

#if NETSTANDARD2_0
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
#endif
            {
                //Only explicit proxies can be set as system proxy!
                //proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
                //proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
                proxyServer.SetAsSystemProxy(explicitEndPoint, ProxyProtocolType.AllHttp);
            }
        }
Exemple #21
0
        static void Main(string[] args)
        {
            var proxyServer = new ProxyServer();

            //locally trust root certificate used by this proxy
            proxyServer.TrustRootCertificate = true;

            proxyServer.BeforeRequest  += OnRequest;
            proxyServer.BeforeResponse += OnResponse;
            proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
            proxyServer.ClientCertificateSelectionCallback  += OnCertificateSelection;


            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
            {
                //Exclude Https addresses you don't want to proxy
                //Usefull for clients that use certificate pinning
                //for example dropbox.com
                // ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" }

                //Use self-issued generic certificate on all https requests
                //Optimizes performance by not creating a certificate for each https-enabled domain
                //Usefull when certificate trust is not requiered by proxy clients
                // GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
            };

            //An explicit endpoint is where the client knows about the existance of a proxy
            //So client sends request in a proxy friendly manner
            proxyServer.AddEndPoint(explicitEndPoint);
            proxyServer.Start();


            //Transparent endpoint is usefull for reverse proxying (client is not aware of the existance of proxy)
            //A transparent endpoint usually requires a network router port forwarding HTTP(S) packets to this endpoint
            //Currently do not support Server Name Indication (It is not currently supported by SslStream class)
            //That means that the transparent endpoint will always provide the same Generic Certificate to all HTTPS requests
            //In this example only google.com will work for HTTPS requests
            //Other sites will receive a certificate mismatch warning on browser
            var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
            {
                GenericCertificateName = "google.com"
            };

            proxyServer.AddEndPoint(transparentEndPoint);

            //proxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
            //proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };

            foreach (var endPoint in proxyServer.ProxyEndPoints)
            {
                Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
                                  endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
            }

            //Only explicit proxies can be set as system proxy!
            proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
            proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);

            //wait here (You can use something else as a wait function, I am using this as a demo)
            Console.Read();

            //Unsubscribe & Quit
            proxyServer.BeforeRequest  -= OnRequest;
            proxyServer.BeforeResponse -= OnResponse;
            proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
            proxyServer.ClientCertificateSelectionCallback  -= OnCertificateSelection;

            proxyServer.Stop();
        }
Exemple #22
0
        /// <summary>
        ///     This is called when client is aware of proxy
        ///     So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
        /// </summary>
        /// <param name="endPoint">The explicit endpoint.</param>
        /// <param name="clientConnection">The client connection.</param>
        /// <returns>The task.</returns>
        private async Task handleClient(ExplicitProxyEndPoint endPoint, TcpClientConnection clientConnection)
        {
            var cancellationTokenSource = new CancellationTokenSource();
            var cancellationToken       = cancellationTokenSource.Token;

            var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken);

            Task <TcpServerConnection>?prefetchConnectionTask = null;
            bool closeServerConnection = false;
            bool calledRequestHandler  = false;

            try
            {
                TunnelConnectSessionEventArgs?connectArgs = null;

                var method = await HttpHelper.GetMethod(clientStream, BufferPool, cancellationToken);

                if (clientStream.IsClosed)
                {
                    return;
                }

                // Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
                if (method == KnownMethod.Connect)
                {
                    // read the first line HTTP command
                    var requestLine = await clientStream.ReadRequestLine(cancellationToken);

                    if (requestLine.IsEmpty())
                    {
                        return;
                    }

                    var connectRequest = new ConnectRequest(requestLine.RequestUri)
                    {
                        RequestUriString8 = requestLine.RequestUri,
                        HttpVersion       = requestLine.Version
                    };

                    await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken);

                    connectArgs             = new TunnelConnectSessionEventArgs(this, endPoint, connectRequest, clientStream, cancellationTokenSource);
                    clientStream.DataRead  += (o, args) => connectArgs.OnDataSent(args.Buffer, args.Offset, args.Count);
                    clientStream.DataWrite += (o, args) => connectArgs.OnDataReceived(args.Buffer, args.Offset, args.Count);

                    await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc);

                    // filter out excluded host names
                    bool decryptSsl  = endPoint.DecryptSsl && connectArgs.DecryptSsl;
                    bool sendRawData = !decryptSsl;

                    if (connectArgs.DenyConnect)
                    {
                        if (connectArgs.HttpClient.Response.StatusCode == 0)
                        {
                            connectArgs.HttpClient.Response = new Response
                            {
                                HttpVersion       = HttpHeader.Version11,
                                StatusCode        = (int)HttpStatusCode.Forbidden,
                                StatusDescription = "Forbidden"
                            };
                        }

                        // send the response
                        await clientStream.WriteResponseAsync(connectArgs.HttpClient.Response, cancellationToken);

                        return;
                    }

                    if (await checkAuthorization(connectArgs) == false)
                    {
                        await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc);

                        // send the response
                        await clientStream.WriteResponseAsync(connectArgs.HttpClient.Response, cancellationToken);

                        return;
                    }

                    // write back successful CONNECT response
                    var response = ConnectResponse.CreateSuccessfulConnectResponse(requestLine.Version);

                    // Set ContentLength explicitly to properly handle HTTP 1.0
                    response.ContentLength = 0;
                    response.Headers.FixProxyHeaders();
                    connectArgs.HttpClient.Response = response;

                    await clientStream.WriteResponseAsync(response, cancellationToken);

                    var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);

                    if (clientStream.IsClosed)
                    {
                        return;
                    }

                    bool isClientHello = clientHelloInfo != null;
                    if (clientHelloInfo != null)
                    {
                        connectRequest.TunnelType      = TunnelType.Https;
                        connectRequest.ClientHelloInfo = clientHelloInfo;
                    }

                    await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc, isClientHello);

                    if (decryptSsl && clientHelloInfo != null)
                    {
                        connectRequest.IsHttps = true; // todo: move this line to the previous "if"
                        clientStream.Connection.SslProtocol = clientHelloInfo.SslProtocol;

                        bool http2Supported = false;

                        if (EnableHttp2)
                        {
                            var alpn = clientHelloInfo.GetAlpn();
                            if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2))
                            {
                                // test server HTTP/2 support
                                try
                                {
                                    // todo: this is a hack, because Titanium does not support HTTP protocol changing currently
                                    var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                                    true, SslExtensions.Http2ProtocolAsList,
                                                                                                    true, cancellationToken);

                                    http2Supported = connection.NegotiatedApplicationProtocol ==
                                                     SslApplicationProtocol.Http2;

                                    // release connection back to pool instead of closing when connection pool is enabled.
                                    await tcpConnectionFactory.Release(connection, true);
                                }
                                catch (Exception)
                                {
                                    // ignore
                                }
                            }
                        }

                        if (EnableTcpServerConnectionPrefetch)
                        {
                            IPAddress[]? ipAddresses = null;
                            try
                            {
                                // make sure the host can be resolved before creating the prefetch task
                                ipAddresses = await Dns.GetHostAddressesAsync(connectArgs.HttpClient.Request.RequestUri.Host);
                            }
                            catch (SocketException) { }

                            if (ipAddresses != null && ipAddresses.Length > 0)
                            {
                                // don't pass cancellation token here
                                // it could cause floating server connections when client exits
                                prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                                  true, null, false,
                                                                                                  CancellationToken.None);
                            }
                        }

                        string connectHostname = requestLine.RequestUri.GetString();
                        int    idx             = connectHostname.IndexOf(":");
                        if (idx >= 0)
                        {
                            connectHostname = connectHostname.Substring(0, idx);
                        }

                        X509Certificate2?certificate = null;
                        SslStream?       sslStream   = null;
                        try
                        {
                            sslStream = new SslStream(clientStream, false);

                            string certName = HttpHelper.GetWildCardDomainName(connectHostname);
                            certificate = endPoint.GenericCertificate ??
                                          await CertificateManager.CreateServerCertificate(certName);

                            // Successfully managed to authenticate the client using the fake certificate
                            var options = new SslServerAuthenticationOptions();
                            if (EnableHttp2 && http2Supported)
                            {
                                options.ApplicationProtocols = clientHelloInfo.GetAlpn();
                                if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0)
                                {
                                    options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList;
                                }
                            }

                            options.ServerCertificate              = certificate;
                            options.ClientCertificateRequired      = false;
                            options.EnabledSslProtocols            = SupportedSslProtocols;
                            options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck;
                            await sslStream.AuthenticateAsServerAsync(options, cancellationToken);

#if NETSTANDARD2_1
                            clientStream.Connection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif

                            // HTTPS server created - we can now decrypt the client's traffic
                            clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool, cancellationToken);
                            sslStream    = null; // clientStream was created, no need to keep SSL stream reference

                            clientStream.DataRead  += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count);
                            clientStream.DataWrite += (o, args) => connectArgs.OnDecryptedDataReceived(args.Buffer, args.Offset, args.Count);
                        }
                        catch (Exception e)
                        {
                            sslStream?.Dispose();

                            var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
                            throw new ProxyConnectException(
                                      $"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs);
                        }

                        method = await HttpHelper.GetMethod(clientStream, BufferPool, cancellationToken);

                        if (clientStream.IsClosed)
                        {
                            return;
                        }

                        if (method == KnownMethod.Invalid)
                        {
                            sendRawData = true;
                            await tcpConnectionFactory.Release(prefetchConnectionTask, true);

                            prefetchConnectionTask = null;
                        }
                    }
                    else if (clientHelloInfo == null)
                    {
                        method = await HttpHelper.GetMethod(clientStream, BufferPool, cancellationToken);

                        if (clientStream.IsClosed)
                        {
                            return;
                        }
                    }

                    if (cancellationTokenSource.IsCancellationRequested)
                    {
                        throw new Exception("Session was terminated by user.");
                    }

                    if (method == KnownMethod.Invalid)
                    {
                        sendRawData = true;
                    }

                    // Hostname is excluded or it is not an HTTPS connect
                    if (sendRawData)
                    {
                        // create new connection to server.
                        // If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then
                        // this connection should not be HTTPS.
                        var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                        true, null,
                                                                                        true, cancellationToken);

                        try
                        {
                            if (isClientHello)
                            {
                                int available = clientStream.Available;
                                if (available > 0)
                                {
                                    // send the buffered data
                                    var data = BufferPool.GetBuffer();

                                    try
                                    {
                                        // clientStream.Available should be at most BufferSize because it is using the same buffer size
                                        int read = await clientStream.ReadAsync(data, 0, available, cancellationToken);

                                        if (read != available)
                                        {
                                            throw new Exception("Internal error.");
                                        }

                                        await connection.Stream.WriteAsync(data, 0, available, true, cancellationToken);
                                    }
                                    finally
                                    {
                                        BufferPool.ReturnBuffer(data);
                                    }
                                }

                                var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream, BufferPool, cancellationToken);

                                ((ConnectResponse)connectArgs.HttpClient.Response).ServerHelloInfo = serverHelloInfo;
                            }

                            if (!clientStream.IsClosed && !connection.Stream.IsClosed)
                            {
                                await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool,
                                                        null, null, connectArgs.CancellationTokenSource, ExceptionFunc);
                            }
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }

                        return;
                    }
                }

                if (connectArgs != null && method == KnownMethod.Pri)
                {
                    // todo
                    string?httpCmd = await clientStream.ReadLineAsync(cancellationToken);

                    if (httpCmd == "PRI * HTTP/2.0")
                    {
                        connectArgs.HttpClient.ConnectRequest !.TunnelType = TunnelType.Http2;

                        // HTTP/2 Connection Preface
                        string?line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != string.Empty)
                        {
                            throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
                        }

                        line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != "SM")
                        {
                            throw new Exception($"HTTP/2 Protocol violation. 'SM' expected, '{line}' received");
                        }

                        line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != string.Empty)
                        {
                            throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
                        }

                        var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                        true, SslExtensions.Http2ProtocolAsList,
                                                                                        true, cancellationToken);

                        try
                        {
#if NETSTANDARD2_1
                            var connectionPreface = new ReadOnlyMemory <byte>(Http2Helper.ConnectionPreface);
                            await connection.Stream.WriteAsync(connectionPreface, cancellationToken);

                            await Http2Helper.SendHttp2(clientStream, connection.Stream,
                                                        () => new SessionEventArgs(this, endPoint, clientStream, connectArgs?.HttpClient.ConnectRequest, cancellationTokenSource)
                            {
                                UserData = connectArgs?.UserData
                            },
                                                        async args => { await onBeforeRequest(args); },
                                                        async args => { await onBeforeResponse(args); },
                                                        connectArgs.CancellationTokenSource, clientStream.Connection.Id, ExceptionFunc);
#endif
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }
                    }
                }

                calledRequestHandler = true;

                // Now create the request
                await handleHttpSessionRequest(endPoint, clientStream, cancellationTokenSource, connectArgs, prefetchConnectionTask);
            }
            catch (ProxyException e)
            {
                closeServerConnection = true;
                onException(clientStream, e);
            }
            catch (IOException e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Connection was aborted", e));
            }
            catch (SocketException e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Could not connect", e));
            }
            catch (Exception e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Error occured in whilst handling the client", e));
            }
            finally
            {
                if (!cancellationTokenSource.IsCancellationRequested)
                {
                    cancellationTokenSource.Cancel();
                }

                if (!calledRequestHandler)
                {
                    await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
                }

                clientStream.Dispose();
            }
        }
        /// <summary>
        ///     This is called when client is aware of proxy
        ///     So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
        /// </summary>
        /// <param name="endPoint">The explicit endpoint.</param>
        /// <param name="clientConnection">The client connection.</param>
        /// <returns>The task.</returns>
        private async Task handleClient(ExplicitProxyEndPoint endPoint, TcpClientConnection clientConnection)
        {
            var cancellationTokenSource = new CancellationTokenSource();
            var cancellationToken       = cancellationTokenSource.Token;

            var clientStream       = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize);
            var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);

            Task <TcpServerConnection> prefetchConnectionTask = null;
            bool closeServerConnection = false;
            bool calledRequestHandler  = false;

            SslStream sslStream = null;

            try
            {
                string connectHostname = null;
                TunnelConnectSessionEventArgs connectArgs = null;

                // Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
                if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1)
                {
                    // read the first line HTTP command
                    string httpCmd = await clientStream.ReadLineAsync(cancellationToken);

                    if (string.IsNullOrEmpty(httpCmd))
                    {
                        return;
                    }

                    Request.ParseRequestLine(httpCmd, out string _, out string httpUrl, out var version);

                    var httpRemoteUri = new Uri("http://" + httpUrl);
                    connectHostname = httpRemoteUri.Host;

                    var connectRequest = new ConnectRequest
                    {
                        RequestUri  = httpRemoteUri,
                        OriginalUrl = httpUrl,
                        HttpVersion = version
                    };

                    await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken);

                    connectArgs = new TunnelConnectSessionEventArgs(this, endPoint, connectRequest,
                                                                    cancellationTokenSource);
                    connectArgs.ProxyClient.Connection   = clientConnection;
                    connectArgs.ProxyClient.ClientStream = clientStream;

                    await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc);

                    // filter out excluded host names
                    bool decryptSsl = endPoint.DecryptSsl && connectArgs.DecryptSsl;

                    if (connectArgs.DenyConnect)
                    {
                        if (connectArgs.HttpClient.Response.StatusCode == 0)
                        {
                            connectArgs.HttpClient.Response = new Response
                            {
                                HttpVersion       = HttpHeader.Version11,
                                StatusCode        = (int)HttpStatusCode.Forbidden,
                                StatusDescription = "Forbidden"
                            };
                        }

                        // send the response
                        await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
                                                                    cancellationToken : cancellationToken);

                        return;
                    }

                    if (await checkAuthorization(connectArgs) == false)
                    {
                        await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc);

                        // send the response
                        await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
                                                                    cancellationToken : cancellationToken);

                        return;
                    }

                    // write back successful CONNECT response
                    var response = ConnectResponse.CreateSuccessfulConnectResponse(version);

                    // Set ContentLength explicitly to properly handle HTTP 1.0
                    response.ContentLength = 0;
                    response.Headers.FixProxyHeaders();
                    connectArgs.HttpClient.Response = response;

                    await clientStreamWriter.WriteResponseAsync(response, cancellationToken : cancellationToken);

                    var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);

                    bool isClientHello = clientHelloInfo != null;
                    if (isClientHello)
                    {
                        connectRequest.TunnelType      = TunnelType.Https;
                        connectRequest.ClientHelloInfo = clientHelloInfo;
                    }

                    await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc, isClientHello);

                    if (decryptSsl && isClientHello)
                    {
                        connectRequest.RequestUri = new Uri("https://" + httpUrl);

                        bool http2Supported = false;

                        var alpn = clientHelloInfo.GetAlpn();
                        if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2))
                        {
                            // test server HTTP/2 support
                            try
                            {
                                // todo: this is a hack, because Titanium does not support HTTP protocol changing currently
                                var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                                isConnect : true, applicationProtocols : SslExtensions.Http2ProtocolAsList,
                                                                                                noCache : true, cancellationToken : cancellationToken);

                                http2Supported = connection.NegotiatedApplicationProtocol ==
                                                 SslApplicationProtocol.Http2;
                                //release connection back to pool instead of closing when connection pool is enabled.
                                await tcpConnectionFactory.Release(connection, true);
                            }
                            catch (Exception)
                            {
                                // ignore
                            }
                        }

                        if (EnableTcpServerConnectionPrefetch)
                        {
                            IPAddress[] ipAddresses = null;
                            try
                            {
                                //make sure the host can be resolved before creating the prefetch task
                                ipAddresses = await Dns.GetHostAddressesAsync(connectArgs.HttpClient.Request.RequestUri.Host);
                            }
                            catch (SocketException) { }

                            if (ipAddresses != null && ipAddresses.Length > 0)
                            {
                                //don't pass cancellation token here
                                //it could cause floating server connections when client exits
                                prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                                  isConnect: true, applicationProtocols: null, noCache: false,
                                                                                                  cancellationToken: CancellationToken.None);
                            }
                        }

                        X509Certificate2 certificate = null;
                        try
                        {
                            sslStream = new SslStream(clientStream, false);

                            string certName = HttpHelper.GetWildCardDomainName(connectHostname);
                            certificate = endPoint.GenericCertificate ??
                                          await CertificateManager.CreateServerCertificate(certName);

                            // Successfully managed to authenticate the client using the fake certificate
                            var options = new SslServerAuthenticationOptions();
                            if (EnableHttp2 && http2Supported)
                            {
                                options.ApplicationProtocols = clientHelloInfo.GetAlpn();
                                if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0)
                                {
                                    options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList;
                                }
                            }

                            options.ServerCertificate              = certificate;
                            options.ClientCertificateRequired      = false;
                            options.EnabledSslProtocols            = SupportedSslProtocols;
                            options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck;
                            await sslStream.AuthenticateAsServerAsync(options, cancellationToken);

#if NETCOREAPP2_1
                            clientConnection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif

                            // HTTPS server created - we can now decrypt the client's traffic
                            clientStream       = new CustomBufferedStream(sslStream, BufferPool, BufferSize);
                            clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);
                        }
                        catch (Exception e)
                        {
                            var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
                            throw new ProxyConnectException(
                                      $"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs);
                        }

                        if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == -1)
                        {
                            decryptSsl = false;
                        }

                        if (!decryptSsl)
                        {
                            await tcpConnectionFactory.Release(prefetchConnectionTask, true);

                            prefetchConnectionTask = null;
                        }
                    }

                    if (cancellationTokenSource.IsCancellationRequested)
                    {
                        throw new Exception("Session was terminated by user.");
                    }

                    // Hostname is excluded or it is not an HTTPS connect
                    if (!decryptSsl || !isClientHello)
                    {
                        if (!isClientHello)
                        {
                            connectRequest.TunnelType = TunnelType.Websocket;
                        }

                        // create new connection to server.
                        // If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then
                        // this connection should not be HTTPS.
                        var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                        isConnect : true, applicationProtocols : SslExtensions.Http2ProtocolAsList,
                                                                                        noCache : true, cancellationToken : cancellationToken);

                        try
                        {
                            if (isClientHello)
                            {
                                int available = clientStream.Available;
                                if (available > 0)
                                {
                                    // send the buffered data
                                    var data = BufferPool.GetBuffer(BufferSize);

                                    try
                                    {
                                        await clientStream.ReadAsync(data, 0, available, cancellationToken);

                                        // clientStream.Available should be at most BufferSize because it is using the same buffer size
                                        await connection.StreamWriter.WriteAsync(data, 0, available, true, cancellationToken);
                                    }
                                    finally
                                    {
                                        BufferPool.ReturnBuffer(data);
                                    }
                                }

                                var serverHelloInfo = await SslTools.PeekServerHello(connection.Stream, BufferPool, cancellationToken);

                                ((ConnectResponse)connectArgs.HttpClient.Response).ServerHelloInfo = serverHelloInfo;
                            }

                            await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool, BufferSize,
                                                    (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
                                                    (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
                                                    connectArgs.CancellationTokenSource, ExceptionFunc);
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }

                        return;
                    }
                }

                if (connectArgs != null && await HttpHelper.IsPriMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1)
                {
                    // todo
                    string httpCmd = await clientStream.ReadLineAsync(cancellationToken);

                    if (httpCmd == "PRI * HTTP/2.0")
                    {
                        connectArgs.HttpClient.ConnectRequest.TunnelType = TunnelType.Http2;

                        // HTTP/2 Connection Preface
                        string line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != string.Empty)
                        {
                            throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
                        }

                        line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != "SM")
                        {
                            throw new Exception($"HTTP/2 Protocol violation. 'SM' expected, '{line}' received");
                        }

                        line = await clientStream.ReadLineAsync(cancellationToken);

                        if (line != string.Empty)
                        {
                            throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
                        }

                        var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
                                                                                        isConnect : true, applicationProtocols : SslExtensions.Http2ProtocolAsList,
                                                                                        noCache : true, cancellationToken : cancellationToken);

                        try
                        {
                            await connection.StreamWriter.WriteLineAsync("PRI * HTTP/2.0", cancellationToken);

                            await connection.StreamWriter.WriteLineAsync(cancellationToken);

                            await connection.StreamWriter.WriteLineAsync("SM", cancellationToken);

                            await connection.StreamWriter.WriteLineAsync(cancellationToken);

#if NETCOREAPP2_1
                            await Http2Helper.SendHttp2(clientStream, connection.Stream, BufferSize,
                                                        (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
                                                        (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
                                                        () => new SessionEventArgs(this, endPoint, cancellationTokenSource)
                            {
                                ProxyClient = { Connection = clientConnection },
                                HttpClient  = { ConnectRequest = connectArgs?.HttpClient.ConnectRequest },
                                UserData    = connectArgs?.UserData
                            },
                                                        async args => { await invokeBeforeRequest(args); },
                                                        async args => { await invokeBeforeResponse(args); },
                                                        connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc);
#endif
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }
                    }
                }

                calledRequestHandler = true;
                // Now create the request
                await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
                                               cancellationTokenSource, connectHostname, connectArgs, prefetchConnectionTask);
            }
            catch (ProxyException e)
            {
                closeServerConnection = true;
                onException(clientStream, e);
            }
            catch (IOException e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Connection was aborted", e));
            }
            catch (SocketException e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Could not connect", e));
            }
            catch (Exception e)
            {
                closeServerConnection = true;
                onException(clientStream, new Exception("Error occured in whilst handling the client", e));
            }
            finally
            {
                if (!calledRequestHandler)
                {
                    await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
                }

                sslStream?.Dispose();
                clientStream.Dispose();

                if (!cancellationTokenSource.IsCancellationRequested)
                {
                    cancellationTokenSource.Cancel();
                }
            }
        }
Exemple #24
0
        public void StartProxy()
        {
            proxyServer.BeforeRequest  += onRequest;
            proxyServer.BeforeResponse += onResponse;
            proxyServer.AfterResponse  += onAfterResponse;

            proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
            proxyServer.ClientCertificateSelectionCallback  += OnCertificateSelection;

            //proxyServer.EnableWinAuth = true;

            explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000);

            // Fired when a CONNECT request is received
            explicitEndPoint.BeforeTunnelConnectRequest  += onBeforeTunnelConnectRequest;
            explicitEndPoint.BeforeTunnelConnectResponse += onBeforeTunnelConnectResponse;

            // An explicit endpoint is where the client knows about the existence of a proxy
            // So client sends request in a proxy friendly manner
            proxyServer.AddEndPoint(explicitEndPoint);
            proxyServer.Start();

            // Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
            // A transparent endpoint usually requires a network router port forwarding HTTP(S) packets
            // or by DNS to send data to this endPoint.
            //var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 443, true)
            //{
            //    // Generic Certificate hostname to use
            //    // When SNI is disabled by client
            //    GenericCertificateName = "localhost"
            //};

            //proxyServer.AddEndPoint(transparentEndPoint);
            //proxyServer.UpStreamHttpProxy = new ExternalProxy("localhost", 8888);
            //proxyServer.UpStreamHttpsProxy = new ExternalProxy("localhost", 8888);

            // SOCKS proxy
            //proxyServer.UpStreamHttpProxy = new ExternalProxy("127.0.0.1", 1080)
            //    { ProxyType = ExternalProxyType.Socks5, UserName = "******", Password = "******" };
            //proxyServer.UpStreamHttpsProxy = new ExternalProxy("127.0.0.1", 1080)
            //    { ProxyType = ExternalProxyType.Socks5, UserName = "******", Password = "******" };


            //var socksEndPoint = new SocksProxyEndPoint(IPAddress.Any, 1080, true)
            //{
            //    // Generic Certificate hostname to use
            //    // When SNI is disabled by client
            //    GenericCertificateName = "google.com"
            //};

            //proxyServer.AddEndPoint(socksEndPoint);

            foreach (var endPoint in proxyServer.ProxyEndPoints)
            {
                Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ", endPoint.GetType().Name,
                                  endPoint.IpAddress, endPoint.Port);
            }

            // Only explicit proxies can be set as system proxy!
            //proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
            //proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
            if (RunTime.IsWindows)
            {
                proxyServer.SetAsSystemProxy(explicitEndPoint, ProxyProtocolType.AllHttp);
            }
        }
Exemple #25
0
        //This is called when client is aware of proxy
        //So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
        private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient)
        {
            Stream clientStream = tcpClient.GetStream();

            clientStream.ReadTimeout  = ConnectionTimeOutSeconds * 1000;
            clientStream.WriteTimeout = ConnectionTimeOutSeconds * 1000;

            var clientStreamReader = new CustomBinaryReader(clientStream);
            var clientStreamWriter = new StreamWriter(clientStream)
            {
                NewLine = ProxyConstants.NewLine
            };

            Uri httpRemoteUri;

            try
            {
                //read the first line HTTP command
                var httpCmd = await clientStreamReader.ReadLineAsync();

                if (string.IsNullOrEmpty(httpCmd))
                {
                    Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
                    return;
                }

                //break up the line into three components (method, remote URL & Http Version)
                var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3);

                //Find the request Verb
                var httpVerb = httpCmdSplit[0];

                if (httpVerb.ToUpper() == "CONNECT")
                {
                    httpRemoteUri = new Uri("http://" + httpCmdSplit[1]);
                }
                else
                {
                    httpRemoteUri = new Uri(httpCmdSplit[1]);
                }

                //parse the HTTP version
                Version version = new Version(1, 1);
                if (httpCmdSplit.Length == 3)
                {
                    string httpVersion = httpCmdSplit[2].Trim();

                    if (httpVersion == "http/1.0")
                    {
                        version = new Version(1, 0);
                    }
                }
                //filter out excluded host names
                var excluded = endPoint.ExcludedHttpsHostNameRegex != null?
                               endPoint.ExcludedHttpsHostNameRegex.Any(x => Regex.IsMatch(httpRemoteUri.Host, x)) : false;


                List <HttpHeader> connectRequestHeaders = null;

                //Client wants to create a secure tcp tunnel (its a HTTPS request)
                if (httpVerb.ToUpper() == "CONNECT" && !excluded && httpRemoteUri.Port != 80)
                {
                    httpRemoteUri = new Uri("https://" + httpCmdSplit[1]);
                    string tmpLine = null;
                    connectRequestHeaders = new List <HttpHeader>();
                    while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync()))
                    {
                        var header = tmpLine.Split(ProxyConstants.ColonSplit, 2);

                        var newHeader = new HttpHeader(header[0], header[1]);
                        connectRequestHeaders.Add(newHeader);
                    }

                    if (await CheckAuthorization(clientStreamWriter, connectRequestHeaders) == false)
                    {
                        Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
                        return;
                    }

                    await WriteConnectResponse(clientStreamWriter, version);

                    SslStream sslStream = null;

                    try
                    {
                        sslStream = new SslStream(clientStream, true);
                        var certificate = certificateCacheManager.CreateCertificate(httpRemoteUri.Host, false);
                        //Successfully managed to authenticate the client using the fake certificate
                        await sslStream.AuthenticateAsServerAsync(certificate, false,
                                                                  SupportedSslProtocols, false);

                        //HTTPS server created - we can now decrypt the client's traffic
                        clientStream = sslStream;

                        clientStreamReader = new CustomBinaryReader(sslStream);
                        clientStreamWriter = new StreamWriter(sslStream)
                        {
                            NewLine = ProxyConstants.NewLine
                        };
                    }
                    catch
                    {
                        if (sslStream != null)
                        {
                            sslStream.Dispose();
                        }

                        Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
                        return;
                    }

                    //Now read the actual HTTPS request line
                    httpCmd = await clientStreamReader.ReadLineAsync();
                }
                //Sorry cannot do a HTTPS request decrypt to port 80 at this time
                else if (httpVerb.ToUpper() == "CONNECT")
                {
                    //Cyphen out CONNECT request headers
                    await clientStreamReader.ReadAllLinesAsync();

                    //write back successfull CONNECT response
                    await WriteConnectResponse(clientStreamWriter, version);

                    await TcpHelper.SendRaw(BUFFER_SIZE, ConnectionTimeOutSeconds, httpRemoteUri.Host, httpRemoteUri.Port,
                                            httpCmd, version, null,
                                            false, SupportedSslProtocols,
                                            new RemoteCertificateValidationCallback(ValidateServerCertificate),
                                            new LocalCertificateSelectionCallback(SelectClientCertificate),
                                            clientStream, tcpConnectionFactory, UpStreamEndPoint);

                    Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
                    return;
                }
                //Now create the request
                await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
                                               httpRemoteUri.Scheme == Uri.UriSchemeHttps?httpRemoteUri.Host : null, endPoint, connectRequestHeaders, null, null);
            }
            catch (Exception)
            {
                Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
            }
        }
        //This is called when client is aware of proxy
        private async void HandleClient(ExplicitProxyEndPoint endPoint, TcpClient client)
        {
            Stream clientStream       = client.GetStream();
            var    clientStreamReader = new CustomBinaryReader(clientStream);
            var    clientStreamWriter = new StreamWriter(clientStream);

            Uri httpRemoteUri;

            try
            {
                //read the first line HTTP command
                var httpCmd = await clientStreamReader.ReadLineAsync();

                if (string.IsNullOrEmpty(httpCmd))
                {
                    Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
                    return;
                }

                //break up the line into three components (method, remote URL & Http Version)
                var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3);

                //Find the request Verb
                var httpVerb = httpCmdSplit[0];

                if (httpVerb.ToUpper() == "CONNECT")
                {
                    httpRemoteUri = new Uri("http://" + httpCmdSplit[1]);
                }
                else
                {
                    httpRemoteUri = new Uri(httpCmdSplit[1]);
                }

                //parse the HTTP version
                Version version = new Version(1, 1);
                if (httpCmdSplit.Length == 3)
                {
                    string httpVersion = httpCmdSplit[2].Trim();

                    if (httpVersion == "http/1.0")
                    {
                        version = new Version(1, 0);
                    }
                }
                //filter out excluded host names
                var excluded = endPoint.ExcludedHttpsHostNameRegex != null?
                               endPoint.ExcludedHttpsHostNameRegex.Any(x => Regex.IsMatch(httpRemoteUri.Host, x)) : false;

                //Client wants to create a secure tcp tunnel (its a HTTPS request)
                if (httpVerb.ToUpper() == "CONNECT" && !excluded && httpRemoteUri.Port != 80)
                {
                    httpRemoteUri = new Uri("https://" + httpCmdSplit[1]);
                    await clientStreamReader.ReadAllLinesAsync();

                    await WriteConnectResponse(clientStreamWriter, version);

                    SslStream sslStream = null;

                    try
                    {
                        //create the Tcp Connection to server and then release it to connection cache
                        //Just doing what CONNECT request is asking as to do
                        var tunnelClient = await tcpConnectionCacheManager.GetClient(httpRemoteUri.Host, httpRemoteUri.Port, true, version,
                                                                                     UpStreamHttpProxy, UpStreamHttpsProxy, BUFFER_SIZE, SupportedSslProtocols, new RemoteCertificateValidationCallback(ValidateServerCertificate),
                                                                                     new LocalCertificateSelectionCallback(SelectClientCertificate));

                        await tcpConnectionCacheManager.ReleaseClient(tunnelClient);

                        sslStream = new SslStream(clientStream, true);
                        var certificate = await certificateCacheManager.CreateCertificate(httpRemoteUri.Host, false);

                        //Successfully managed to authenticate the client using the fake certificate
                        await sslStream.AuthenticateAsServerAsync(certificate, false,
                                                                  SupportedSslProtocols, false);

                        //HTTPS server created - we can now decrypt the client's traffic
                        clientStream = sslStream;

                        clientStreamReader = new CustomBinaryReader(sslStream);
                        clientStreamWriter = new StreamWriter(sslStream);
                    }
                    catch
                    {
                        if (sslStream != null)
                        {
                            sslStream.Dispose();
                        }

                        Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
                        return;
                    }

                    //Now read the actual HTTPS request line
                    httpCmd = await clientStreamReader.ReadLineAsync();
                }
                //Sorry cannot do a HTTPS request decrypt to port 80 at this time
                else if (httpVerb.ToUpper() == "CONNECT")
                {
                    //Cyphen out CONNECT request headers
                    await clientStreamReader.ReadAllLinesAsync();

                    //write back successfull CONNECT response
                    await WriteConnectResponse(clientStreamWriter, version);

                    //Just relay the request/response without decrypting it
                    await TcpHelper.SendRaw(clientStream, null, null, httpRemoteUri.Host, httpRemoteUri.Port,
                                            false, SupportedSslProtocols);

                    Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
                    return;
                }

                //Now create the request
                await HandleHttpSessionRequest(client, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
                                               httpRemoteUri.Scheme == Uri.UriSchemeHttps?true : false);
            }
            catch
            {
                Dispose(client, clientStream, clientStreamReader, clientStreamWriter, null);
            }
        }
Exemple #27
0
        protected override void OnStart(string[] args)
        {
            // we do all this in here so we can reload settings with a simple restart

            _proxyServerInstance = new ProxyServer(false);

            if (Properties.Settings.Default.ListeningPort <= 0 ||
                Properties.Settings.Default.ListeningPort > 65535)
            {
                throw new Exception("Invalid listening port");
            }

            _proxyServerInstance.CheckCertificateRevocation        = Properties.Settings.Default.CheckCertificateRevocation;
            _proxyServerInstance.ConnectionTimeOutSeconds          = Properties.Settings.Default.ConnectionTimeOutSeconds;
            _proxyServerInstance.Enable100ContinueBehaviour        = Properties.Settings.Default.Enable100ContinueBehaviour;
            _proxyServerInstance.EnableConnectionPool              = Properties.Settings.Default.EnableConnectionPool;
            _proxyServerInstance.EnableTcpServerConnectionPrefetch = Properties.Settings.Default.EnableTcpServerConnectionPrefetch;
            _proxyServerInstance.EnableWinAuth            = Properties.Settings.Default.EnableWinAuth;
            _proxyServerInstance.ForwardToUpstreamGateway = Properties.Settings.Default.ForwardToUpstreamGateway;
            _proxyServerInstance.MaxCachedConnections     = Properties.Settings.Default.MaxCachedConnections;
            _proxyServerInstance.ReuseSocket        = Properties.Settings.Default.ReuseSocket;
            _proxyServerInstance.TcpTimeWaitSeconds = Properties.Settings.Default.TcpTimeWaitSeconds;
            _proxyServerInstance.CertificateManager.SaveFakeCertificates = Properties.Settings.Default.SaveFakeCertificates;
            _proxyServerInstance.EnableHttp2 = Properties.Settings.Default.EnableHttp2;
            _proxyServerInstance.NoDelay     = Properties.Settings.Default.NoDelay;

            if (Properties.Settings.Default.ThreadPoolWorkerThreads < 0)
            {
                _proxyServerInstance.ThreadPoolWorkerThread = Environment.ProcessorCount;
            }
            else
            {
                _proxyServerInstance.ThreadPoolWorkerThread = Properties.Settings.Default.ThreadPoolWorkerThreads;
            }

            if (Properties.Settings.Default.ThreadPoolWorkerThreads < Environment.ProcessorCount)
            {
                ProxyServiceEventLog.WriteEntry(
                    $"Worker thread count of {Properties.Settings.Default.ThreadPoolWorkerThreads} is below the " +
                    $"processor count of {Environment.ProcessorCount}. This may be on purpose.", System.Diagnostics.EventLogEntryType.Warning);
            }

            var explicitEndPointV4 = new ExplicitProxyEndPoint(IPAddress.Any, Properties.Settings.Default.ListeningPort, Properties.Settings.Default.DecryptSsl);

            _proxyServerInstance.AddEndPoint(explicitEndPointV4);

            if (Properties.Settings.Default.EnableIpV6)
            {
                var explicitEndPointV6 = new ExplicitProxyEndPoint(IPAddress.IPv6Any, Properties.Settings.Default.ListeningPort, Properties.Settings.Default.DecryptSsl);

                _proxyServerInstance.AddEndPoint(explicitEndPointV6);
            }

            if (Properties.Settings.Default.LogErrors)
            {
                _proxyServerInstance.ExceptionFunc = ProxyException;
            }

            _proxyServerInstance.Start();

            ProxyServiceEventLog.WriteEntry($"Service Listening on port {Properties.Settings.Default.ListeningPort}", System.Diagnostics.EventLogEntryType.Information);
        }
Exemple #28
0
        /// <summary>
        /// Set the given explicit end point as the default proxy server for current machine
        /// </summary>
        /// <param name="endPoint"></param>
        /// <param name="protocolType"></param>
        public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType)
        {
            if (RunTime.IsRunningOnMono)
            {
                throw new Exception("Mono Runtime do not support system proxy settings.");
            }

            ValidateEndPointAsSystemProxy(endPoint);

            bool isHttp  = (protocolType & ProxyProtocolType.Http) > 0;
            bool isHttps = (protocolType & ProxyProtocolType.Https) > 0;

            if (isHttps)
            {
                if (!endPoint.EnableSsl)
                {
                    throw new Exception("Endpoint do not support Https connections");
                }

                EnsureRootCertificate();

                //If certificate was trusted by the machine
                if (!CertificateManager.CertValidated)
                {
                    protocolType = protocolType & ~ProxyProtocolType.Https;
                    isHttps      = false;
                }
            }

            //clear any settings previously added
            if (isHttp)
            {
                ProxyEndPoints.OfType <ExplicitProxyEndPoint>().ToList().ForEach(x => x.IsSystemHttpProxy = false);
            }

            if (isHttps)
            {
                ProxyEndPoints.OfType <ExplicitProxyEndPoint>().ToList().ForEach(x => x.IsSystemHttpsProxy = false);
            }

            systemProxySettingsManager.SetProxy(
                Equals(endPoint.IpAddress, IPAddress.Any) |
                Equals(endPoint.IpAddress, IPAddress.Loopback)
                    ? "127.0.0.1"
                    : endPoint.IpAddress.ToString(),
                endPoint.Port,
                protocolType);

            if (isHttp)
            {
                endPoint.IsSystemHttpsProxy = true;
            }

            if (isHttps)
            {
                endPoint.IsSystemHttpsProxy = true;
            }

            firefoxProxySettingsManager.UseSystemProxy();

            string proxyType = null;

            switch (protocolType)
            {
            case ProxyProtocolType.Http:
                proxyType = "HTTP";
                break;

            case ProxyProtocolType.Https:
                proxyType = "HTTPS";
                break;

            case ProxyProtocolType.AllHttp:
                proxyType = "HTTP and HTTPS";
                break;
            }

            if (protocolType != ProxyProtocolType.None)
            {
                Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System {2} Proxy", endPoint.IpAddress, endPoint.Port, proxyType);
            }
        }
Exemple #29
0
 /// <summary>
 /// Set the given explicit end point as the default proxy server for current machine
 /// </summary>
 /// <param name="endPoint"></param>
 public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint)
 {
     SetAsSystemProxy(endPoint, ProxyProtocolType.Https);
 }
        public MainWindow()
        {
            proxyServer = new ProxyServer();

            //proxyServer.EnableHttp2 = true;

            //proxyServer.CertificateManager.CertificateEngine = CertificateEngine.DefaultWindows;

            ////Set a password for the .pfx file
            //proxyServer.CertificateManager.PfxPassword = "******";

            ////Set Name(path) of the Root certificate file
            //proxyServer.CertificateManager.PfxFilePath = @"C:\NameFolder\rootCert.pfx";

            ////do you want Replace an existing Root certificate file(.pfx) if password is incorrect(RootCertificate=null)?  yes====>true
            //proxyServer.CertificateManager.OverwritePfxFile = true;

            ////save all fake certificates in folder "crts"(will be created in proxy dll directory)
            ////if create new Root certificate file(.pfx) ====> delete folder "crts"
            //proxyServer.CertificateManager.SaveFakeCertificates = true;

            proxyServer.ForwardToUpstreamGateway = true;

            //increase the ThreadPool (for server prod)
            //proxyServer.ThreadPoolWorkerThread = Environment.ProcessorCount * 6;

            ////if you need Load or Create Certificate now. ////// "true" if you need Enable===> Trust the RootCertificate used by this proxy server
            //proxyServer.CertificateManager.EnsureRootCertificate(true);

            ////or load directly certificate(As Administrator if need this)
            ////and At the same time chose path and password
            ////if password is incorrect and (overwriteRootCert=true)(RootCertificate=null) ====> replace an existing .pfx file
            ////note : load now (if existed)
            //proxyServer.CertificateManager.LoadRootCertificate(@"C:\NameFolder\rootCert.pfx", "PfxPassword");

            var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true);

            proxyServer.AddEndPoint(explicitEndPoint);
            //proxyServer.UpStreamHttpProxy = new ExternalProxy
            //{
            //    HostName = "158.69.115.45",
            //    Port = 3128,
            //    UserName = "******",
            //    Password = "******",
            //};

            proxyServer.BeforeRequest  += ProxyServer_BeforeRequest;
            proxyServer.BeforeResponse += ProxyServer_BeforeResponse;
            proxyServer.AfterResponse  += ProxyServer_AfterResponse;
            explicitEndPoint.BeforeTunnelConnectRequest  += ProxyServer_BeforeTunnelConnectRequest;
            explicitEndPoint.BeforeTunnelConnectResponse += ProxyServer_BeforeTunnelConnectResponse;
            proxyServer.ClientConnectionCountChanged     += delegate
            {
                Dispatcher.Invoke(() => { ClientConnectionCount = proxyServer.ClientConnectionCount; });
            };
            proxyServer.ServerConnectionCountChanged += delegate
            {
                Dispatcher.Invoke(() => { ServerConnectionCount = proxyServer.ServerConnectionCount; });
            };
            proxyServer.Start();

            proxyServer.SetAsSystemProxy(explicitEndPoint, ProxyProtocolType.AllHttp);

            InitializeComponent();
        }