Nginx + apache 2 = нет real-ip. Способ решения.
Рубрики: Webdev
Сегодня будет пост, который к сеонизму имеет мало отношения, но может оказаться весьма полезным тем, кто держит свои сервера.
Если кто не знает, nginx – это такой очень маленький и очень быстрый сервер, который может работать как прокси. И , если его поставить поверх апача, то тогда скрипты в переменной REMOTE_ADDR будут видеть не айпишник клиента, а айпи nginx’а (127.0.0.1 обычно). В случае с apache 1.3 эта проблема решается с помощью модуля mod_realip от создателя nginx. Но в случае apache 2 это решается несколько сложнее.
Я не могу решить эту задачу с пол года. В основно из-за того, что и без этого всё работало. Да и вообще было влом вновь ковыряться с сервером, благо пока всё работает как часы. Но сегодня всё-таки решился и сделал это.
Итак, чтобы пофиксить проблему с реальными айпишниками клиентов при использовании связки nginx+apache2, нужн-то всего лишь поставить один модуль к апачу и прописать 3 строки в конфигах.
Модуль нужен rpaf2. Если у вас freebsd, то его брать нужно тут ports/www/mod_rpaf2, дальше стандартно make install clean, дальше он уже сам себя в пишет в httpd.conf, нужно будет только раскомментировать строчку
#LoadModule rpaf_module libexec/apache2/mod_rpaf.so
Путь к .so файлу может отличаться. Это не суть важно. Если у вас не freebsd, то брать модуль отсюда. Собирать и прописывать вышеприведенную строчку в конфиге апача.
Дальше там же в конфиге апача нужно добавить 2 строчки:
RPAFproxy_ips 127.0.0.1
RPAFEnable On
Первая строка – это айпишник(и) прокси(ей), вторая – говорит апачу, что rpaf юзать нужно. Что делает rpaf – он из заголовка X-Forwarded-for делает REMOTE_ADDR.
Собственно остается в конфиге nginx’а в разделе server дописать одну строчку:
proxy_set_header X-Forwarded-for $remote_addr;
Теперь нужно перезапустить оба сервер любым способом. Через панель управления там или из шела. С апачем всё понятно, а вот для управления nginx’ом можно сделать такой вот .sh файлик:
kill -HUP `cat /usr/local/etc/nginx/logs/nginx.pid`
Эта строка подаёт процессу nginx сигнал о том, что ему нужно применить новый конфиг и перезапустить worker-процессы. nginx.pid – соответственно файл с текущим номером мастер-процесса nginx’а.
Все, проблема решена.
зы
Всё хочу написать серию статей «Nginx для чайников», да вот руки не доходят.
Метки: apache • nginx • proxy • администрирование сервера • сервер


Обязательно напиши как устанавливать и настраивать nginx, многим будет полезно! Ждем.
Постараюсь. Но это много писать надо, а много писать у меня редко получается
Как сделать так, чтобы не искажалась переменная HTTP_X_FORWARDED_FOR??? В ней передается внутренний ip клиента, когда он идет через прокси.
Мне надо получать неискаженную remote_addr и HTTP_X_FORWARDED_FOR одновременно, в апаче, работающем через nginx. Как такое сделать??? Нигде не нашел информации по этому поводу
> Всё хочу написать серию статей “Nginx для чайников”, да вот руки не доходят.
Писать статью (а тем более много) для такой мелкой и миллион раз описанной процедуры это понтизм и идиотизм.
2 vir
когда дело доходит до nginx’а, то любой материал крайне полезен. Я, например, совершенно нихера не понимаю в администрировании серверов под *nix’ом, но мне пришлось ставить nginx чтобы как-то привести нагрузку на сервер в норму. И я не нашел ни одного нормального материала в инете, где всё было бы разжовано для совсем глупых, как я. Везде подразумевается, что ты уже дохера чего знаешь.
2Padlik:
Так держать!
2Andrey:
Для того, чтобы пременная передалась Апачу, вам необходимо установить соответствующий Header:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Так же приведу несколько полезных строк, помогающих обойти ряд ошибок при использовании PHP(fcgi) с NginX:
location ~ .php$ {
fastcgi_pass 127.0.0.1:8888;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REQUEST_URI $fastcgi_script_name?$query_string;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $document_root;
}
Так же, вполне возможно, вы могли сталкнуться с проблемой при использовании NginX как SSL proxy. Проблема заключается в том, что при редиректе NginX отправит запрос на Apache, порт 80, и будет невозможно определить PHP скриптом, находиться пользователь в HTTPS-зоне или в HTTP. Данной ситуации вам поможет следующая магическая грабля:
в NginX, при редиректе:
proxy_set_header SSL YES;
В .htaccess или в конфигурацию виртуального хоста:
RewriteEngine on
RewriteCond %{HTTP:SSL} YES
RewriteRule .* – [E=HTTPS:on,L]
RewriteRule .* – [E=SERVER_PORT:443,L]
Что установит переменные HTTP_SERVER_VARS[HTTPS]=on, как и должно быть по теории.
Padlik, благодарю за статью!
Сделал всё как написано на Apache 2.2 + Nginx, заработало «на ура», realIP появился! Если б не эта статья то ещё бы долго мучался, аналогичного материала в сети нет, одни вопросы без ответов.
2 Slava
Я сам так и не смог найти ни одной нормальной статьи по этому делу. Только через прокуривание половины рассылки по nginx смог осилить эту проблему
Может проще так, не сбивая родные параметры?
В httpd.conf пишем
RPAFEnable On
RPAFproxy_ips 127.0.0.1
RPAFheader X-Real-IP
в nginx.conf пишем
proxy_set_header X-Real-IP $remote_addr;
Решение этой же проблемы под линухом http://padlik.ru/entries/265.html
> kill -HUP `cat /usr/local/etc/nginx/logs/nginx.pid`
а «/usr/local/etc/rc.d/nginx restart» уже не подходит для ребута?
>а “/usr/local/etc/rc.d/nginx restart” уже не подходит для ребута?
ето убьет текущие конекты, а через HUP сигнал переоткроются процессы с новым конфигом