How to get the actual client IP address through nginx/apache proxy?

When using nginx/apache as a proxy for Workerman, nginx/apache actually acts as the client for Workerman. As a result, the IP address obtained in Workerman will be that of the nginx/apache server, not the actual client's IP address. The following method can be used to obtain the actual client IP address.


nginx/apache passes the client's actual IP address through the HTTP header, for example, by setting the following in the nginx configuration within the location block:

proxy_set_header X-Real-IP $remote_addr;

Workerman reads this header value and saves it to the $connection object (or $_SESSION variable in GatewayWorker). The IP address can be directly accessed when needed.


The following configuration is suitable for http/https ws/wss protocols. Similar methods are required for obtaining the client IP address for other protocols, where the proxy server needs to insert a segment of IP data to pass the actual client IP address.

Sample nginx configuration:

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_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    # This part is used to pass the actual client IP through the HTTP header
    proxy_set_header X-Real-IP $remote_addr;

  # location / {} Other configurations for the site...

Obtaining the client IP from the header set by nginx in Workerman:

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

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

// Callback when a client connects, i.e., after the TCP three-way handshake
$worker->onConnect = function(TcpConnection $connection) {
    * Callback onWebSocketConnect during the client's websocket handshake
    * Access X_REAL_IP value set by nginx through onWebSocketConnect callback
   $connection->onWebSocketConnect = function(TcpConnection $connection){
        * The connection object does not have a realIP property, so we dynamically add a realIP property to the connection object
        * Remember that PHP objects can have properties added dynamically, you can use your preferred property name
       $connection->realIP = $_SERVER['HTTP_X_REAL_IP'];
$worker->onMessage = function(TcpConnection $connection, $data)
    // Access the actual client IP address directly using $connection->realIP

Obtaining the client IP from the header set by nginx in GatewayWorker:

Add the following code to Events.php:

class Events
   public static function onWebsocketConnect($client_id, $data)
        $_SESSION['realIP'] = $data['server']['HTTP_X_REAL_IP'];
   // .... Other code omitted....

After adding the code, restart GatewayWorker.

By using $_SESSION['realIP'] in the onMessage and onClose methods in Events.php, the actual client IP address can be obtained.

Note: $_SESSION['realIP'] cannot be directly used in onWorkerStart, onConnect, and onWorkerStop in Events.php.