Tag Archives: AJP

ProxyAJP를 이용한 Apache2 + Tomcat 연동시 중대한 보안 문제

– 2010.08.03 추가
아래에 쓴글은 정상적으로 작동하지 않으며 다음의 방법이 보안을 위한 정상적인 방법입니다.


ProxtRequests 설정을 Off로 변경 :
외부 요청이 차단됨, 이후에도 ProxyPass, ProxtPassMatch등 정상 사용 가능


– 기존의 글

기존에 다음과 같은 ProxyAJP를 이용한 Apache2와 Tomcat의 연동법에 대한 글을 썼었습니다.

Proxy AJP + mod_rewrite를 이용하여 Apache 2.2 + Tomcat 완벽 연동하기
Apache 2 Proxy AJP를 이용한 호스팅 환경에서의 완벽 연동

하지만 위의 방법들에 중대한 보안 문제가 있다는 것을 알게 되었습니다. 어느 순간부터인가 서버에 엄청난 트래픽이 유입되더군요.

저는 단순히 DDOS공격인줄 알았습니다. IP는 정체를 알수 없이 전세계에서 들어오더군요. 사실상 끝나기를 기다리며 내 서버에는 사실상 영리목적의 사이트가 없는데 무엇이 목적일까 고민하게 되었습니다.

우선 쌓이는 로그가 매우 특이한것을 알수 있었습니다. 로그는 대충 다음과 같은 형식이었습니다.

[code]202.109.175.224 – – [17/Apr/2009:21:17:39 +0900] “GET http://www.dfwater.com/Index.asp HTTP/1.1” 503 28 “http://www.dfwater.com/” “Mozilla/4.0 (compatible; MSIE 6.0; Windows 5.1)”
84.16.227.121 – – [17/Apr/2009:21:17:35 +0900] “GET http://www.google.com/ie?q=puts+inurl:?p%3D&hl=en&num=100&start=200&sa=N HTTP/1.0” 302 335 “http://www.google.com/ie?q=puts+inurl:?p%3D&hl=en&num=100&start=200&sa=N” “Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)”
64.91.72.166 – – [17/Apr/2009:21:17:39 +0900] “CONNECT 205.188.251.26:443 HTTP/1.0” 200 – “-” “-“
61.160.211.12 – – [17/Apr/2009:21:17:36 +0900] “GET http://www.kiss888mu.cn HTTP/1.1” 500 3847 “http://www.baidu.com” “Mozilla/4.0 (compatible; MSIE 6.0; Windows 5.1)”
118.69.166.3 – – [17/Apr/2009:21:17:39 +0900] “GET http://69.147.112.211/config/isp_verify_user?l=mmg&p=0011 HTTP/1.0” 200 26 “-” “-“
208.70.78.177 – – [17/Apr/2009:21:17:36 +0900] “GET http://www.google.com/ie?as_q=inurl:/guestbook.html+tampa+fl+gay+life+and+dating&num=100&hl=en HTTP/1.0” 302 355 “http://www.google.com/ie?as_q=inurl:/guestbook.html+tampa+fl+gay+life+and+dating&num=100&hl=en” “Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8b2) Gecko/20050224 Firefox/1.0+”
78.30.203.105 – – [17/Apr/2009:21:17:39 +0900] “GET http://inmarket73.ru/forum/index.php?s=fb2bade970f814c6d66c67f414a2328b&act=Reg&CODE=image&rc=35f728107e6ae6292a22c4e6f16634ac&p=3 HTTP/1.0” 200 68 “http://inmarket73.ru/forum/index.php?act=Reg&CODE=image&rc=7f430230e31d334872d1b5136a57b9ce&p=1” “Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1)”
94.76.199.2 – – [17/Apr/2009:21:17:36 +0900] “GET http://superschurke.de/comments/feed/ HTTP/1.1” 404 809 “-” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)”[/code]

로그가 좀 지저분 합니다만 형식이 다음과 같다는것만 보시면 됩니다. 요청이 GET 메서드 이후에 http로 시작하는 것을 알수 있습니다. 그것도 전혀 쌩뚱 맞은 도메인과 호스트에 요청을 합니다.

