Skip to content
This repository has been archived by the owner on Jul 9, 2023. It is now read-only.

Setting e.DecryptSsl=false in OnBeforeSslAuthenticate gives "Could not establish connection" Exception. #868

Closed
testuser546 opened this issue Jun 10, 2021 · 6 comments
Labels

Comments

@testuser546
Copy link

I want to bypass some sites over my proxy. for that i was using an iptable rule as sudo iptables -t nat -I OUTPUT -d "+url+" -j ACCEPT it only work with full url patter like www.facebook.com but there are some Url which are not constat. like they are frequently changing w2dc23uj2355.app.syn.asana.com.---etc here starting part of url always changing. so i did another way by not decrypting site. here i took google.com and zoom.com as example.

 private async Task OnBeforeSslAuthenticate(object sender, BeforeSslAuthenticateEventArgs e)
       {
            try
            {
                string hostname = e.SniHostName;
                //Console.WriteLine("******* "+hostname);
                Console.WriteLine("OnBeforeSslAuthenticate : " + e.SniHostName);

                if (hostname.Contains("zoom.com")|| hostname.Contains("zoom.us") || hostname.Contains("google.com"))
                {
                    e.DecryptSsl = false;
                    Console.WriteLine("OnBeforeSslAuthenticate:: DecryptSsl() : " + e.DecryptSsl);
                }                            
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        } 

when I Set this, i get an exception in TransperentClienHandler.cs => handleClient().
here is a whole method.

            int port, CancellationTokenSource cancellationTokenSource, CancellationToken cancellationToken)
        {
            bool isHttps = false;
            var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken);

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

                if (clientHelloInfo != null)
                {
                    var httpsHostName = clientHelloInfo.GetServerName() ?? endPoint.GenericCertificateName;

                    var args = new BeforeSslAuthenticateEventArgs(clientConnection, cancellationTokenSource, httpsHostName);

                    await endPoint.InvokeBeforeSslAuthenticate(this, args, ExceptionFunc);

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


                    if (endPoint.DecryptSsl && args.DecryptSsl)
                    {
                        Console.WriteLine("Decrypting traffic for url " + httpsHostName);
                        clientStream.Connection.SslProtocol = clientHelloInfo.SslProtocol;

                        // do client authentication using certificate
                        X509Certificate2? certificate = null;
                        SslStream? sslStream = null;
                        try
                        {
                            sslStream = new SslStream(clientStream, false);

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

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

                            // 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
                            isHttps = true;
                        }
                        catch (Exception e)
                        {
                            sslStream?.Dispose();

                            var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
                            var session = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
                            throw new ProxyConnectException(
                                $"Couldn't authenticate host '{httpsHostName}' with certificate '{certName}'.", e, session);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Direct traffic for url " + httpsHostName);

                        var sessionArgs = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
                        var connection = await tcpConnectionFactory.GetServerConnection(this, httpsHostName, port,
                                    HttpHeader.Version11, false, null,
                                    true, sessionArgs, UpStreamEndPoint,
                                    UpStreamHttpsProxy, true, cancellationToken);



                        try
                        {
                            int available = clientStream.Available;

                            Console.WriteLine("Direct traffic for url " + httpsHostName + " available" + 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
                                    await clientStream.ReadAsync(data, 0, available, cancellationToken);
                                    await connection.Stream.WriteAsync(data, 0, available, true, cancellationToken);
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine("Inner catch" + ex.Message);
                                }
                                finally
                                {
                                    BufferPool.ReturnBuffer(data);
                                }
                            }

                            if (!clientStream.IsClosed && !connection.Stream.IsClosed)
                            {
                                await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool,
                                    null, null, cancellationTokenSource, ExceptionFunc);
                            }
                        }
                        catch(Exception ex)
                        {
                            Console.WriteLine("Outer catch" + ex.Message);
                        }
                        finally
                        {
                            await tcpConnectionFactory.Release(connection, true);
                        }

                        return;
                    }
                }

                // HTTPS server created - we can now decrypt the client's traffic
                // Now create the request
                await handleHttpSessionRequest(endPoint, clientStream, cancellationTokenSource, isHttps: isHttps);
            }
            catch (ProxyException e)
            {
                Console.WriteLine("Outer catch ProxyException" + e.Message);
                onException(clientStream, e);
            }
            catch (IOException e)
            {
                Console.WriteLine("Outer catch IOException" + e.Message);
                onException(clientStream, new Exception("Connection was aborted", e));
            }
            catch (SocketException e)
            {
                Console.WriteLine("Outer catch SocketException" + e.Message);
                onException(clientStream, new Exception("Could not connect", e));
            }
            catch (Exception e)
            {
                Console.WriteLine("Outer catch Exception" + e.Message);
                Console.WriteLine("Outer catch Exception" + e);
                onException(clientStream, new Exception("Error occured in whilst handling the client", e));
            }
            finally
            {
                clientStream.Dispose();
            }
        } 

