Как получить реальный 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'].