Как получить реальный IP клиента через прокси nginx/apache?

Используя nginx/apache в качестве прокси для workerman, nginx/apache фактически выступает в роли клиента workerman, поэтому IP-адрес клиента, получаемый на workerman, является IP-адресом сервера nginx/apache, а не реальным IP-адресом клиента. Чтобы получить реальный IP-адрес клиента, можно воспользоваться следующими методами.

Принцип:

nginx/apache передает реальный IP клиента через HTTP заголовок, например, в конфигурации nginx в блоке location добавляется proxy_set_header X-Real-IP $remote_addr;. Workerman считывает это значение заголовка и сохраняет его в $connection объекте, (GatewayWorker может сохранить его в переменной $_SESSION), и при использовании просто считывает эту переменную.

Внимание:

Следующая конфигурация подходит для http/https ws/wss протоколов. Для других протоколов способ получения IP клиента похож, требуется, чтобы прокси-сервер вставлял в пакет данные об IP-адресе, передавая реальный IP клиента.

Конфигурация nginx будет выглядеть примерно так:

server {
  listen 443;

  ssl on;
  ssl_certificate /etc/ssl/server.pem;
  ssl_certificate_key /etc/ssl/server.key;
  ssl_session_timeout 5m;
  ssl_session_cache shared:SSL:50m;
  ssl_protocols SSLv3 SSLv2 TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;

  location /wss
  {
    proxy_pass http://127.0.0.1:8282;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    # Эта часть использует HTTP заголовок для передачи реального IP клиента
    proxy_set_header X-Real-IP $remote_addr;
  }

  # location / {} Другие настройки сайта...
}

Работает с заголовками, установленными nginx для получения IP клиента

<?php

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('websocket://0.0.0.0:7272');

/**
 * Коллбек onWebSocketConnect при рукопожатии клиента через websocket
 * В коллбеке onWebSocketConnect получить значение X_REAL_IP, переданное nginx через HTTP заголовок
 */
$worker->onWebSocketConnect = function(TcpConnection $connection, $request){
    /**
     * В объекте connection изначально нет свойства realIP, здесь мы динамически добавляем ему свойство realIP
     * Не забывайте, что в PHP объекты могут динамически добавлять свойства, вы также можете использовать любое имя свойства, которое вам нравится
     */
    //$connection->realIP = $_SERVER['HTTP_X_REAL_IP']; // использование workerman v4
    $connection->realIP = $request->header('x-real-ip'); // использование workerman v5
};
$worker->onMessage = function(TcpConnection $connection, $data)
{
    // При использовании реального IP клиента просто используйте $connection->realIP
    $connection->send($connection->realIP);
};
Worker::runAll();

GatewayWorker получает IP клиента из заголовка, установленного nginx

Добавьте следующий код в Events.php

class Events
{
   public static function onWebsocketConnect($client_id, $data)
   {    
        $_SESSION['realIP'] = $data['server']['HTTP_X_REAL_IP'];
   }
   // .... Пропущен другой код....
}

После добавления кода необходимо перезапустить GatewayWorker.

Теперь вы можете получить реальный IP клиента через $_SESSION['realIP'] в методах onMessage и onClose в Events.php.

Внимание: В onWorkerStart, onConnect, onWorkerStop в Events.php нельзя напрямую использовать $_SESSION['realIP'].