이것이 왜 이상하냐면 보통의 브라우저는 요청을 할때 다음과 같이 합니다. theeye.pe.kr/index.html의 요청이 있다면 DNS에 질의 하여 theeye.pe.kr 도메인의 호스트 IP를 알아낸 이후에 그곳에 접속하여 GET /index.html 과 같은 방법으로 요청을 하게 됩니다.

위와 같은 방법은 마치 여의도에 가서 “롯데월드가 어딧나요?” 라고 물어보는 꼴이 되는 것입니다.

왜 저런 요청이 자꾸 들어오는 것인지 궁금하여 서버에 다음과 같이 테스트를 해보았습니다.

[code]telnet theeye.pe.kr 80
GET http://www.naver.com[/code]
자, 상식적으로 잘못된 요청이라고 나와야 하지만 정상적으로 페이지가 출력됩니다. 아니 왜 내 서버에서 엉뚱한 사이트의 요청을 처리해 주는 것이지!?

이제 여의도에 가서 “롯데월드가 어딧나요?” 라고 물었더니 상대방이 자기 차에 태워 롯데월드에 데려다 주었습니다.

친절한 사람이군요;;; 근데 문제가, 이걸 악용해서 소문이 나서 세상의 모든 사람이 이 친절한 사람에게 와서 자신이 가고싶은 곳이 어딧는지를 물어본다는 것이 문제가 됩니다.

서버가 엉뚱한 요청을 받아 대리 요청후에 결과를 되돌려 주는 문제는 일전의 Proxy설정의 잘못이었습니다.

ProxyAJP설정을 별다른 보안 절차 없이 설정하게 되면 이 세상 모든 http 요청의 IP세탁 시스템으로 둔갑되어질 수 있습니다.

이문제를 해결하기 위해서는 간단하게 Proxy 요청은 로컬호스트에서만 가능하게 설정하시면 됩니다.

[code]<Proxy *>
Order Deny,Allow
Deny from all
Allow from localhost
</Proxy>[/code]
간단하게 해결되었죠? Proxy 설정을 하시고 서버를 운영하시는 분들은 다른 호스트로의 요청을 해보시기 바랍니다.

에러없이 요청이 정상처리 된다면, 이제 표적이 되기전에 설정을 조금 손보시기 바랍니다.

첨언 : 추가로 로그들을 쭉 분석해 봤는데, 위와 같은 방법을 사용하는 이유는 특정 사이트의 검색요청을 계속하여 검색랭킹을 올린다거나, 추천사이트의 어뷰징 혹은 사이트 페이지뷰를 높이는데 사용되어지는 듯 싶습니다.

Proxy AJP + mod_rewrite를 이용하여 Apache 2.2 + Tomcat 완벽 연동하기

블로그 글에 자꾸 반말/존칭이 섞여가는거 같아 껄끄럽긴 하지만 이번에는 존댓말로 써봅니다;;

여러분의 JAVA/JSP는 어떤 WAS에서 돌리고 계신가요? 톰캣을 쓰신다고요?

그럼 웹서버는 아파치를 사용하시겠군요. 연동을 위해 톰캣 사이트에서 받을 수 있는 mod_jk를 많이들 쓰실것입니다.

하지만 아파치 2.2.x에서 제공하는 Proxy AJP를 사용하면 매우 깔끔하게 연동을 할 수 있습니다.

톰캣은 설치가 되어 정상적으로 동작하고 있는 상황이라 가정하고 아파치 설정만을 적어보겠습니다.

[이곳]에서 가장 최신의 아파치 2.2 버젼을 다운받습니다. 압축을 풀고 컴파일을 합니다.

설정(쓰레드 방식)
[code][root@Theeye src]$ CC=”gcc” CFLAGS=”-O2″ ./configure –prefix=/usr/local/httpd –enable-so –enable-proxy-ajp –enable-cgi –enable-rewrite –enable-speling –enable-usertrack –enable-deflate –enable-ssl –enable-cache –enable-disk-cache –enable-expires –enable-file-cache –enable-headers –enable-mem-cache –enable-mime-magic –enable-proxy –enable-mods-shared=all –with-mpm=worker[/code]
설정(프로세스 방식)
[code][root@Theeye src]$ CC=”gcc” CFLAGS=”-O2″ ./configure –prefix=/usr/local/httpd –enable-so –enable-proxy-ajp –enable-cgi –enable-rewrite –enable-speling –enable-usertrack –enable-deflate –enable-ssl –enable-cache –enable-disk-cache –enable-expires –enable-file-cache –enable-headers –enable-mem-cache –enable-mime-magic –enable-proxy –enable-mods-shared=all –with-mpm=prefork[/code]
컴파일
[code][root@Theeye src]$ make
[root@Theeye src]$ make install
[/code]

