Лак автоматическое добавление IP балансировщика нагрузки в заголовок X-Forwarded-For
мой поток запросов выглядит следующим образом;
HAProxy --> Varnish (4.0.1) --> Apache web backends
когда новый запрос поступает в HAProxy, IP-адрес клиента добавляется в X-Forwarded-For
заголовок (что хорошо!). Тем не менее, похоже, что лак добавляет HAProxy
IP также. Когда запрос попадает в мой vcl_recv
порядок,X-Forwarded-For
заголовок:
X-Forwarded-For: end-user-ip, haproxy-ip
вы можете видеть это в varnishlog
выход:
* << Request >> 8
- Begin req 7 rxreq
- Timestamp Start: 1409262358.542659 0.000000 0.000000
- Timestamp Req: 1409262358.542659 0.000000 0.000000
- ReqStart 192.168.1.103 48193
- ReqMethod PURGE
- ReqURL /some/path
- ReqProtocol HTTP/1.1
- ReqHeader Authorization: Basic xxx
- ReqHeader User-Agent: curl/7.30.0
- ReqHeader Host: example.com
- ReqHeader Accept: */*
- ReqHeader X-Forwarded-For: 1.2.3.4
- ReqHeader Connection: close
- ReqUnset X-Forwarded-For: 1.2.3.4
- ReqHeader X-Forwarded-For: 1.2.3.4, 192.168.1.101
- VCL_call RECV
- ReqUnset X-Forwarded-For: 1.2.3.4, 192.168.1.101
- VCL_acl NO_MATCH purge_acl
- Debug "VCL_error(403, Not allowed.)"
- VCL_return synth
причина, по которой мне нужен точный IP-адрес клиента, заключается в том, что я могу его проверить против правил ACL для PURGE
/BAN
. С момента последнего IP в X-Forwarded-For
заголовок-это HAProxy, проверка ACL не выполняется для всех IPs. Вот соответствующий раздел моей конфигурации:
acl purge_acl {
"1.2.3.4";
}
sub vcl_recv {
set req.backend_hint = load_balancer.backend();
if (req.method == "PURGE") {
if (!std.ip(req.http.X-forwarded-for, "0.0.0.0") ~ purge_acl) {
return(synth(403, "Not allowed."));
}
ban("obj.http.x-url ~ " + req.url);
return(synth(200, "Ban added"));
}
}
любые идеи, как я могу полагаться исключительно на X-Forwarded-For
заголовок от HAProxy, без подделки лака?
Примечание стороны, кажется, что лак делает именно это (хотя это не в конфигурации MV VCL):
if (req.restarts == 0) {
if (req.http.X-Forwarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
3 ответов
я также столкнулся с этой проблемой сегодня.
на default.vcl
в varnish 4.0 был переименован в builtin.vcl
и не содержит set req.http.X-Forwarded-For
часть, которую вы упомянули - ссылке. Тем не менее он явно добавляет в разделенный запятыми список промежуточный IP - адрес прокси в соответствии со спецификациями протокола -ссылка на Википедию.
одним из решений было бы использовать X-Real-IP
заголовок вместо этого, перезаписывая этот заголовок все время в HAProxy с реальным ip-адрес клиента и использование этого для VCL ACL.
другое решение, как (ошибочно) упоминается в лаковом форуме, будет regsub(req.http.X-Forwarded-For, "[, ].*$", "")
это занимает самый левый IP-адрес. Однако этот метод НЕ БЕЗОПАСНО, так как этот заголовок можно легко подделать.
мое предложение состояло бы в том, чтобы извлечь известную часть, лакировать IP из заголовка следующим образом:
if (!std.ip(regsub(req.http.X-Forwarded-For, ", 192\.168\.1\.101$", ""), "0.0.0.0") ~ purge_acl) {
return(synth(403, "Not allowed."));
}
единственная проблема с этим, если есть более 2 прыжков в связь, например. вы также используете прокси для подключения к интернету. Хорошим решением для этого является nginx
так как вы можете определить доверенные прыжки, и они игнорируются рекурсивно до реального IP-адреса клиента.
set_real_ip_from 192.168.1.101;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
вы можете увидеть более подробную информацию об этом в этом serverfault thread ответ
вы также можете проверить, почему в вашем VCL_call RECV
вы ReqUnset X-Forwarded-For
перед матчем ACL.
Varnish добавляет свою логику по умолчанию к любым функциям, которые вы определяете, таким как vcl_recv
вместо того, чтобы просто переопределять его. Значение по умолчанию vcl_recv
логика содержит:
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
как вы заметили. Мне кажется странным, что это похоже на логику по умолчанию лака в vcl_recv
выполняется впереди vcl_recv
логика. Какое значение вы видите для X-Forwarded-For
внутри vcl_deliver
если вы определяете свой собственный?
одна вещь, которую вы могли бы сделать, это разобрать первый IP-адрес, как это, где необходимо:
set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "^([^,]+),?.*$", "");
исходный код Vanish переместился в GitHub, поэтому для справки, начиная с версии 4.0, логика X-Forwarded-For была перемещена из builtin.vcl
(ранее default.vcl
), а исходную логику можно найти в bin / varnishd / cache / cache_req_fsm.c.