spdy-http2 / node-spdy

SPDY server on Node.js
2.81k stars 196 forks source link

Add a reverse proxy "hijacking" feature. #179

Closed jeffreydwalter closed 7 years ago

jeffreydwalter commented 9 years ago

In go, there's a function called hijack that basically "steals" a tls socket to tunnel from an existing connection. There's a spdy library for go (https://github.com/SlyMarbo/spdy/blob/master/proxy.go) which uses this feature to "hijack" an existing tls connection, which it then creates a reverse spdy proxy through.

I've been able to emulate this feature in a spdy client/server that I wrote, but I'm wondering if there's a more correct way to do this with node-spdy, or if not, can we make the feature part of the node-spdy library, because it's VERY useful.

I'm basically doing something like this in my node spdy server code:

// Setup tls server. var server = tls.createServer(options); var hijacked_agent = null;

server.on('secureConnection', function(cleartextStream) { var Self = this;

cleartextStream.on('data', function(data) {
    // The client is supposed to send a CONNECT immediately after the tls connection is established.
    // If we get that, then return a 200, which causes the client to "convert" into a SPDY server. 
    // We then convert to a SPDY proxy server.
    if(data.toString().match(/^CONNECT \/ HTTP\/1.1\r\n/)) {
        cleartextStream.write("HTTP/1.0 200\n\nOK\n\r\n\r", function() {
            function HijackedAgent(options)
            {
                GLOBAL.http.Agent.call(this, options);
                this.options = options;

                // Replace the default node-spdy createConnection() function with one that returns our current tls socket.
                this.createConnection = function createConnection(options)
                {
                    function read() {
                        var b = cleartextStream.read();
                        if(b === null) {
                            cleartextStream.once('readable', read);
                        }
                    }

                    if(cleartextStream.read) {
                        read();
                    }

                    return cleartextStream;
                };
            }

            GLOBAL.util.inherits(HijackedAgent, require('http').Agent);

            hijacked_agent = require('spdy').createAgent(HijackedAgent, options))
            .on('error', Self.HandleAgentDisconnect.bind(Self))
                .on('close', Self.HandleAgentDisconnect.bind(Self));

        });
    }
});

});

... later in the code

// We "inject" our tls cleartextStream we established earlier by passing our hijacked_agent as an http.agent. var request = GLOBAL.http.get({ path: '/some/resource', agent: hijacked_agent, });

request.on('response', function(response) { ... do the usual ... response.on('data', function(chunk) { response_body += chunk; });

    response.on('end', function GetKuid() {
        ...
});

}); ...

euprogramador commented 8 years ago

http2 reverse proxy ?