53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
import { Request } from 'express';
|
|
|
|
/**
|
|
* 클라이언트의 실제 IP 주소를 추출합니다.
|
|
*
|
|
* @description
|
|
* Proxy, Load Balancer, CDN 뒤에 있어도 실제 클라이언트 IP를 정확하게 가져옵니다.
|
|
* 다음 순서로 IP를 확인합니다:
|
|
* 1. X-Forwarded-For 헤더 (Proxy/Load Balancer)
|
|
* 2. X-Real-IP 헤더 (Nginx)
|
|
* 3. req.ip (Express 기본)
|
|
* 4. req.socket.remoteAddress (직접 연결)
|
|
* 5. 'unknown' (IP를 찾을 수 없는 경우)
|
|
*
|
|
* @param req - Express Request 객체
|
|
* @returns 클라이언트 IP 주소
|
|
*
|
|
* @example
|
|
* const ip = getClientIp(req);
|
|
* console.log(ip); // '203.123.45.67' or 'unknown'
|
|
*/
|
|
export function getClientIp(req: Request): string {
|
|
// 1. X-Forwarded-For 헤더 확인 (Proxy/Load Balancer 환경)
|
|
// 형식: "client IP, proxy1 IP, proxy2 IP"
|
|
const forwardedFor = req.headers['x-forwarded-for'];
|
|
if (forwardedFor) {
|
|
// 배열이면 첫 번째 요소, 문자열이면 콤마로 split
|
|
const ips = Array.isArray(forwardedFor)
|
|
? forwardedFor[0]
|
|
: forwardedFor.split(',')[0];
|
|
return ips.trim();
|
|
}
|
|
|
|
// 2. X-Real-IP 헤더 확인 (Nginx 환경)
|
|
const realIp = req.headers['x-real-ip'];
|
|
if (realIp && typeof realIp === 'string') {
|
|
return realIp.trim();
|
|
}
|
|
|
|
// 3. Express가 제공하는 req.ip
|
|
if (req.ip) {
|
|
return req.ip;
|
|
}
|
|
|
|
// 4. Socket의 remoteAddress
|
|
if (req.socket?.remoteAddress) {
|
|
return req.socket.remoteAddress;
|
|
}
|
|
|
|
// 5. IP를 찾을 수 없는 경우
|
|
return 'unknown';
|
|
}
|