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,onConnecteonWorkerStopno Events.php, não é possível usar diretamente$_SESSION['realIP'].