Я чесал голову в течение нескольких часов и хотел посмотреть, может ли кто-нибудь помочь.
1) У меня есть балансировщик нагрузки с 6 серверами в задней части.
2) Внутренние серверы - это Nginx, и для получения реальных IP-адресов посетителей все, что мне нужно сделать, это выполнить следующие действия при каждой установке Nginx, и я могу получить реальный IP-адрес клиента для каждого посетителя.
set_real_ip_from 192.168.255.0/24; <-- to handle the load balancer IP
real_ip_header X-Forwarded-For;
3) Теперь я установил Varnish перед каждым Nginx, работающим на 127.0.0.1, выполняющим кеширование, и по какой-то причине Nginx больше не видит настоящие IP-адреса клиентов, поступающие из LoadBalancer -> Varnish -> Nginx
Он печатает следующее:
IP-адрес: 192.168.255.9 <- это должен быть реальный IP-адрес клиента, а не 192.168 (при условии, что IP-адрес балансировщика нагрузки печатается)
Более подробный адрес хоста: 192.168.255.9
Большое спасибо, если вы можете помочь.
Дэйв
ОБНОВИТЬ:
Без Varnish в уравнении у меня есть следующий LB -> NGINX, а в NGINX существуют следующие
set_real_ip_from 192.168.255.0/24;
real_ip_header X-Forwarded-For;
Когда NGINX регистрирует remote_addr, первая запись ниже печатает реальный IP-адрес клиента.
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
213.205.234.x - - [05/Sep/2012:09:42:08 -0700] "GET /2011/10/28/chicken-and-apples-in- honey-mustard-sauce/ HTTP/1.1" 200 18283 "-" "Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9100 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30" "213.205.234.x"
С Varnish в уравнении LB -> Varnish -> NGINX
А в NGINX я переключил set_real_ip_from на 127.0.0.1
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
$ remote_addr в NGINX не выводит реальный IP-адрес клиента:
192.168.255.9 - - [05/Sep/2012:09:46:41 -0700] "GET /2012/09/03/stuffed-baked-potatoes-deconstructed/ HTTP/1.1" 200 18159 "-" "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; ADR6400L Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" "69.255.125.x, 192.168.255.9"
Как видно из вышеизложенного, печатаемый $ remote_addr - это IP-адрес балансировщика нагрузки: 192.168.255.9 вместо удаленного_аддра клиента. Хотя «$ http_x_forwarded_for» печатает правильный адрес, я думаю: «69.255.125.x, 192.168.255.9». Моя цель - сделать так, чтобы $ remote_addr содержал вместо этого правильный IP-адрес.
Спасибо Дэйв
ОБНОВИТЬ:
Вот мой default.vcl от Varnish, закомментировал часть, упомянутую Шейном, вот текущий вывод журнала доступа от NGINX
127.0.0.1 - - [05/Sep/2012:11:16:43 -0700] "GET /wp-content/plugins/wp-pagenavi/pagenavi-css.css?ver=2.70 HTTP/1.1" 304 0 "http://mobilefoodblog.com/2011/10/28/chicken-and-apples-in-honey-mustard-sauce/" "Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; SCH-I405 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" "67.168.209.192, 192.168.255.9"
# This is a basic VCL configuration file for varnish. See the vcl(7)
# man page for details on VCL syntax and semantics.
#
# Default backend definition. Set this to point to your content
# server.
#
backend default {
.host = "localhost";
.port = "8080";
}
sub detect_device {
# Define the desktop device
set req.http.X-Device = "desktop";
if (req.http.User-Agent ~ "iP(hone|od)" || req.http.User-Agent ~ "Android" || req.http.User-Agent ~ "iPad") {
# Define smartphones and tablets
set req.http.X-Device = "smart";
}
elseif (req.http.User-Agent ~ "SymbianOS" || req.http.User-Agent ~ "^BlackBerry" || req.http.User-Agent ~ "^SonyEricsson" || req.http.User-Agent ~ "^Nokia" || req.http.User-Agent ~ "^SAMSUNG" || req.http.User-Agent ~ "^LG") {
# Define every other mobile device
set req.http.X-Device = "other";
}
}
acl purge {
"localhost";
}
sub vcl_recv {
call detect_device;
# 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;
# }
# }
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
return(lookup);
}
if (req.url ~ "^/$") {
unset req.http.cookie;
}
}
sub vcl_hit {
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged.";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
error 404 "Not in cache.";
}
if (!(req.url ~ "wp-(login|admin)")) {
unset req.http.cookie;
}
if (req.url ~ "^/[^?]+.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.|)$") {
unset req.http.cookie;
set req.url = regsub(req.url, "\?.$", "");
}
if (req.url ~ "^/$") {
unset req.http.cookie;
}
}
sub vcl_fetch {
if (req.url ~ "^/$") {
unset beresp.http.set-cookie;
}
if (!(req.url ~ "wp-(login|admin)")) {
unset beresp.http.set-cookie;
}
}
sub vcl_hash {
set req.hash += req.url;
if (req.http.host) {
set req.hash += req.http.host;
} else {
set req.hash += server.ip;
}
# And then add the device to the hash (if its a mobile device)
if (req.http.X-Device ~ "smart" || req.http.X-Device ~ "other") {
set req.hash += req.http.X-Device;
}
return (hash);
}
Поскольку Varnish работает на каждом сервере, на котором запущен nginx, источником соединения с точки зрения nginx является 127.0.0.1, а не балансировщик нагрузки.
set_real_ip_from 192.168.255.0/24;
Это проблема; nginx не будет "доверять" X-Forwarded-For
заголовок, когда соединение исходит от 127.0.0.1 (процесс Varnish); все, что он доверяет, - это вся сеть 192.168.255.0/24. Добавьте авторизацию, чтобы доверять заголовку, когда Varnish отправляет его.
set_real_ip_from 127.0.0.1;
Редактировать:
nginx плохо себя ведет при разборе X-Forwarded-For
заголовок для «настоящего» IP клиента; он ищет последнюю запись в заголовке, которая никогда не является реальным IP-адресом клиента, если имеется более одной записи. Видеть этот вопрос для получения дополнительной информации по этой проблеме.
Я бы рекомендовал, чтобы Varnish перестал добавлять свои собственные X-Forwarded-For
заголовок. Вы захотите снять эту часть vcl_recv
функция:
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;
}
}
Предоставьте текущую конфигурацию vcl, если вам нужна помощь, что нужно изменить для вас, так как это может быть явно настроено или добавлено по умолчанию (или и то и другое).
Изменить 2:
Замените это на vcl_recv
функция в вашей конфигурации Varnish; он объединяет настройки, которые вы настроили, с поведением по умолчанию при удалении X-Forwarded-For
обман, который присутствует по умолчанию.
sub vcl_recv {
call detect_device;
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
return(lookup);
}
if (req.url ~ "^/$") {
unset req.http.cookie;
}
# Default logic follows; it's normally appended.
# It'll still be appended, but having the return(lookup)
# prevents its use. X-Forward-For header behavior removed.
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.request != "GET" && req.request != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
/* Not cacheable by default */
return (pass);
}
return (lookup);
}
Похоже, ваш балансировщик нагрузки не передает IP-адрес клиента ни в одном заголовке. Поскольку вы не сказали, что используете для балансировщика нагрузки, невозможно дать конкретное решение, но в целом вы хотите настроить балансировщик нагрузки так, чтобы IP-адрес клиента помещался в один из заголовков (например, X-Forwarded-For
). Вы также можете назначить для этого собственный заголовок, если хотите.
Если ваш балансировщик нагрузки устанавливает X-Forwarded-For, я бы настроил ваши серверы Varnish так, чтобы они устанавливали заголовок, отличный от X-Forwarded-For, чтобы у вас была полная видимость как IP-адреса клиента, так и того, какой сервер обработал запрос. .
Предполагая, что ваш балансировщик нагрузки использует X-Forwarded-For
заголовок для HTTP и HTTPS, тогда ...
sub vcl_recv {
...
set req.http.X-Forwarded-For = req.http.X-Forwarded-For;
server {
...
set_real_ip_from 192.168.255.0/24;
real_ip_header X-Forwarded-For;
Я добавлю что вы действительно должны запускать только 1 экземпляр Varnish, это лишает смысла иметь несколько кешей (так как балансировщик нагрузки может передать запрос на незаполненный экземпляр Varnish). Ваши показатели попадания будут хуже, не говоря уже о том, что это просто пустая трата ресурсов.