daguej / node-proxywrap

Wrap node's Server interfaces to be compatible with the PROXY protocol
48 stars 36 forks source link

Cannot connect behind ELB #6

Closed gordyr closed 10 years ago

gordyr commented 10 years ago

Hi,

I'm having some real troubles getting this set up.

I need to run a cluster of node.js instances, all running primus (https://github.com/primus/primus) with the sock.js transport from behind an ELB.

My ELP listeners are configures like so:

TCP 80 -> TCP 80 HTTPS 8084 -> HTTPS 8084

8084 is the port that the node.js/Primus servers use. When a client connects a simple GET request is sent to the node js server, I intercept it and enable CORS since it is on a different domain to my app then finally Primus/Sock.js should upgrade the connection to a websocket through port 80.

I have correctly enabled the proxy protocol for both ports 8084 and 80 and of course have installed proxywrap.

Now everything works perfectly when I set the primus connection address to a single server and disable proxywrap. But as soon as I turn proxywrap back on and try to send connect to the loadbalancer, it fails.

I'm relatively inexperienced with this kind of stuff and feel at a complete loss.

Any help or advice you could give me would be greatly appreciated.

Here is my node.js/Primus code:

var Primus = require('primus');
var https = require('https');
var proxiedHttps = require('proxywrap').proxy(https);
var fs = require('fs');

var options = {
        key: fs.readFileSync('/key.key'),
        cert: fs.readFileSync('/cert.crt'),
        ca: fs.readFileSync('/csa.csa'),
        requestCert: true,
        rejectUnauthorized: false
};

//Create server and allow cross domain
var server = proxiedHttps.createServer(options, function(request, response){    
        var origin = (request.headers.origin || "*");
        if (request.method.toUpperCase() === "OPTIONS"){
            response.writeHead("204", "No Content", {
                            "access-control-allow-origin": origin,
                            "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS",
                            "access-control-allow-headers": "content-type, accept",
                            "access-control-max-age": 10, // Seconds.
                            "content-length": 0
            });

            return( response.end() );
        }

        var requestBodyBuffer = [];
        request.on("data", function( chunk ){
                requestBodyBuffer.push( chunk );
        });     
        request.on("end", function(){
                var requestBody = requestBodyBuffer.join( "" );
                var responseBody = (
                    "Thank You For The Cross-Domain AJAX Request:\n\n" +
                    "Method: " + request.method + "\n\n" +
                    requestBody
                );
                response.writeHead("200", "OK", {
                                    "access-control-allow-origin": origin,
                                    "content-type": "text/plain",
                                    "content-length": responseBody.length
                });

                return( response.end( responseBody ) );
            }
        );
});
daguej commented 10 years ago

Your ELB should use TCP for port 8084 as well. In HTTPS mode, the ELB actually decrypts traffic and fiddles with the application-later protocol (HTTP in this case), which we don't want.

gordyr commented 10 years ago

Thanks.. I've just tried as you suggested and used require('net') instead of require('https') (which I assume is correct) but the problem still remains.

daguej commented 10 years ago

You should still use the https module in node, but the ELB needs to be set to TCP mode instead of HTTPS.