FlexCloud FAQ


* 아파치 Access Log 에서의 IP Logging


일반적인 아파치 로그 설정
LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
%v : 가상호스트명

%h : 리모트 IP



로드밸런서를 거치게 되면 %h 의 리포트 IP가 로드밸런서 IP로 찍히게 됩니다.

LogFormat "%v %{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""

여기서 %h 를 %{X-Forwarded-For}i 로 변경해 주서야 합니다.

HTTP Header 값인 X-Forwarded-For 를 바로 사용하는 것입니다.



- access log 포멧 

포맷

의미

%a

원격지 IP 주소

%A

로컬 IP 주소

%B

HTTP 헤더를 제외하고 전송된 바이트

%b

HTTP 헤더를 제외하고 전송된 바이트. CLF 포맷에서는 , 전송된 것이 없을 경우 0 으로 표시하기 보다는 ‘-‘ 로 표시한다.

%{FOOBAR}e

서버에 의해 지정된 환경변수

%f         

파일 이름

%h         

원격지 호스트

%H                    

요청한 프로토콜

%{Foobar}i

Foobar 의 내용: 클라이언트에서 서버로 요청된 헤더라인으로 예를 들자면, Referer 헤더일 경우 %{Referer}i 로 사용되어 진다. 

%l         

원격지 사용자이름 (이것이 사용되어 지기 위해서는 IdentityCheck 가 반드시 enable 되어져 있어야 한다)

%m                    

요청방식

%{Foobar}o

서버에서 응답되어 지는 HTTP 헤더. 예를들면 :

%{Content-Type}o, %{Last-Modified}o

%p         

요청을 처리하는 서버의 참조적인 포트

%P        

현 요청을 처리하고 있는 아파치 자식 프로세서의 프로세스 ID

%q                     

쿼리 문자열 (쿼리가 있을 경우 “?” 뒤로 쿼리문이 포함되며 그렇지 않을 경우 공백으로 처리된다)

%r         

HTTP 메소드를 포함한 요청의 첫 라인

%s         

HTTP 상태코드. 만약 클라이언트의 요청이 내부적인 리다이렉트를 발생시켰을 경우 %s 는 초기 요청의 상태코드를 %>s 는 최종상태 코드를 포함하게 된다. 일반적으로, %s 의 사용 보다는 %>s 가 유용하다.

%t         

요청한 시간과 날짜 (standard english format)

%{format}t

strftime() function 을 이용한 포맷형식에 따른 시간

[Day/Month/Year:Hours:Minutes:Seconds Time Zone]

%T        

요청을 처리하는데 걸린 시간 (초)

%u         

인증이 요청된 원격 사용자 이름

%U        

요청된 URL

%v         

요청을 처리하는 서버의 참조적인 서버 이름

%V        

UseCanonicalName 설정에 따른 서버 이름






* reverse proxy add forward module로 해결하기


가상서버에서 방문자 IP가 잡히지 않는 문제는 아파치로그 뿐만이 아닌 웹솔루션 소스를 뜯어 고쳐야 하는 것과 사이트 관리상에 상당한 문제점이 발생할 수 있습니다. 

따라서 이러한 문제를 근본적으로 해결할 수 있는 것이 바로 reverse proxy add forward(RPAF)입니다.

이 모듈을 올려주면 이러한 문제가 해결이 되므로 가상서버, VPS, UML에서는 필수적인 모듈입니다.

1. 설치방법 방법은 http://www.just4fun.co.kr/drupal/?q=node/233 에서 소개한 것처럼 하면 됩니다.
wget http://stderr.net/apache/rpaf/download/mod_rpaf-0.6.tar.gz
tar xzvf mod_rpaf-0.6.tar.gz
cd mod_rpaf-0.6
/usr/local/httpd/bin/apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c

2. mod_rpaf-2.0라는 공유객체가 생성이 되면 아파치 모듈에 자동 복사되어 넣어집니다. LoadModue에도 자동 추가 됩니다.(httpd.conf)
LoadModule rpaf_module modules/mod_rpaf-2.0.so

3. 다음을 2번 아래에 추가합니다.
RPAFenable On
RPAFsethostname On
RPAFproxy_ips [내부IP]

여기서 내부IP는 자신의 가상서버의 IP가 아닌 또다른 내부IP입니다. 제생각에는 포워딩을 해주는 프록시 IP같은데, 아파치 로그를 보면 계속 어떤 특정한 IP로 찍히는 것을 확인할 수 있을 것입니다. 그것을 기입합니다. (예를들면 10.0.0.177 또는 192.0.0.20)
RPAFenable On
RPAFsethostname On
RPAFproxy_ips 10.0.0.177

