Come ottenere l'IP reale del client attraverso il proxy nginx/apache?

Quando si utilizza nginx/apache come proxy per workerman, in realtà nginx/apache funge da client per workerman, quindi l'IP del client ottenuto su workerman è l'IP del server nginx/apache, non l'IP reale del client. Ecco come ottenere l'IP reale del client:

Principio:

nginx/apache passa l'IP reale del client tramite l'intestazione HTTP, ad esempio nella configurazione nginx aggiungere proxy_set_header X-Real-IP $remote_addr; all'interno della direttiva location. Workerman legge questo valore dall'intestazione e lo salva nell'oggetto $connection (GatewayWorker può salvarlo nella variabile $_SESSION), quindi può essere letto direttamente quando necessario.

Nota:

Questa configurazione è adatta per i protocolli http/https ws/wss. Per ottenere l'IP del client in altri protocolli, è necessario che il server proxy inserisca un blocco di dati IP per passare l'IP reale del client.

Configurazione nginx simile a quanto segue:

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";
    # Questa parte passa l'IP reale del client tramite l'intestazione HTTP
    proxy_set_header X-Real-IP $remote_addr;
  }

  # location / {} Altre configurazioni del sito...
}

Lettura dell'IP del client impostato da nginx da workerman:

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

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

// Quando il client si connette e completa la handshaking WebSocket
$worker->onConnect = function(TcpConnection $connection) {
   /**
    * Callback onWebSocketConnect durante la handshaking del client WebSocket
    * Ottiene il valore X_REAL_IP tramite l'intestazione http in onWebSocketConnect
    */
   $connection->onWebSocketConnect = function(TcpConnection $connection){
       /**
        * L'oggetto connection non ha l'attributo realIP, quindi qui si aggiunge dinamicamente
        * l'attributo realIP all'oggetto connection
        */
       $connection->realIP = $_SERVER['HTTP_X_REAL_IP'];
   };
};
$worker->onMessage = function(TcpConnection $connection, $data)
{
    // Quando si utilizza l'IP reale del client, si può usare direttamente $connection->realIP
    $connection->send($connection->realIP);
};
Worker::runAll();

Ottenere l'IP del client impostato da nginx da GatewayWorker:

Aggiungi il seguente codice a Events.php:

class Events
{
   public static function onWebsocketConnect($client_id, $data)
   {    
        $_SESSION['realIP'] = $data['server']['HTTP_X_REAL_IP'];
   }
   // ... Altri codici omessi...
}

Dopo aver aggiunto il codice, è necessario riavviare GatewayWorker.

In questo modo, è possibile ottenere l'IP reale del client in onMessage e onClose metodi di Events.php utilizzando $_SESSION['realIP'].

Nota: onWorkerStart, onConnect, onWorkerStop in Events.php non possono utilizzare direttamente $_SESSION['realIP'].