아파치가 설치된 디렉토리의 conf/httpd.conf 파일을 열어 다음의 두가지가 정상적으로 존재하는지 확인합니다.
[code]LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule rewrite_module modules/mod_rewrite.so[/code]

그리고 마지막쯤에 있는 가상호스팅 관련 설정을 인클루드 하도록 설정합니다.
[code]Include conf/extra/httpd-vhosts.conf[/code]

아파치 설치 디렉토리의 conf/extra/httpd-vhost.conf 파일을 열어 가상호스트를 추가합니다.
[code]<VirtualHost *:80>
    ServerAdmin your@emailhere
    DocumentRoot /var/www/html
    ServerName theeye.pe.kr
    ErrorLog logs/theeye.pe.kr-error_log
    CustomLog logs/theeye.pe.kr-access_log common


    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} \.(htm|html|xhtml|js|css|jpg|gif|png|swf)$
    RewriteRule (.*) – [L]
    RewriteRule (.*) ajp://localhost:8009$1 [P]
</VirtualHost>[/code]
위와같은 rewrite를 통한 설정은 htm, html, xhtml, js, css, jpg, gif, png, swf 확장자를 가진 요청은 아파치가 처리하도록 하고 나머지는 톰캣이 처리하도록 합니다. 원하시는 확장자를 마음껏 추가하셔도 됩니다.

톰캣이 설치된 디렉토리의 conf/server.xml의 설정을 변경합니다. Connector설정을 확인합니다.
[code]<Connector port=”8009″ protocol=”AJP/1.3″ maxThreads=”150″ minSpareThreads=”25″
    maxSpareThreads=”75″ enableLookups=”false” redirectPort=”8443″ acceptCount=”100″
    debug=”0″ connectionTimeout=”20000″ disableUploadTimeout=”true” URIEncoding=”UTF-8″ />[/code]

아파치 가상호스트에 지정한것과 동일한 호스트를 설정합니다.
[code]<Host name=”theeye.pe.kr” debug=”0″ appBase=”/var/www/html” unpackWARs=”true” autoDeploy=”true” xmlValidation=”false” xmlNamespaceAware=”false”>
<Context path=”” docBase=”/var/www/html” debug=”0″ reloadable=”false” crossContext=”true” />
</Host>[/code]

자, 이제 아파치와 톰캣의 설정이 모두 끝났습니다. 위와 같이 사용하시면 아파치에서 처리할 파일과 톰캣이 처리할 파일들을 따로 분리할 필요도 없으며 확장자에 따라 정확히 아파치와 톰캣이 분산 처리를 하게 됩니다.

정적인 파일들을 톰캣이 처리할 필요는 없으니깐요^^

추가로 특정 호스트에게만 오픈하는 관리자 페이지거나 개발서버일 경우 다음과 같이 접근 가능 아이피를 지정할 수 있습니다.

[code]<VirtualHost *:80>
    ServerAdmin your@emailhere
    DocumentRoot /var/www/html
    ServerName theeye.pe.kr
    ErrorLog logs/theeye.pe.kr-error_log
    CustomLog logs/theeye.pe.kr-access_log common


    RewriteEngine On
    RewriteCond !%{REMOTE_ADDR} ^127\.0\.0\.1$
    RewriteRule ^.*$ – [F]
    RewriteCond %{REQUEST_FILENAME} \.(htm|html|xhtml|js|css|jpg|gif|png|swf)$
    RewriteRule (.*) – [L]
    RewriteRule (.*) ajp://localhost:8009$1 [P]
</VirtualHost>[/code]

127.0.0.1 아이피를 가진 호스트가 아니라면 아파치에서 바로 에러페이지를 출력하게 됩니다.

위의 방법을 사용할 경우 보안 문제가 있으니 [ProxyAJP를 이용한 Apache2 + Tomcat 연동시 중대한 보안 문제]을 참고하세요