Pull to refresh

Проксируем Cookies на Nginx при помощи модуля lua-nginx

Reading time 4 min
Views 30K


Я уже писал о том, как с помощью Nginx трансформировать контент на лету. С момента публикации статьи на базе описанного метода запущен и развивается реальный проект ecommerce. Помимо перевода и трансформации также реализован и SEO рерайт по заветам руководства для начинающих от Google.

Однако, до полной победы изделия русских программистов над заграничным контентом, не хватало одной небольшой, но очень важной вещи — проксирования Cookies.

В чем суть проблемы


Проблема заключается в том, что любой нормальный сервер приложений всегда выставляет Cookie, например для того, чтобы сохранять сессию клиента или корзину с его товаром. Если этот сервер (точнее его администратор) озабочен поддержанием определенного уровня безопасности, то он выставляет в теле Cookie домен и путь, например domain= backend.org; path=/path1. Наш Nginx запущенный в режиме Reverse Proxy замечательно меняет все ссылки в теле документов с backend.org на frontend.org, но не делает этого для кук! Это означает что браузер клиента отвергнет такие куки.

Этот вопрос с давних пор волнует умы администраторов nginx, в рассылках он всплывает по 1-2 раза в год. Большинство вопрошавших, по-видимому, решили свои проблемы подкручивая логику backendа, но не я! После очередного апдейта оригинального сайта стало понятно, что костыль с PHP + Curl тянуть больше невозможно и надо непременно найти решение с помощью Nginx!

Я вернул тему в рассылку, попутно перебирая варианты из ngx_http_perl_module и переменной $upstream_http_set_cookie, даже заглянул в дебри сорсов с призрачной надеждой написать модуль самому. Но все было неудачно пока в один прекрасный момент я не получил письмо от Mikhail Mazursky, который дал ценный совет. Благодаря этому совету я не только с легкостью решил задачу проксирования Cookie, но и получил новый инструмент, с помощью которого можно создать версию 2.0 своего проекта.

Решение


Название этого инструмента lua-nginx-module, который написан еще одним китайским самородком с корнями из Taobao. Из названия легко понять, что речь об языке скриптов Lua встроенном в Nginx — но это больше чем просто интерпретатор! Эти ребята создали полностью неблокируемую реализацию с производительностью десятки тысяч операций в секунду, которая имеет хуки ко всем событиям внутри Nginx. То что раньше можно было реализовать только написав свой модуль на C, теперь можно сделать несколькими строчками на Lua. Заинтересовались?


Установка


Для начала качаем свежую версию Nginx cами знаете откуда. Вдруг кто забыл?

Затем качаем свежую версию lua-nginx-module со страницы проекта.

Потребуются библиотеки:

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

Как собирать Nginx должны бы уже знать наизусть, глядя на скорость выпуска новые релизы. Приведу конфиг из моего кукбука:

./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-*


Конфигурация


После make install не забываем перезапустить nginx. И смотрим что же получилось? А получилась вот такая великолепная штука: http://wiki.nginx.org/HttpLuaModule, которая по уверению его создателей на среднем настольном ПК тянет 25 тысяч запросов в секунду. Внимательно изучив документацию становится понятно, что в среде исполнения Lua доступны все события и внутренние обработчики Nginx. Конкретно для нашей задачи мы будем использовать директиву header_filter_by_lua . Открываем конфигурационный файл, выбираем нужный location и добавляем простой код:

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
';


Тут приведен самый простой вариант обработчика — первый код на lua который я увидел в своей жизни. Можно и нужно написать универсальный парсер хедеров Set-Cookie, страна уже ждет своего героя в комментариях!

Что дальше?


Когда задача решена, да еще таким простым способом, то сразу хочется поставить новую цель. Какие идеи появились у меня по применению нового инструмента?

  1. Счетчик посещений. Счетчик внутри самого вебсервера будет избавлен от кучи програмного кода благодаря прямому доступу к нужным переменным. Если подключить NoSQL систему типа Redis прямо к Nginx, то мы избавимся и от кучи SQL кода. Это будет совершенно незаметный и чертовски быстрый счетчик!
  2. Анти-ДДОС. C помощью языка, на котором пишется AI большинства современных игр легко делать интеллектуальный фильтр нежелательных запросов к веб-серверу.
  3. Автоматический генератор SEO реврайтов. Вместо ручного прописывания правил и добавления метатегов — пишем скрипт, который генерирует метатеги на лету, например как в модуле для livestreet.
  4. И, конечно, перевод-2.0, с элементами распознавания html блоков и избирательной фильтрации содержимого.


А что придумал ты, уважаемый хабраюзер?

P.S. Скучный пост, совсем нет картинок. На правах анонса добавлю картинку, как SEO рерайт при помощи Nginx изменил позицию в поиске Google. Нужна про это статья?

Tags:
Hubs:
+62
Comments 18
Comments Comments 18

Articles