3

I want to use nginx as a load balancer in front of several node.js application nodes.

round-robin and ip_hash methods are unbelievably easy to implement but in my use case, they're not the best fit.

I need nginx to serve clients to backend nodes in respect to their session id's which are given by first-landed node.

During my googlings, I've come up with "hash"ing method but I couldn't find too many resources around.

Here is what I tried:

my_site.conf:

http {

    upstream my_servers {
        hash $remote_addr$http_session_id consistent;
        server 127.0.0.1:3000;
        server 127.0.0.1:3001;
        server 127.0.0.1:3002;
    }

    server {
        listen 1234;
        server_name example.com;

        location / {
            proxy_pass http://my_servers;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_redirect off;
            proxy_buffering off;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

And at the application, I return Session-ID header with the session id.

res.setHeader('Session-ID', req.sessionID);

I'm missing something, but what?

2
  • $http_session_id refers to header sent by client (browser), not your application response. And what you need is nginx.org/r/sticky, but it's in commercial subscription only. Why you don't want simple ip_hash? Commented Apr 28, 2015 at 5:58
  • Yeah, after asking the question I've found 'sticky' module... But as you said it's commercial :( Because I need to count different clients eventhough they're from the same IP... By the way, please add your comment as an answer and I'm gonna accept it. Commented Apr 28, 2015 at 7:14

2 Answers 2

3

$http_session_id refers to header sent by client (browser), not your application response. And what you need is http://nginx.org/r/sticky, but it's in commercial subscription only.

There is third-party module that will do the same as commercial one, but you'll have to recompile nginx.

Sign up to request clarification or add additional context in comments.

Comments

0

It doesn't work out of the box because nginx is a (good) webserver, but not a real load-balancer. Prefer haproxy for load-balancing.

Furthermore, what you need is not hashing. You need persistence on a session-id header and you need to be able to persist on source IP until you get this header. This is pretty straight forward with HAProxy. HAProxy can also be used to check if the session id has been generated by the server or if it has been forged by the client.

backend myapp
 # create a stick table in memory
 # (note: use peers to synchronize the content of the table)
 stick-table type string len 32 expire 1h size 1m
 # match client http-session-id in the table to do the persistence
 stick match hdr(http-session-id)
 # if not found, then use the source IP address
 stick on src,lower  # dirty trick to turn the IP address into a string

 # learn the http-session-id that has been generated by the server
 stick store-response hdr(http-session-id)

 # add a header if the http-session-id seems to be forged (not found in the table)
 # (note: only available in 1.6-dev)
 acl has-session-id req.hdr(http-session-id) -m found
 acl unknown-session-id req.hdr(http-session-id),in_table(myapp)
 http-request set-header X-warning unknown\ session-id if has-session-id unknown-session-id

Then you are fully secured :)

Baptiste

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.