BOARD

자료·레퍼런스

PHP 및 그누보드 환경에서 프록시·CDN 고려한 클라이언트 실제 IP 추출 방법

페이지 정보

profile_image
작성자 최고관리자
댓글 0건 조회 16회 작성일 26-09-28 16:50

본문

PHP 및 그누보드 환경에서 프록시·CDN 고려한 클라이언트 실제 IP 추출 방법

프록시 서버나 클라우드플레어(CloudFlare) 환경에서 $SERVER['REMOTEADDR']가 실제 IP 대신 중간 서버 IP를 반환할 때, 실제 방문자 IP를 정확히 식별하고 그누보드 콘텐츠 및 관리자 권한을 제어하는 방법을 안내합니다.

프록시 환경에서 $_SERVER['REMOTE_ADDR']가 실제 IP를 가져오지 못하는 이유

PHP에서 클라이언트의 IP 주소를 확인할 때 흔히 사용하는 $_SERVER['REMOTE_ADDR']는 TCP/IP 레벨에서 요청을 보낸 직접적인 연결 주소를 반환합니다. 일반적인 직접 접속 환경에서는 정상적으로 동작하지만, 프록시 서버나 로드 밸런서(예: NGINX, HAProxy, Cloudflare 등)가 앞단에 배치된 구조에서는 웹 서버가 클라이언트와 직접 통신하지 않고 중간 서버를 거쳐 요청을 받게 됩니다.

이로 인해 $_SERVER['REMOTE_ADDR']는 실제 방문자의 IP 주소가 아니라 요청을 전달한 프록시 서버나 로드 밸런서의 내부 IP 주소를 반환하게 됩니다. 따라서 프록시 환경에서 실제 방문자의 IP를 정확히 식별하려면 HTTP_X_FORWARDED_FOR나 HTTP_CF_CONNECTING_IP 같은 별도의 HTTP 헤더를 함께 확인해야 합니다.

프록시 환경에서 실제 클라이언트 IP 추출 방법

PHP 환경에서 프록시 서버, 로드 밸런서, CDN(예: CloudFlare) 등을 경유하는 경우, 기본 변수인 $_SERVER['REMOTE_ADDR']를 사용하면 방문자의 실제 IP가 아닌 중간 프록시 서버의 IP 주소가 조회됩니다. 이를 해결하기 위해 HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR 등의 헤더를 우선순위별로 확인하여 실제 클라이언트 IP를 추출할 수 있습니다.

1. 우선순위 로직을 적용한 IP 추출 패턴

다양한 서버 환경과 프록시 헤더를 검사하여 실제 IP를 확보하는 기본적인 PHP 코드 구현 방식은 다음과 같습니다.

function getUserIP() {
 // CloudFlare 환경을 사용하는 경우 CF-Connecting-IP 반영 가능
 if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
 $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
 $_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
 }
 
 $client = @$_SERVER['HTTP_CLIENT_IP'];
 $forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
 $remote = $_SERVER['REMOTE_ADDR'];
 
 if (filter_var($client, FILTER_VALIDATE_IP)) {
 $ip = $client;
 } elseif (filter_var($forward, FILTER_VALIDATE_IP)) {
 $ip = $forward;
 } else {
 $ip = $remote;
 }
 return $ip;
}

또한 간단한 조건문이나 삼항 연산자를 활용하여 순차적으로 값을 확인할 수 있습니다.

$client_ip = isset($_SERVER['HTTP_CLIENT_IP'])? $_SERVER['HTTP_CLIENT_IP']: (isset($_SERVER['HTTP_X_FORWARDED_FOR'])? $_SERVER['HTTP_X_FORWARDED_FOR']: $_SERVER['REMOTE_ADDR']);

2. 콤마(,)로 구분된 다중 IP 처리

HTTP_X_FORWARDED_FOR 헤더에는 프록시 체인을 거치면서 여러 개의 IP가 콤마(,)로 구분되어 담길 수 있습니다. (예: 203.0.113.10, 10.0.0.1) 이 경우 목록 중 첫 번째 값이 실제 클라이언트의 IP이므로, 다음과 같이 분리하여 처리해야 합니다.

if (count(explode(',', $client_ip)) == 2) {
 $ip0 = explode(',', $client_ip);
 $client_ip = $ip0[0];
}

3. 적용 시 주의사항

  • 사용자가 사용하는 특정 프록시 서버의 헤더 설정이나 네트워크 구성에 따라 추출 로직이 달라질 수 있습니다.
  • 프록시 환경에서 단순히 REMOTE_ADDR만 사용할 경우 서버 IP나 프록시 IP가 수집되므로, 관리자 접근 제어 및 방문자 로그 기록 시 위와 같은 우선순위 로직을 적용해야 합니다.