4. 이제 아파치를 재가동하면 정상적으로 IP가 기록되는 것을 로그파일로 확인할 수 있습니다.
5. 로그설정에서 IP(X-Forwarded-For)식으로 2개를 활용하면 IP(실제IP)가 잡힙니다.

*** 간혹 프록시를 이용해서 장난치는 경우도 실제IP를 파악할 수 있습니다


LogFormat "%v %{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" X-Forwarded-For
CustomLog /var/log/apache/www.example.com-xforwarded.log X-Forwarded-For

EX)
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
LogFormat "%v %{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" X-Forwarded-For


* X-Forwarded-For 헤더를 이용한 Apache ACL 설정

이 설정은 추가 모듈을 필요로 하지 않으며, 현재 Apache에서 제공하는 ACL 기능만으로 구현이 가능합니다.


설정 예)
X-Forwarded-For 헤더값으로 넘어오는 IP가 172.21.21.* network인 모든 Client와 192.168.122.111 인 Client만 접속을 허용하고 나머지에 대해서는 접속을 거부(403 access deny) 함.


<Directory "/app/apache/htdocs">

SetEnvIf X-Forwarded-For ^172\.21\.21\.* allow_ip
SetEnvIf X-Forwarded-For ^192\.168\.122\.111 allow_ip
Order deny,allow
Deny from all
Allow from env=allow_ip
< /Directory>

위의 allow_ip는 중복해서 계속 추가해서 쓰면 됩니다.


Cache를 통한 서비스를 제공하다보면 오리진쪽에서는 실제 클라이어트 IP를 일반적인 header나 로그로 확인을 할 수가 없습니다. 이럴때 X-Forwarded-For 를 사용하면 실제 클라이언트 IP확인이 가능합니다.

PHP 코드
<?
$check_ip1 = $_SERVER['HTTP_X_FORWARDED_FOR'];
$check_ip2 = $_SERVER['REMOTE_ADDR'];
echo "HTTP_X_FORWARDED_FOR IP: ".$check_ip1."<br>";
echo "REMOTE_ADDR IP: ".$check_ip2."<br>";
?>
Apache Logformat
LogFormat "%{X-Forwarded-For}i %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined




* Tomcat 의 Access log의 경우

  1. <!-- 아래 Valve를 추가 -->
  2. <Valve className="org.apache.catalina.valves.RemoteIpValve" />
  3. <!-- AccessLogValve를 아래와 같이 수정 -->
  4. <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%{X-Forwarded-For}i %h %l %u %t &quot;%r&quot; %s %b %{User-Agent}i" />

* Nginx 의 경우 nginx.conf
        location ~ \.jsp$ {
            proxy_pass              http://localhost:15000;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header        Host $http_host;
        }







* 언어별 X-Forward-for 헤더 추출 방법.

C#

// Look for a proxy address firstString 
_ip = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
// If there is no proxy, get the standard remote address
If (_ip == "" || _ip.ToLower == "unknown")
_ip = Request.ServerVariables["REMOTE_ADDR"];

PHP

Based on code from OxyScripts.

function GetUserIP() { 
if (isset($_SERVER)) {

if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))

return $_SERVER["HTTP_X_FORWARDED_FOR"];

if (isset($_SERVER["HTTP_CLIENT_IP"]))
return $_SERVER["HTTP_CLIENT_IP"];

return $_SERVER["REMOTE_ADDR"];
}
if (getenv('HTTP_X_FORWARDED_FOR'))

return getenv('HTTP_X_FORWARDED_FOR');

if (getenv('HTTP_CLIENT_IP'))

return getenv('HTTP_CLIENT_IP');

return getenv('REMOTE_ADDR');
}

Java and JSP

String ipaddress = request.getHeader("HTTP_X_FORWARDED_FOR");
if
(ipaddress == null)
ipaddress = request.getRemoteAddr();

ASP/VBScript

ipaddress = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
if ipaddress = ""
then
ipaddress = Request.ServerVariables("REMOTE_ADDR"
)end if

ColdFusion

<CFCOMPONENT> 
<CFIF #CGI.HTTP_X_Forwarded_For# EQ "">
<CFSET ipaddress="#CGI.Remote_Addr#">
<CFELSE>
<CFSET ipaddress="#CGI.HTTP_X_Forwarded_For#">
</CFIF>
</CFCOMPONENT>

Perl

$ip = $req->header('Client-IP') || $req->header('Remote-Addr');
if ($req->header('X-Forwarded-For'))
{ $proxy = $ip; $ip = $req->header('X-Forwarded-For');}

If you know anymore, just ping them in my general direction and they can be added.


출처 : http://blog.syszone.co.kr/3159

출처 : http://crown0047.egloos.com/1150193