Como obter o verdadeiro IP do cliente através do proxy nginx/apache?

Usando nginx/apache como proxy para workerman, o nginx/apache efetivamente atua como o cliente do workerman, portanto, o IP do cliente obtido no workerman será o IP do servidor nginx/apache, e não o IP real do cliente. Para obter o verdadeiro IP do cliente, você pode seguir os métodos abaixo.

Princípio:

O nginx/apache transmite o verdadeiro IP do cliente através do cabeçalho HTTP, por exemplo, na configuração do nginx, adicione em location a linha proxy_set_header X-Real-IP $remote_addr; para configurá-lo. O workerman lê esse valor do cabeçalho e o armazena no $connection objeto, (GatewayWorker pode armazená-lo na variável $_SESSION), e ao usá-lo, você pode acessar a variável diretamente.

Atenção:

As configurações a seguir se aplicam aos protocolos http/https ws/wss. Para outros protocolos, o método para obter o IP do cliente é semelhante, exigindo que o servidor proxy insira uma seção de dados de IP no pacote para transmitir o verdadeiro IP do cliente.

A configuração do nginx é semelhante à seguinte:

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";
    # Esta parte utiliza o cabeçalho http para transmitir o verdadeiro IP do cliente
    proxy_set_header X-Real-IP $remote_addr;
  }

  # location / {} Outras configurações do site...
}

O workerman lê o IP do cliente do cabeçalho definido pelo nginx

<?php

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

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

/**
 * Callback onWebSocketConnect durante a conexão websocket do cliente
 * No callback onWebSocketConnect, obtenha o valor X_REAL_IP do cabeçalho http definido pelo nginx
 */
$worker->onWebSocketConnect = function(TcpConnection $connection, $request){
    /**
     * O objeto connection originalmente não possui o atributo realIP, aqui adicionamos dinamicamente um atributo realIP ao objeto connection
     * Lembre-se de que objetos PHP podem ter atributos adicionados dinamicamente, e você pode usar o nome de atributo que preferir
     */
    //$connection->realIP = $_SERVER['HTTP_X_REAL_IP']; // Uso do workerman v4
    $connection->realIP = $request->header('x-real-ip'); // Uso do workerman v5
};
$worker->onMessage = function(TcpConnection $connection, $data)
{
    // Ao usar o verdadeiro IP do cliente, basta usar $connection->realIP
    $connection->send($connection->realIP);
};
Worker::runAll();

O GatewayWorker obtém o IP do cliente do cabeçalho definido pelo nginx

Adicione o seguinte código ao Events.php

class Events
{
   public static function onWebsocketConnect($client_id, $data)
   {    
        $_SESSION['realIP'] = $data['server']['HTTP_X_REAL_IP'];
   }
   // .... Código omitido....
}

Após adicionar o código, é necessário reiniciar o GatewayWorker.

Dessa forma, você pode obter o verdadeiro IP do cliente através de $_SESSION['realIP'] nos métodos onMessage e onClose dentro do Events.php.

Atenção: Nos métodos onWorkerStart, onConnect e onWorkerStop no Events.php, não é possível usar diretamente $_SESSION['realIP'].