Nginx/Apache 프록시를 통해 클라이언트의 실제 IP를 얻는 방법은 무엇인가요?
Nginx/Apache를 Workerman의 프록시로 사용할 때, Nginx/Apache는 사실 Workerman의 클라이언트 역할을 합니다. 따라서 Workerman에서 얻는 클라이언트 IP는 Nginx/Apache 서버의 IP일 뿐 실제 클라이언트의 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를 전달하는 데이터를 삽입해야 합니다.
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 / {} 사이트의 다른 설정...
}
Workerman이 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');
/**
* 클라이언트 WebSocket 핸드셰이크 시의 콜백 onWebSocketConnect
* onWebSocketConnect 콜백에서 Nginx를 통해 HTTP 헤더의 X_REAL_IP 값을 얻습니다.
*/
$worker->onWebSocketConnect = function(TcpConnection $connection, $request){
/**
* connection 객체에는 realIP 속성이 없습니다. 여기서 connection 객체에 동적으로 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가 Nginx에서 설정한 헤더에서 클라이언트 IP를 가져오는 방법
Events.php에 아래 코드를 추가합니다.
class Events
{
public static function onWebsocketConnect($client_id, $data)
{
$_SESSION['realIP'] = $data['server']['HTTP_X_REAL_IP'];
}
// .... 다른 코드는 생략합니다....
}
코드를 추가한 후 GatewayWorker를 재시작해야 합니다.
이제 Events.php의 onMessage 및 onClose 메소드에서 $_SESSION['realIP']를 통해 클라이언트의 실제 IP를 얻을 수 있습니다.
주의: Events.php의
onWorkerStart,onConnect,onWorkerStop에서는$_SESSION['realIP']를 직접 사용할 수 없습니다.