Лак сбрасывает все, кроме последнего x-forwarded-for IP-адреса... ошибка?

При попытке выяснить, почему наша установка Varnish 4.1 (на CentOS7 через репозиторий varnish-cache.org) не следовала правилам vcl, установленным для регистрации IP-адреса клиента в заголовке X-Forwarded-For (см. " Журнал прокси Varnish 4") / балансировщик нагрузки вместо клиентских IP-адресов) Я случайно заметил что-то странное при просмотре файлов varnishlog:

- Begin        req 9353447 rxreq
- Timestamp    Start: 1488771709.337974 0.000000 0.000000
- Timestamp    Req: 1488771709.337974 0.000000 0.000000
- ReqStart     172.25.20.65 19903
- ReqMethod    GET
- ReqURL       /about-us/
- ReqProtocol  HTTP/1.1
- ReqHeader    host: www.<notreallythishost>.com
- ReqHeader    Accept: */*
- ReqHeader    Accept-Encoding: gzip, deflate
- ReqHeader    Cache-Control: no-cache
- ReqHeader    From: bingbot(at)microsoft.com
- ReqHeader    Pragma: no-cache
- ReqHeader    User-Agent: Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)
- ReqHeader    X-Forwarded-For: 40.77.167.41
- ReqHeader    X-Forwarded-Port: 80
- ReqHeader    X-Forwarded-Proto: http
- ReqHeader    Connection: keep-alive
- ReqUnset     X-Forwarded-For: 40.77.167.41
- ReqHeader    X-Forwarded-For: 40.77.167.41, 172.25.20.65
- VCL_call     RECV
- ReqUnset     X-Forwarded-For: 40.77.167.41, 172.25.20.65
- ReqHeader    X-Forwarded-For: 172.25.20.65
- ReqUnset     Accept-Encoding: gzip, deflate
- ReqHeader    Accept-Encoding: gzip
- ReqUnset     User-Agent: Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)
- VCL_return   hash
- VCL_call     HASH
- VCL_return   lookup
- VCL_call     MISS
- VCL_return   fetch
- Link         bereq 9353449 fetch
- Timestamp    Fetch: 1488771709.338395 0.000421 0.000421
- RespProtocol HTTP/1.1

Это полностью объясняет, почему нам никогда не удавалось получить что-либо кроме IP-адреса балансировщика нагрузки, зарегистрированного через varnishncsa, в любой точке независимо от используемой нами технологии ведения журнала.

Похоже, что при обработке запроса он создает заголовок X-Forwarded-For, добавляя в заголовок IP-адрес AWS Load Balancer, но при вызове vc_call он снова восстанавливается и удаляется исходный IP-адрес клиента. Итак, как мне сохранить нетронутым X-Forwarded-For и почему Varnish смещает IP-адреса с левой стороны, а не просто добавляет их в заголовок X-Forwarded-For, как это должно быть? Ошибка?

1 ответ

Решение

Таким образом, обходной путь для этого (возможная ошибка в 4.1.3-1.el7.x86_64) был подсказкой, которую я нашел, просматривая другие вопросы о журналировании лака, в частности, один из них по отключению заголовка x-forwarded-for вообще.

Хотя это не то, что я хотел сделать, он дал намек о том, чтобы не допустить добавления лаком своего собственного содержимого vcl_recv к основанию моего определения функции vcl_recv. В частности, укажите свой собственный возврат (поиск) (хотя это лак <= 3) или возврат (хеш) (лак 4.x).

Так что теперь у меня есть это в верхней части vcl_recv():

# ensure proper logging of x-forwarded-for IP addresses
std.collect(req.http.x-forwarded-for);
set req.http.x-forwarded-for = regsub ( req.http.x-forwarded-for, "^(([0-9]{1,3}\.){3}[0-9]{1,3})(.*)", "\1" );
if (req.http.x-forwarded-for) {
    std.log("ip:" + req.http.x-forwarded-for);
} else {
    std.log("ip:" + client.ip);
}

Затем, в самом конце функции, я, конечно, как я уже упоминал:

return (hash);

Так что теперь он успешно регистрирует только IP-адрес клиента, как и должно быть, с добавлением опции varnishncsa:

-F "%%{VCL_Log:ip}x %%l %%u %%t \"%%r\" %%s %%b \"%%{Referer}i\" \"%%{User-agent}i\""

Надеюсь, кто-то найдет эту информацию полезной.

ОБНОВЛЕНИЕ: Так же, как примечание, я нашел этот пост о спуфинге в этом ответе nginx, и было бы неплохо иметь что-то вроде заголовков real_ip_from или rust_ip_from на лаке, но на данный момент он не выглядит изначально. Мое первоначальное решение выберет поддельный адрес в этом случае. Поэтому было бы лучше удалить регулярное выражение с удаленными известными IP-адресами, а вместо этого выбрать первый необработанный IP-адрес клиента. Примерно так будет работать:

set req.http.x-forwarded-for = regsub ( req.http.x-forwarded-for, "(([0-9]{1,3}\.){3}[0-9]{1,3})(, (172.25.20.65|172.25.10.228),?)+$", "\1" );

где 172.25.20.65 и 172.25.10.228 - мои доверенные IP-адреса (прокси-серверы или балансировщики нагрузки выбраны и добавлены в X-Forwarded-For и т. д.). В зависимости от того, ожидаете ли вы увидеть прокси /LB перед ним, ваше регулярное выражение может быть таким, если вы ожидаете, что в заголовке всегда будет хотя бы один балансировщик / прокси нагрузки:

(([0-9]{1,3}\.){3}[0-9]{1,3})(, (<trustedip1>|<trustedip2>|...),?)+$

или это, если допустимо не иметь ничего перед вашим лаковым сервером:

(([0-9]{1,3}\.){3}[0-9]{1,3})(, (<trustedip1>|<trustedip2>|...),?)*$

Хотя, если это последний случай, зачем вам искать заголовок x-forwarded-for...

Другие вопросы по тегам