HTTPXFORWARDED_FOR 헤더의 콤마 구분자 IP 분리 방법

프록시 서버나 로드 밸런서, CDN 환경을 거치며 요청이 전달될 때 HTTP_X_FORWARDED_FOR 헤더에는 여러 개의 IP 주소가 콤마(,)로 나열되어 포함될 수 있습니다. 이 경우 첫 번째로 나오는 IP가 실제 클라이언트의 IP이며, 그 뒤에 나오는 IP들은 경유한 프록시 서버들의 IP입니다.

콤마 구분자 처리 및 첫 번째 IP 추출 로직

여러 IP가 쉼표로 구분되어 있을 때 explode 함수를 사용하여 첫 번째 실제 클라이언트 IP를 정확히 분리할 수 있습니다.

$client_ip = isset($_SERVER['HTTP_CLIENT_IP'])? $_SERVER['HTTP_CLIENT_IP']: (isset($_SERVER['HTTP_X_FORWARDED_FOR'])? $_SERVER['HTTP_X_FORWARDED_FOR']: $_SERVER['REMOTE_ADDR']);

if (count(explode(',', $client_ip)) == 2) {
 $ip0 = explode(',', $client_ip);
 $client_ip = $ip0[0];
}

또한 문자열 내에 콤마가 포함되어 있는지 확인하고 분할하는 반복문 기반의 정제 처리 예시는 다음과 같습니다.

if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',')!== false) {
 $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
 foreach ($iplist as $ip) {
 if (validate_ip($ip)) {
 return $ip;
 }
 }
}

주의 사항 및 다음 행동

  • HTTP_X_FORWARDED_FOR 헤더는 클라이언트가 임의로 조작할 수 있는 HTTP 헤더이므로, 헤더 값이 설정된 위치와 방식을 신뢰할 수 있는 환경인지 먼저 확인해야 합니다.
  • 프록시 서버의 설정이나 구성에 따라 추출 로직이 달라질 수 있으므로 적용 후 실제 접속 IP와 일치하는지 확인하는 검증 단계를 거쳐야 합니다.

CloudFlare 및 프록시 환경에서 실제 클라이언트 IP 추출 방법

클라우드플레어(CloudFlare) CDN이나 프록시 서버, 로드 밸런서를 경유하는 환경에서는 PHP의 기본 변수인 $_SERVER['REMOTE_ADDR']를 사용할 경우 실제 방문자의 IP가 아닌 프록시 서버의 IP 주소가 반환됩니다. 이를 해결하기 위해 표준이 아닌 전용 헤더와 우선순위 로직을 적용해야 합니다.

1. CloudFlare 및 프록시 환경의 IP 추출 원리

  • CloudFlare 환경: 클라우드플레어는 실제 방문자 IP를 전달하기 위해 HTTP_CF_CONNECTING_IP 헤더를 제공합니다.
  • 프록시 및 로드 밸런서 환경: 프록시 체인을 통과할 때 원래 클라이언트 IP를 기록하는 HTTP_X_FORWARDED_FOR 헤더를 활용합니다. 이 헤더는 콤마(,)로 여러 IP가 구분되어 전달될 수 있으며, 첫 번째 값이 실제 클라이언트의 IP입니다.

2. 실제 IP 추출을 위한 PHP 코드 구현 패턴

getUserIP() 함수를 구현하여 클라우드플레어 전용 헤더(HTTP_CF_CONNECTING_IP)와 프록시 헤더를 순서대로 검증하고 필터링할 수 있습니다.

function getUserIP() {
 // Get real visitor IP behind CloudFlare network
 if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
 $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
 $_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
 }
 $client = @$_SERVER['HTTP_CLIENT_IP'];
 $forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
 $remote = $_SERVER['REMOTE_ADDR'];
 
 if (filter_var($client, FILTER_VALIDATE_IP)) {
 $ip = $client;
 } elseif (filter_var($forward, FILTER_VALIDATE_IP)) {
 $ip = $forward;
 } else {
 $ip = $remote;
 }
 return $ip;
}
$ip4 = getUserIP();

또한 콤마로 구분된 HTTP_X_FORWARDED_FOR 값을 처리할 때는 아래와 같이 첫 번째 IP를 분리하여 정확한 값을 확보할 수 있습니다.

$client_ip = isset($_SERVER['HTTP_CLIENT_IP'])? $_SERVER['HTTP_CLIENT_IP']: (isset($_SERVER['HTTP_X_FORWARDED_FOR'])? $_SERVER['HTTP_X_FORWARDED_FOR']: $_SERVER['REMOTE_ADDR']);