And This is a Full stack trace message I'm getting.

 Outer catch ExceptionCould not establish connection to clients2.google.com
 Outer catch ExceptionSystem.Exception: Could not establish connection to clients2.google.com ---> System.Net.Sockets.SocketException: Network is unreachable
    at System.Net.Sockets.Socket.BeginConnectEx(EndPoint remoteEP, Boolean flowContext, AsyncCallback callback, Object state)
    at System.Net.Sockets.Socket.UnsafeBeginConnect(EndPoint remoteEP, AsyncCallback callback, Objecstate, Boolean flowContext)
    at System.Net.Sockets.Socket.BeginConnect(EndPoint remoteEP, AsyncCallback callback, Object state)
    at System.Net.Sockets.Socket.BeginConnect(IPAddress address, Int32 port, AsyncCallback requestCallback, Object state)
    at Titanium.Web.Proxy.Network.Tcp.TcpConnectionFactory.SocketConnectionTaskFactory.beginConnect(IPAddress address, Int32 port, AsyncCallback requestCallback, Object state)
    at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl[TArg1,TArg2](Func`5 beginMethod, Func`2 endFunction, Action`1 endAction, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
    at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func`5 beginMethod, Action`1 endMethod, TArg1 arg1, TArg2 arg2, Object state)
    at Titanium.Web.Proxy.Network.Tcp.TcpConnectionFactory.SocketConnectionTaskFactory.CreateTask(Socket socket, IPAddress ipAddress, Int32 port)
    at Titanium.Web.Proxy.Network.Tcp.TcpConnectionFactory.createServerConnection(String remoteHostName, Int32 remotePort, Version httpVersion, Boolean isHttps, SslProtocols sslProtocol, List`1 applicationProtocols, Boolean isConnect, ProxyServer proxyServer, SessionEventArgsBase sessionArgs, IPEndPoint upStreamEndPoint, IExternalProxy externalProxy, String cacheKey, CancellationTo
    --- End of inner exception stack trace ---
    at Titanium.Web.Proxy.Network.Tcp.TcpConnectionFactory.createServerConnection(String remoteHostName, Int32 remotePort, Version httpVersion, Boolean isHttps, SslProtocols sslProtocol, List`1 applicationProtocols, Boolean isConnect, ProxyServer proxyServer, SessionEventArgsBase sessionArgs, IPEndPoint upStreamEndPoint, IExternalProxy externalProxy, String cacheKey, CancellationTo
    at Titanium.Web.Proxy.Network.Tcp.TcpConnectionFactory.GetServerConnection(ProxyServer proxyServer, String remoteHostName, Int32 remotePort, Version httpVersion, Boolean isHttps, List`1 applicationProtocols, Boolean isConnect, SessionEventArgsBase sessionArgs, IPEndPoint upStreamEndPoint, IExternalProxy externalProxy, Boolean noCache, CancellationToken cancellationToken)
    at Titanium.Web.Proxy.ProxyServer.handleClient(TransparentBaseProxyEndPoint endPoint, TcpClientConnection clientConnection, Int32 port, CancellationTokenSource cancellationTokenSource, CancellationToken cancellationToken)
 OnBeforeSslAuthenticate : clients2.google.com ```

@PinnacleCoders
Copy link

@honfika @justcoding121 i am facing the same issue. Can you please help?

The proxy application when run in transparent mode, gives issues to all the sites which has DecryptSsl=false.

@PinnacleCoders
Copy link

PinnacleCoders commented Jun 15, 2021

@honfika @justcoding121 I tried using the latest dll from nuget but still no success.

@justcoding121
Copy link
Owner

Sorry. I am busy with secular work. Do you know from which release this started to happen? Looks like some issue with tcp connection factory.

@PinnacleCoders
Copy link

PinnacleCoders commented Jun 15, 2021 via email

@justcoding121
Copy link
Owner

Created fix in beta. Reopen if still not working.

@PinnacleCoders
Copy link

PinnacleCoders commented Jun 17, 2021 via email

rmbadmin pushed a commit to BeyondDimension/Titanium-Web-Proxy that referenced this issue Jul 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants