Nginx + apache 2 = нет real-ip. Способ решения.

Сегодня будет пост, который к сеонизму имеет мало отношения, но может оказаться весьма полезным тем, кто держит свои сервера.

Если кто не знает, 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 для чайников», да вот руки не доходят.

В закладки!

Nginx + apache 2 = нет real-ip. Способ решения.: 16 комментариев

  1. Как сделать так, чтобы не искажалась переменная HTTP_X_FORWARDED_FOR??? В ней передается внутренний ip клиента, когда он идет через прокси.
    Мне надо получать неискаженную remote_addr и HTTP_X_FORWARDED_FOR одновременно, в апаче, работающем через nginx. Как такое сделать??? Нигде не нашел информации по этому поводу

  2. > Всё хочу написать серию статей “Nginx для чайников”, да вот руки не доходят.

    Писать статью (а тем более много) для такой мелкой и миллион раз описанной процедуры это понтизм и идиотизм.

  3. 2 vir
    когда дело доходит до nginx’а, то любой материал крайне полезен. Я, например, совершенно нихера не понимаю в администрировании серверов под *nix’ом, но мне пришлось ставить nginx чтобы как-то привести нагрузку на сервер в норму. И я не нашел ни одного нормального материала в инете, где всё было бы разжовано для совсем глупых, как я. Везде подразумевается, что ты уже дохера чего знаешь.

  4. 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, как и должно быть по теории.

  5. Padlik, благодарю за статью!
    Сделал всё как написано на Apache 2.2 + Nginx, заработало «на ура», realIP появился! Если б не эта статья то ещё бы долго мучался, аналогичного материала в сети нет, одни вопросы без ответов.

  6. 2 Slava
    Я сам так и не смог найти ни одной нормальной статьи по этому делу. Только через прокуривание половины рассылки по nginx смог осилить эту проблему :)

  7. Может проще так, не сбивая родные параметры?

    В httpd.conf пишем
    RPAFEnable On
    RPAFproxy_ips 127.0.0.1
    RPAFheader X-Real-IP

    в nginx.conf пишем

    proxy_set_header X-Real-IP $remote_addr;

  8. >а “/usr/local/etc/rc.d/nginx restart” уже не подходит для ребута?
    ето убьет текущие конекты, а через HUP сигнал переоткроются процессы с новым конфигом

  9. Самая главная загвоздка в установке apxs на centos. Yum не катит, потому что не находит такого пакета. Установил httpd-devel, но и это не помогло. Как быть? Без этого не могу скомпилировать mod_rpaf.

  10. Уведомление: Что людям интересно :Padlik.ru

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>