if (count(explode(',', $client_ip)) == 2) {
 $ip0 = explode(',', $client_ip);
 $client_ip = $ip0[0];
}

3. 적용 시 주의사항

  • 사용자가 사용하는 특정 프록시 서버의 헤더 설정에 따라 추출 로직이 달라질 수 있습니다.
  • 프록시 헤더(X-Forwarded-For 등)는 임의로 조작될 수 있는 값이므로, 신뢰할 수 있는 프록시 및 CDN 환경에서만 사용하는 것이 안전합니다.

그누보드에서 실제 클라이언트 IP 기반 콘텐츠 접근 제어 방법

프록시 서버나 CDN(예: 클라우드플레어) 환경에서는 기본 서버 변수인 $_SERVER['REMOTE_ADDR']가 실제 방문자의 IP가 아닌 프록시 서버의 IP를 반환합니다. 따라서 올바른 IP 추출 로직을 거친 뒤 관리자 권한 및 특정 IP 조건을 결합하여 콘텐츠를 제어해야 합니다.

1. 실제 클라이언트 IP 추출하기

프록시 환경에서는 HTTP_X_FORWARDED_FOR 헤더를 확인해야 하며, 콤마(,)로 여러 IP가 구분되어 전달될 경우 첫 번째 값을 실제 클라이언트 IP로 사용합니다.

<?php
// HTTP_X_FORWARDED_FOR 헤더를 쉼표로 분리하여 첫 번째 IP 추출
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
 $ipList = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
 $client_ip = trim($ipList[0]);
} else {
 $client_ip = $_SERVER['REMOTE_ADDR'];
}
?>

2. 그누보드에서 관리자 및 특정 IP 조건에 따른 콘텐츠 제어 예시

추출한 $client_ip 변수와 그누보드의 관리자 판별 변수($is_admin), 회원 정보($member['mb_id'])를 조건문으로 조합하여 특정 사용자에게만 콘텐츠를 노출하거나 제한할 수 있습니다.

<?php
// 특정 IP, 최고/부관리자 여부, 특정 회원 아이디 조건을 모두 만족할 때 콘텐츠 제어
if ($client_ip == "허용할_IP" && $is_admin && $member['mb_id'] == '특정회원') {
 echo "관리자 전용 콘텐츠입니다.";
}
?>

상황별 IP 추출 및 제어 판단 기준

내 상황우선할 판단다음 행동
프록시나 로드밸런서를 거쳐 접속 시 REMOTE_ADDR가 내부 IP로 조회되는 경우HTTP_X_FORWARDED_FOR 헤더의 우선순위 검사 적용콤마(,) 구분자를 분리하여 첫 번째 IP를 추출하는 로직 구현
클라우드플레어(CloudFlare) CDN을 적용하여 방문자 IP가 가려지는 경우HTTP_CF_CONNECTING_IP 헤더 존재 여부 확인 및 최우선 반영전용 헤더 값을 $_SERVER['REMOTE_ADDR']에 덮어쓰거나 별도 함수로 격리
그누보드에서 특정 IP 및 관리자 권한에 따라 콘텐츠 제어를 수행하려는 경우확보한 실제 클라이언트 IP 변수와 $is_admin, $member['mb_id'] 조건 조합조건문 검증 로직을 거쳐 접근 제어 및 방문자 기록 기능 연동

실전 FAQ

Q. HTTP_X_FORWARDED_FOR 헤더 값에 여러 IP가 콤마로 섞여 있을 때 실제 사용자 IP를 어떻게 확정하나요?

  • 답변: 프록시 체인을 거치며 누적된 IP 목록 중 가장 첫 번째에 위치한 IP가 최초 요청을 보낸 실제 클라이언트의 IP입니다. explode(',', $client_ip)를 통해 배열로 분할한 뒤 첫 번째 인덱스 값([0])을 가져와야 합니다.

Q. 클라우드플레어 환경에서 그누보드 접속자 로그나 관리자 IP 검증이 정상 동작하지 않을 때 대안은 무엇인가요?

  • 답변: 클라우드플레어는 표준 헤더 대신 HTTP_CF_CONNECTING_IP를 통해 실제 IP를 전달합니다. common.php 상단 또는 별도 클래스 구조를 통해 해당 헤더 값을 기본 서버 변수에 반영하는 전처리 로직을 추가하여 해결할 수 있습니다.

참고자료

기타 참고자료

댓글목록

등록된 댓글이 없습니다.