Apache Jakarta(이하 Web Server)와 Apache Tomcat(이하 WAS)로 구성되어 있는 홈페이지가 꾀 존재하는 것으로 알 고 있다.

그런데 이런 홈페이지 중에 금저의 이유로 L4를 쓰지 못해 L4와 유사 기능을 하는 소프트웨어를 설치하여(HA-Proxy) 로드발란싱과 Fail-Over 기능을 대체하고 있습니다.


그런데 HA-Proxy를 거쳐서 Web Server를 통하여 ajp1.3으로 WAS와 연동하는 구조에서 Web Server 까지는 Client의 실제 IP를 X-Forwarded-For라는 X-Host Header 정보로 확인이 가능하지만 Web Server에서 WAS로 보내지는 Reqeust에서는 이 X-Host Header 정보가 보내지지 않아 IP Filter 작업을 할 때 애를 먹게 되는 경우가 있습니다.



구성도시스템 구성도


위 구성도에서 보면 HA-Proxy1에서 Web Server와 통신할 때에는 HTTP 통신이기 때문에 Client의 실제 IP를 확인할 수 있습니다. 하지만 HA-Proxy2에서는 Web Server와 WAS의 통신이 AJP 1.3이라는 TCP/IP통신을 하게 되면서 실제 클라이언트 IP가 아닌 Web Sever에서 AJP1.3 통신을 하기위한 IP가 Client IP가 되어 WAS에서 확인하게 됩니다.


WAS에서는 Client IP가 Web Server가 됨WAS에서는 Client IP가 Web Server가 됨


이 처럼 HA-Proxy와 같은 소프트웨어 로드밴런싱 도구를 사용하는 경우 WAS에서 Client IP를 알 수 있는 방법은 없습니다. 해서 사용되는 것이 

X-Forwarded-For라는 X-Host 헤더정보 입니다. 사실 Web Server의 입장에서도 WAS와 동일하게 HA-Proxy1이 있는 Server가 Client가 됩니다. 해서 Web Server에서 로그를 남길 때 %h또는 %{c}a 를 할 때 HA-Proxy 서버의 IP가 확인 됩니다. 하지만 %{X-Forwarded-For}를 하면 실제 Client IP가 확인되게 됩니다. 물론 HA-Proxy에서 X-Forwarded-For 헤더정보로 Client IP를 실어서 보낼 수 있도록 설정을 미리 해두어야 합니다.


오늘은 HA-Proxy에서 X-Forwarded-For 헤더로 Client IP를 더하여서 Web Server로 보내고 있다고 가정하고 Web Server의 설정과 WAS의 설정을 확인해 보도록 하겠습니다.


사실 Web Server도 X-Forwarded-For 헤더를 WAS로 보내는 설정만 하면 됩니다. 문제는 mod_jk.so 파일의 버전입니다. mod_jk.so를 추가하고 <IfModule jk_module>에서 JkOptions라는 곳에 옵션으로 +ForwardPhysicalAddress라는 명령어를 추가해야 이 명령어를 추가하면 에러가 발생하는 경우를 보게 됩니다. 그래서 mod_jk의 버전별 ChangeLog를 확인해 보았는데 mod_jk 1.2.39버전부터 ForwardPhysicalAddress 옵션을 JkOptions로 사용할 수 있음을 보게 됩니다. 해서 mod_jk 소스를 최신버전으로 다시 받아서 compile하고 mod_jk.so파일을 변경해 주었습니다.


다음은 mod_jk소스를 받아서 compile하는 과정입니다.


1. 최신 mod_jk.so 컴파일 하기

우선 mod_jk 최신 버전을 다운로드 받습니다(현재 2014-04-22일 최고 버전은 1.2.40 입니다).

[root@localhost ~]# wget http://mirror.apache-kr.org/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.40-src.tar.gz


다운로드된 파일을 압축을 해제합니다.

[root@localhost ~]# tar -zxvf tomcat-connectors-1.2.40-src.tar.gz


압축해제된 디렉토리의 native 폴더로 이동합니다.

[root@localhost ~]# cd tomcat-connectors-1.2.40-src/native/


configure 파일에 apxs위치를 설정해 줍니다. 

[root@localhost native]# ./configure --with-apxs=${webserver.home:web server 설치 디렉토리}/bin/apxs


make 또는 make install 합니다. make install 하게 되면 아파치 홈 디렉토리의 /modules 폴더에 자동을 mod_jk.so파일이 복사된다고 하더군요.

[root@localhost native]# make


[root@localhost native]# make install


하지만 혹시 모르니 그냥 mod_jk.so파일을 아파치 홈 디렉토리의 /modules 폴더에 복사합니다.


자 이제 최신 mod_jk.so는 구했습니다. 다음은 아파치 설정을 하도록 하겠습니다.


2.아파치 설정하기

web server 홈 디렉토리의 설정파일로 이동합니다. 저는 Apache Jakarta(Web Server)를 사용하고 있기 때문에 ${webserver.home}/conf/httpd.conf 파일을 수정하도록 하겠습니다. httpd.conf 파일에 LoadModule하는 부분 마지막에 다음을 추가 합니다.


LoadModule jk_module modules/mod_jk.so


그리고 <IfModule jk_module>에 JkOptions를 추가합니다.


<IfModule jk_module>

        JkWorkersFile ...

        JkShmFile ...

        JkLogFile ...

        JkOptions +ForwardKeySize +ForwardPhysicalAddress +ForwardURIProxy

        JkLogLevel error

</IfModule>


이렇게 JKOptions에 +ForwardKeySize +ForwardPhysicalAddress +ForwardURIProxy 를 추가 합니다. JkOptions에는 어떤 값이 있고 의미하고 있는 것이 무엇인지는 아래 링크를 참조해주시기 바랍니다.


>>JkOptions링크 클릭<<


자 이렇게 한 후에는 한 가지 추가적으로 더 해줘야 할  것이 있습니다. 바로 mod_remoteip.so 파일을 추가해주는 것입니다. 이미 httpd.conf에는 mod_remoteip.so가 있습니다. 주석처리 되어 있는 것을 삭제해 주시면 됩니다. 그리고 이 또한 설정을 해줘야 합니다. 다음은 

<IfModule remote_module>에 대한 설정입니다.


<IfModule remoteip_module>

    RemoteIPHeader X-Client-IP

    RemoteIPInternalProxy 127.0.0.1

</IfModule>


remoteip_module에 대한 설정은 다음 링크를 확인해 주시기 바라빈다. X-Forwarded-For에 대한 내용을 jk_module로 WAS에 보내려면 위와 같이 RemoteIPHeader에 X-Client-IP라고 입력하고 RemoteIPInternalProxy에는 127.0.0.1을 입력합니다.


>>mod_remoteip 링크<<


자 이 것으로 Web Server에서는 모든 설정이 끝났습니다. 이제 WAS에서 request.getHeader("x-forwarded-for")로 Client IP를 확인해 보면 정상적인 Client IP가 확인되게 됩니다.


HA-Proxy에서 X-Forwarded-For를 구성하는 방법은 다음 링크 또는 X-Forwarded-For on HA-Proxy를 구글링 해보시기를 추천듭니다.


>>HA-Proxy 링크<<<


감사합니다.



Posted by gofly