We proxy cookies on Nginx using the lua-nginx module



    I already wrote about how to use Nginx to transform content on the fly . Since the publication of the article on the basis of the described method, a real ecommerce project has been launched and is developing. In addition to translation and transformation, SEO rewriting on the covenants of a beginner's guide from Google is also implemented .

    However, until the product of Russian programmers completely won over foreign content, one small but very important thing was missing - proxying Cookies .

    What is the essence of the problem


    The problem is that any normal application server always sets a cookie, for example, in order to save a client session or a basket with its goods. If this server (or rather its administrator) is concerned with maintaining a certain level of security, then it sets the domain and path in the cookie body, for example domain = backend.org; path = / path1 . Our Nginx launched in Reverse Proxy mode changes all links in the document body from backend.org to frontend.org , but it doesn’t do this for cookies! This means that the client’s browser will reject these cookies.

    This question has long worried the minds of nginx administrators; in newsletters, it pops up 1-2 times a year. Most of the questioners, apparently, solved their problems by twisting the logic of the backend , but not me! After the next update of the original site, it became clear that it was no longer possible to pull the crutch with PHP + Curl and you must certainly find a solution using Nginx!

    I returned the topic to the mailing list, simultaneously sorting through the options from ngx_http_perl_module and the variable $ upstream_http_set_cookie , I even looked into the wilds of sorts with the ghostly hope of writing a module myself. But everything was unsuccessful until at one fine moment I received a letter from Mikhail Mazurskywho gave valuable advice. Thanks to this advice, I not only easily solved the problem of cookie proxying, but also got a new tool with which I can create version 2.0 of my project.

    Decision


    The name of this tool is lua-nginx-module , which is written by another Chinese nugget with roots from Taobao . From the name it’s easy to understand that we are talking about the Lua scripting language built into Nginx - but this is more than just an interpreter! These guys created a completely non-blocking implementation with a performance of tens of thousands of operations per second, which has hooks to all events inside Nginx. What previously could only be implemented by writing your module in C can now be done with a few lines in Lua. Interested in?


    Installation


    To get started, download the latest version of Nginx you yourself know where . Suddenly, who forgot?

    Then we download the latest version of lua-nginx-module from the project page .

    Will

    apt-get install libpcre3 libpcre3-dev libperl-dev lua5.1 liblua5.1-dev

    need libraries: How to build Nginx should already know by heart, looking at the speed of release of new releases. I will give a config from my cookbook:

    ./configure --with-cc-opt="-I /usr/include" --with-ld-opt="-L /usr/lib" --with-http_sub_module --with-http_ssl_module --prefix=/home/nginx/data --user=nginx --group=nginx --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/ --add-module=../substitutions4nginx/ --add-module=../chaoslawful-lua-nginx-module-*


    Configuration


    After make install, do not forget to restart nginx. And look what happened? But it turned out such a great thing: http://wiki.nginx.org/HttpLuaModule , which, according to its creators, draws 25,000 requests per second on an average desktop PC. After carefully studying the documentation, it becomes clear that all events and internal Nginx handlers are available in the Lua runtime. Specifically for our task, we will use the header_filter_by_lua directive . Open the configuration file, select the desired location and add a simple code:

    header_filter_by_lua '
            local headers = ngx.header["Set-Cookie"]
            if headers then
                if type(headers) == "string" then
                    headers = {headers}
                end
                for i, header in ipairs(headers) do
                    local cookie = ngx.re.match(header, "JSESSIONID=([^;]+);", "io")
                    if cookie then
                        headers[i] = "JSESSIONID=" .. cookie[1] .. "; domain=.frontend.com; path=/newpath;"
                    end
                end
                ngx.header["Set-Cookie"] = headers
            end
    ';
    


    Here is the simplest version of the handler - the first lua code I saw in my life. You can and should write a universal Set-Cookie header parser, the country is already waiting for its hero in the comments!

    What's next?


    When the problem is solved, and even in such a simple way, you immediately want to set a new goal. What ideas did I have about using a new tool?

    1. Hit counter The counter inside the web server itself will be spared a lot of program code due to direct access to the necessary variables. If we connect a NoSQL system such as Redis directly to Nginx, then we will get rid of a bunch of SQL code. It will be a completely inconspicuous and damn fast counter!
    2. Anti-DDoS. Using the language in which the AI ​​of most modern games is written, it is easy to make an intelligent filter of unwanted requests to the web server.
    3. Automatic SEO rewrite generator. Instead of manually setting the rules and adding meta tags, we write a script that generates meta tags on the fly, for example, as in the module for livestreet .
    4. And, of course, translation-2.0, with elements for recognizing html blocks and selective filtering of content.


    And what did you come up with, dear habrayuzer?

    PS A boring post, no pictures at all. As an announcement, I’ll add a picture of how SEO rewrite with the help of Nginx changed its position in Google search. Need an article about this?


    Also popular now: