php-fpm behind a reverse proxy server

Имеем nginx:1.25.4-alpine и схему работы:

Теперь о том, что нужно сделать, чтобы получить в php-fpm из Nginx upstream те же значения что и в Nginx Reverse proxy.

$_SERVER['HTTP_HOST']

В Nginx Reverse proxy указываем:

proxy_set_header Host $host; 

все, больше ничего делать не нужно (неизвестная мне магия).

$_SERVER['REQUEST_SCHEME']

proxy_set_header X-Forwarded-Scheme $scheme;

а в Nginx upstream после include fastcgi_params; указываем:

fastcgi_param REQUEST_SCHEME $http_x_forwarded_scheme;
# это говорит Symfony, чтобы Symfony редиректил на https (по умолчанию редиректит на http):
fastcgi_param HTTPS "on";
# непонятно зачем нужна эта директива, из практики я не понял, чем это помогает Symfony:
fastcgi_param SERVER_PORT "443";

Чтение заголовка в nginx

Рассмотрим момент, когда мы передаем заголовок, а затем его значение читаем из переменной.

Чтобы стало еще понятней - создадим в нашем nginx-конфиге location:

location /test {
    return 200 "nginx said $http_word";
}

Теперь делаем запрос:

# curl -H 'word: hello' http://localhost:8000/test

и получаем ответ: nginx said hello

Думаю, идею Вы поняли, подведем маленький итог:

  1. регистр симоволов заголовка не важен (Section 3.1 of RFC 822 [9] : Field names are case-insensitive)
  2. если заголовок не передать, то значение переменной будет равно пустой строке (отлично)
  3. все заголовки можно вычитать из переменных с префиксом $http_ (как видно "-" заменыны на "_")
  4. принято передаваемым заголовкам давать названия начинающиеся с X-Forwarded- (хотя даже на сайте nginx.com и не только, можно встретить кучу примеров не придерживающиеся такой политики именования)

Поехали дальше.

$_SERVER['REMOTE_ADDR']

В Nginx Reverse proxy указываем:

proxy_set_header X-Forwarded-Remote-Addr $remote_addr;

а в Nginx upstream указываем:

fastcgi_param REMOTE_ADDR $http_x_forwarded_remote_addr;

п.с. по по-умолчанию в phpinfo $_SERVER['REMOTE_ADDR'] = 127.0.0.1

$_SERVER['HTTP_X_FORWARDED_REQUEST_ID']

Nginx генерирует ID запроса ($request_id), который мы можем прокинуть в PHP, поэтому в Nginx Reverse proxy указываем:

proxy_set_header X-Forwarded-Request-Id $request_id;

а в Nginx upstream указываем:

fastcgi_param HTTP_X_FORWARDED_REQUEST_ID $http_x_forwarded_request_id;

а в PHP просто вычитываем его из $_SERVER. Кстати, вот какие заголовки используют в Symfony.

Что дальше

Дальше думаю, Вы сами справитесь, кстати если в nginx.conf подключить include fastcgi_params; то у Вас будут:

# cat /etc/nginx/fastcgi_params 

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  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

Исключения в названии переменных

Чтобы передать IP адреса клиентов участвующих в цепочке запросов, в nginx.conf добавляют:

fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;

Как видите, название переменной не соответсвует обозначенному мной ранее.

Т.к. между Nginx Reverse proxy и Nginx upstream есть еще сервера, то REMOTE_ADDR получают так:

  set $realip $remote_addr;
  if ($http_x_forwarded_for ~ "^(\d+\.\d+\.\d+\.\d+)") {
    set $realip $1;
  }
  fastcgi_param REMOTE_ADDR $realip;

Заметка

Некоторые не чураются делать проброс и для похожих заголовков:

fastcgi_param HTTP_X_REQUEST_ID $http_x_forwarded_request_id;
fastcgi_param HTTP_REQUEST_ID $http_x_forwarded_request_id;

но я так делать не буду, чтобы не ломать концепцию.

Что нам предлагают передавать в интернетах

# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Port  $server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";

Зачем-то мапят данные:

map $http_x_forwarded_proto $thescheme {
     default $scheme;
     https https;
}
proxy_set_header X-Forwarded-Proto $thescheme;

Источники: 1 - 2 - 3- 4


11.09.2021 07:08

Комментарии

Комментариев пока нет.


Copyrights © 2007 - 2026 YaPro.Ru