Как переписать доменную часть Set-Cookie в обратном прокси-сервере nginx?

26

У меня есть простой обратный прокси-сервер nginx:

server {
  server_name external.domain.com;
  location / {
    proxy_pass http://backend.int/;
  }
}

Проблема состоит в том, что Set-Cookieзаголовки ответа содержат ;Domain=backend.int, потому что серверная часть не знает, что это обратный прокси.

Как я могу заставить nginx переписывать содержимое Set-Cookieзаголовков ответов, заменяя их ;Domain=backend.intна ;Domain=external.domain.com?

Передача Hostзаголовка без изменений в этом случае не подходит.

Понимаете, Apache httpd уже некоторое время имел эту возможность ProxyPassReverseCookieDomain, но я не могу найти способ сделать то же самое в nginx.

Тобия
источник
2
почему передача заголовка хоста не вариант? IMO часть заголовка сделан для таких вещей. если вам нужно передать, какой прокси был использован, вы должны указать дополнительные заголовки.
Jojoo
1
Предположим, у вас есть устаревший сервер, который выполняет виртуальный хостинг, и вы хотите поставить Nginx перед ним, чтобы опубликовать некоторые из этих сервисов в новом домене. Предположим также, что вы не можете (или не хотите) изменять конфигурацию устаревшего сервера. Nginx содержит все инструменты, необходимые для публикации устаревших сервисов на новых сайтах, за исключением проблемы с доменом cookie.
Тобия

Ответы:

5

Ответ от @shamer отлично работает с несколькими Set-Cookieзаголовками ответа, но не получается, если есть только один. Как указывает agentzh в конце упомянутого потока, if type(cookies) ~= "table" then cookies = {cookies} endнеобходимо обработать этот случай.

Вот и все:

location / { 
    proxy_pass http://backend.int/;

    header_filter_by_lua '
        local cookies = ngx.header.set_cookie 
        if not cookies then return end
        if type(cookies) ~= "table" then cookies = {cookies} end
        local newcookies = {}
        for i, val in ipairs(cookies) do
            local newval = string.gsub(val, "([dD]omain)=[%w_-\\\\.]+", 
                      "%1=external.domain.com") 
            table.insert(newcookies, newval) 
        end 
        ngx.header.set_cookie = newcookies 
    '; 
}
lhagan
источник
2

Этот вопрос возник в списке рассылки nginx [1]. Нет прямого способа сделать это в nginx. Вы должны прибегнуть к использованию модуля ngx_lua (> = v0.3.1).

У пользователя "agentzh" есть пример того, как это будет выглядеть встраиваемым в файл конфигурации:

    server_name external.domain.com; 

    location / { 
        proxy_pass http://backend.int/;

        header_filter_by_lua ' 
            local cookies = ngx.header.set_cookie 
            if not cookies then return end 
            local newcookies = {} 
            for i, val in ipairs(cookies) do 
                local newval = string.gsub(val, "([dD]omain)=[%w_-\\\\.]+", 
                          "%1=external.domain.com") 
                table.insert(newcookies, newval) 
            end 
            ngx.header.set_cookie = newcookies 
        '; 
    } 

[1] http://nginx.2469901.n2.nabble.com/Rewriting-the-domain-part-of-Set-Cookie-in-a-proxy-pass-td6453554.html

shamer
источник
2
Спасибо за правильный ответ, хотя у меня был плохой опыт работы с ngx_lua в прошлом: плохие утечки памяти. Я думаю, что Nginx нужны некоторые простые примитивы для манипулирования заголовками, использующие его встроенный движок регулярных выражений, если не еще несколько пользовательских инструкций, таких как перезапись домена cookie.
Тобия