Skip to content

Zombie client connections with SSL proxy server? #276

@maxcellent

Description

@maxcellent

LittleProxy version: 1.1.0-beta1

Hi,

We are running a SSL proxy and tracking client connection with ActivityTracker. Here are some observations. I believe not all of them are relevant, but I am no expert to proxy technology so trying to provide as much information as I can.

  1. ActivityTracker#clientConnected is invoked before ActivityTracker#clientSSLHandshakeSucceeded, which makes sense because we need a TCP connection established before SSL handshake.
  2. some times there are exact 10 seconds between ActivityTracker#clientConnected and ActivityTracker#clientDisconnected without any activities: nothing received from client, nothing received from server. I don't understand what's happened, maybe it's just ssl handshake failed? Why it will fail at all?
  3. some times none of ActivityTracker#clientSSLHandshakeSucceeded and ActivityTracker#clientDisconnected are invoked after ActivityTracker#clientConnected is invoked (note our server is SSL only). In that case, server keeps sending back 504 Gateway Timeout which doesn't make sense to me at all. What do you expect client to action on a plain HTTP response in a SSL connection? As a result, all these responses are simply dropped by client side. However, because server side is sending this every 70 seconds (the default idle connection timeout). The connection is actually never closed.
  4. checking the code, in ClientToProxyConnection#timedOut
        boolean clientReadMoreRecentlyThanServer =
                currentServerConnection == null
                        || this.lastReadTime > currentServerConnection.lastReadTime;
        if (clientReadMoreRecentlyThanServer) {
            LOG.debug("Server timed out: {}", currentServerConnection);
            currentFilters.serverToProxyResponseTimedOut();
            writeGatewayTimeout(currentRequest);
            // DO NOT call super.timedOut() if the server timed out, to avoid closing the connection unnecessarily
        } else {
            super.timedOut();
        }

because nothing has been sent / received from server (ssl handshake is not performed), currentServerConnection.lastReadTime is always 0, which means clientReadMoreRecentlyThanServer is always true, which then explains 3. Shall we change this to something like this?

        boolean isConnected = isTCPConnected && (isSSL ? isSSLConnected : true );
        boolean clientReadMoreRecentlyThanServer =
                currentServerConnection == null
                        || this.lastReadTime > currentServerConnection.lastReadTime;
        if (clientReadMoreRecentlyThanServer && isConnected) {
            LOG.debug("Server timed out: {}", currentServerConnection);
            currentFilters.serverToProxyResponseTimedOut();
            writeGatewayTimeout(currentRequest);
            // DO NOT call super.timedOut() if the server timed out, to avoid closing the connection unnecessarily
        } else {
            super.timedOut();
        }

I am happy to test and submit a patch. But would like to confirm if this is the desired behaviour first.

Thanks,

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions