iptables와 mod_security 연동을 통한 ip 차단

by ADMINPLAY posted Sep 15, 2010
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄

작성자: 주인장 디지문
(http://www.digimoon.net/)


참고 링크:
http://free4u.wo.tc/weblog/11278

원문 링크:
http://spamcleaner.org/en/misc/modsec2ipt.html


우선 이런 좋은 팁을 소개해 주신 http://free4u.wo.tc 의 님께 감사의 뜻을 전합니다.

서버를 운영하면서 한 때 tcp 80번 포트를 목표로 한 Cache Control Attack을 받은 적이 있습니다.
아파치 로그에 아래와 같은 로그가 마구마구 기록되면서 말이죠.

xx.xx.xx.xx - - [13/Jun/2009:16:31:57 +0900] "GET /zbxe/ HTTP/1.1" 302 281 "http://www.foobar.com" "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; MyIE 3.01)Cache-Control: no-store, must-revalidate" www.foobar.com KR
xx.xx.xx.xx - - [13/Jun/2009:16:31:57 +0900] "GET /zbxe/ HTTP/1.1" 302 281 "http://www.foobar.com" "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; MyIE 3.01)Cache-Control: no-store, must-revalidate" www.foobar.com KR
xx.xx.xx.xx - - [13/Jun/2009:16:31:57 +0900] "GET /zbxe/ HTTP/1.1" 302 281 "http://www.foobar.com" "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; MyIE 3.01)Cache-Control: no-store, must-revalidate" www.foobar.com KR
xx.xx.xx.xx - - [13/Jun/2009:16:31:57 +0900] "GET /zbxe/ HTTP/1.1" 302 281 "http://www.foobar.com" "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; MyIE 3.01)Cache-Control: no-store, must-revalidate" www.foobar.com KR
--------------- ( 이 하 생 략 ) -------------------

 Cache Control Attack은 DDOS 공격의 일종인데 2008년 하반기부터 기승을 부리기 시작한 비교적 최근의 공격 트렌드 방식입니다. 특징이 여타 DDOS 공격에 비해 bps와 pps 수치가 그다지 높지 않은 편임에도 불구하고 CPU와 메모리 자원을 거의 full로 소진시킨다는 점입니다. 이런 까닭에 네트워크 모니터링 장비에서 쉽사리 포착이 되지 않는 면이 있습니다. 공격받을 당시 pps 수치는 최대치가 15000 정도였고 그 외에 간헐적으로 공격이 들어올 때에는 5000-10000 정도에 달하는 수준이었습니다. 이 정도는 평상시 대용량 파일을 업/다운로드할 때에도 충분히 발생할 수 있는 수치인지라 Layer3~4 장비 단에서 공격 여부를 검출해 내기가 어려운 면이 있습니다.
 그래서 http 헤더까지 분석하여 막을 필요가 있는데요. 위 로그에 나온 바와 같이 아파치 로그의 User Agent 란에 "Cache-Control: no-store, must-revalidate" 라는 문자열을 발생시키는 접근에 대해서 mod_security 웹방화벽에 의해 해당 패턴의 접근을 필터링하도록 설정하고 해당 IP를 자동으로 iptables에 등록시켜 tcp 80 포트로의 접근을 차단하는 방법을 스크립트로 구현 가능하지 않을까 평소에도 궁리를 하던 부분이었는데 이번에 우연찮게 원하던 방법을 구현하는 perl 스크립트에 대해 정보를 구할 수 있었습니다.

 
 http://spamcleaner.org/en/misc/modsec2ipt.html 에서 배포하고 있는 perl 스크립트입니다. 설치 및 운영에 관한 메뉴얼을 영문으로 자세하게 소개하고 있으므로 처음 보시는 분들도 적용하는데 무리 없을 겁니다.

 
 웹페이지 최하단에 첨부되어 있는 modsec2ipt.tgz 파일을 먼저 받습니다. 압축을 풀어보면 내용물은 아래와 같습니다.

[root@localhost:~]# wget http://spamcleaner.org/en/misc/modsec2ipt.tgz
[root@localhost:~]# tar xvfz modsec2ipt.tgz
[root@localhost:~]# cd modsec2ipt
[root@localhost:~]# ls -lh
합계 12K
-rw-r--r-- 1 root root  422 2009-01-10 06:18 modsec2ipt
-rwxr-xr-x 1 root root 1.2K 2009-04-07 22:27 modsec2ipt.pl
-rwx------ 1 root root 1.6K 2009-04-07 22:27 modsec2ipt_srv.pl
[root@localhost:~]#


 보안을 위해 modsec2ipt.pl 파일을 웹으로 접근할 수 없는 경로에 위치시키고 mod_security에 의해 실행 가능하도록 nobody나 apache 소유권을 줍니다. 필자의 경우 /usr/local/apache 에 아파치를 설치해서 사용하고 있어서 바이너리 파일이 위치해 있는 /usr/local/apache/bin에 넣어서 사용하고 있습니다.

[root@localhost:/usr/local/apache/bin]# pwd
/usr/local/apache/bin
[root@localhost:/usr/local/apache/bin]# ls -lh modsec2ipt.pl
-rwxr-xr-x 1 nobody nobody 1.1K  6월 18 11:55 modsec2ipt.pl
[root@localhost:/usr/local/apache/bin]#


 modsec2ipt_srv.pl 파일을 /usr/bin 디렉토리에 넣습니다.

[root@localhost:/usr/bin]# pwd
/usr/bin
[root@localhost:/usr/bin]# ls -lh modsec2ipt_srv.pl
-rwx------ 1 root root 1.7K  6월 18 12:24 modsec2ipt_srv.pl
[root@localhost:/usr/bin]#


 modsec2ipt_srv.pl 파일을 편집기로 열어보면 아래와 같이 상단부에 로그 파일 경로가 지정되어 있습니다(붉은색 부분). 기본값으로는 /var/log/modsec2ipt.log, /var/log/modsec2ipt_error.log 인데 임의로 변경 가능합니다. 기본값을 그대로 유지한다면 touch 커맨드로 /var/log/modsec2ipt.log, /var/log/modsec2ipt_error.log 파일을 생성해 줍니다.

#!/usr/bin/perl
###########################################################
# modsec2ipt_srv.pl
#
# server used to block IPs with iptables and mod_security.
# uses/creates the chain "MODSEC2IPT"
#
###########################################################
$chain = "MODSEC2IPT";
# blocked IP's log :
$log  = '/var/log/modsec2ipt.log';
# errors log :
$error_log='/var/log/modsec2ipt_error.log';
###########################################################

 

 /etc/xinetd.d/modsec2ipt 파일을 아래와 같이 작성합니다.

service modsec2ipt
  {
    flags         = NAMEINARGS
    socket_type   = stream
    protocol      = tcp
    wait          = no
    user          = root
    server        = /usr/sbin/tcpd
    server_args   = /usr/bin/modsec2ipt_srv.pl
    only_from     = 127.0.0.1
    cps           = 1 1
  }


 /etc/services에 아래 내용을 한 줄 추가합니다.

modsec2ipt   54545/tcp


 xinetd 수퍼데몬을 리스타트하면 스크립트가 작동을 시작합니다.

[root@localhost:/usr/bin]# /etc/init.d/xinetd restart


 아래와 같은 검사 결과가 나오면 설정에 이상 없는 것입니다.

[root@localhost:/usr/bin]# telnet localhost 54545
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
OK, modsec2ipt server
quit
OK
Connection closed by foreign host.
[root@localhost:/usr/bin]#

[root@localhost:/usr/bin]# netstat -ntlp | grep 54545
tcp        0      0 0.0.0.0:54545               0.0.0.0:*                   LISTEN      3227/xinetd
[root@localhost:/usr/bin]#


 이제부터 스크립트에 의해 iptables에 등록되는 룰은 MODSEC2IPT라는 체인에 별도로 작성됩니다. 이 체인은 스크립트가 처음 작동할 때 자동으로 생성되므로 수동으로 직접 생성해 줄 필요가 없습니다.

[root@localhost:~]# iptables -nL MODSEC2IPT | less
Chain MODSEC2IPT (1 references)
target     prot opt source               destination
DROP       all  --  xx.xx.xx.xx          0.0.0.0/0
DROP       all  --  yy.yy.yy.yy         0.0.0.0/0
DROP       all  --  zz.zz.zz.zz        0.0.0.0/0
( 이 하 생 략 )


 실제로 웹방화벽에 의해 필터링되는 즉시 iptables에 의해 차단이 되는지 테스트해보겠습니다.
 mod_security 설치 방법 및 운영에 관한 메뉴얼은 아래 URL에서 구하시기 바랍니다.
 http://www.krcert.or.kr/firewall2/index2.jsp

 URL주소 뒤에 'ddos'라는 문자열의 서브 디렉토리 경로를 추가 입력해서 접근을 시도할 경우 차단되도록 하기 위해 mod_security 룰 파일에 아래 룰을 추가하고 아파치를 리스타트합니다.
 참고로 지금부터 언급하는 mod_security 룰은 1.9.5 버전을 기준으로 설명합니다. 2.x 버전부터는 룰 패턴이 조금 다르므로 이 점 유의 바랍니다.

# modsec2ipt 최초 테스트 룰
SecFilterSignatureAction "log,deny,status:403,msg:'Test Rule',exec:/usr/local/apache/bin/modsec2ipt.pl"
SecFilter "\/ddos"


 이제 http://도메인/ddos 과 같이 접속해 보면 예전처럼 웹방화벽의 필터링에 걸리면 웹브라우저에 403 에러 등의 메시지가 출력되는 것과는 달리 아예 접속 자체가 차단되는 것을 확인할 수 있습니다. tcp 80 포트로의 접근만 차단되는 것이므로 터미널로 iptables -nL 커맨드를 통해 접근을 시도한 클라이언트 측 IP가 MODSEC2IPT 체인에 등록된 것을 직접 확인할  수 있습니다.

 
 본 게시물의 서두에서 언급한 Cache Control Attcak 을 막기 위해서는 아래 룰을 추가해 주면 됩니다. 그러나 Cache Control Attcak이 반드시 위와 같은 아파치 로그 패턴을 남기는 것은 아니기 때문에 상황에 따라 알맞은 룰을 직접 커스터마이징해서 관리해야 할 것입니다.

# Cache-Control Attack 방어
SecFilterSignatureAction "log,deny,status:403,msg:'Cache-Control Attack',exec:/usr/local/apache/bin/modsec2ipt.pl"
SecFilterSelective HTTP_User-Agent "cache\-control|no\-store|must\-revalidate"