ACE library 설치법..

1. 공식 다운로드 페이지에서 ACE-5.5.tar.gz파일을 다운로드 받습니다.

2. 환경 변수를 설정합니다.(~/.bash_profile)
  – ACE_ROOT=/home/k2/Apps/ACE_wrappers;export ACE_ROOT
  – LD_LIBRARY_PATH=$ACE_ROOT/ace:$ACE_ROOT/lib:$LD_LIBRARY_PATH;
    export LD_LIBRARY_PATH

3. $ACE_ROOT/ace에서 심볼릭 링크 추가합니다.
  – ln -s config-linux.h config.h

4. $ACE_ROOT/include/makeinclude 에서 심볼릭 링크 추가합니다.
  – ln -s platform_linux.GNU platform_macros.GNU

5. $ACE_ROOT/ace에서 make

6. 컴파일 제대로 되었는지 확인합니다.
  – $ACE_ROOT/examples/Threads에서 make
  – ./task_one 실행하면은 아래 결과처럼 나오면 성공이에요
  (3076410288) in iteration 1
  (3076410288) in iteration 2
  (3076410288) in iteration 3
  (3076410288) in iteration 4
  (3076410288) in iteration 5
  (3076412064) done

7. 설치된 라이브러리 디렉토리는 $ACE_ROOT/lib입니다.

8. 그 다음 ACE 라이브러리를 확인하여 서버 프로그램 개발을 하면 됩니다.

출처 : http://sexymiru.egloos.com/1967295

——————————————————————————————

 실행환경 : ubuntu-10.04 Desktop 버전에서 에러 발생.

 컴파일 중 재정의 문제가 발생. 설치가 진행되지 않는다. configure 를 이용한 설치에도 제대로 진행이 되지 않았다.

 구글과 ACE 메일링 리스트를 살펴서 여러가지 해결법을 찾아보았지만 보이지 않았다… 어떻게 해야되는 것일까…

 Ubuntu-09.04(혹은 09.10) Server 버전에서는 아무 문제 없이 컴파일 되는 것을 확인 했다. 특별히 배포판을 가리지는 않는 것 같다. 아마도 문제점은 커널 버전 혹은 g++ 의 버전 정도가 될 것 같다.

 재정의 컴파일 오류가 났으니 특정 라이브러리가 설치되지 않아서 생기는 문제는 아닌 것 같다.

 사실, ACE-5.8.* 버전은 설치가 쉽게 되었다. 하지만 ACE-5.8.* 대의 버전을 설치할 경우, ACE-5.5.* 버전에서 지원하는 메소드 및 함수가 지원되지 않은 것들이 있다.

 즉, 내가 필요로 하는 메소드와 함수들은 ACE-5.8.* 버전에서는 지원하지 않는 것이다.

 흠.. 조금 더 낮은 버전에서 찾아볼까..

———————————————————————————-

 설치의 실마리를 찾았다.

  • windows
    • ACE_wrapper/ace 에서
    • config.h 파일 생성
      #define ACE_HAS_STANDARD_CPP_LIBRARY 1
      #include “config-win32.h”
  • linux
    • ACE_wrapper/ace 에서
      ln –s config-linux.h config.h
    • ACE_wrapper/include/makeinclude 에서
      ln –s platform_aix_ibm.GNU platform_macros.GNU
    • .bash_profile
      export ACE_ROOT=~/Library/ACE-5.7.9
      export LD_LIBRARY_PATH=$ACE_ROOT/ace
    • ACE_wrapper/ace 에서
      ../configure –enable-stdcpplib
      gmake buildbits=64
  • AIX
    • ACE_wrapper/ace 에서
      ln –s config-aix-5.x.h config.h
    • ACE_wrapper/include/makeinclude 에서
      ln –s platform_aix_ibm.GNU platform_macros.GNU
    • .profile
      export ACE_ROOT=$HOME/lib/ACE-5.5/ACE_wrappers
      export LIBPATH=.:$ACE_ROOT/ace
    • ACE_wrapper/ace 에서
      ../configure –enable-stdcpplib
      gmake buildbits=64 static_libs=1

 출처 : http://anyons.net/tc/entry/ACE-%EC%84%A4%EC%B9%98-%EB%B0%A9%EB%B2%95

error: expected unqualified-id before numeric constant

 오늘 C++ 책에서 나온 소스코드를 컴파일하다 이상한 에러를 발견했다.

17-2.cpp:84: error: expected unqualified-id before numeric constant
17-2.cpp:84: error: expected initializer before numeric constant


 다음의 링크에서 해답을 찾을 수 있었다.

http://bytes.com/topic/c/answers/752247-what-does-expected-unqualified-id-before-numeric-constant-mean

All uppercase names are often used for preprocessor macros, which
doesn’t respect namespace scopes. Therefore such names should
generally be avoided for everything else.

 즉 어디에선가 같은 이름으로 된 매크로를 사용하고 있어서 생기는 문제라는 것이다. 해당 소스의 라인에서 변수명을 바꾸어서 컴파일을 했더니 간단히 문제는 해결되었다. 🙂

시스템 최적화 – 동시사용자 늘리기 위한 커널 조정(ulimit)

 이 글은 http://wiki.kldp.org/KoreanDoc/Ulimit-KLDP (문태준님 작성, 2000년 2월 24일(목))을 토대로 필자가 나름 내용을 추가하여 작성하는 글이다.

 최대한 원글의 내용을 그대로 유지하되, 이미 10년이란 세월이 흘렀으므로 많은 변화가 있었다. 워낙 중요하고 좋은 글이라 그냥 그대로 가져다 쓰려고 했으나, 뭔가 아쉬운 느낌이 들어 없는 실력이지만 약간의 보충을 덧붙여보기로 했다.

  * 이 글은 실제로 제가 대형서버를 운영하고 있는 상황에서 나온 글은 절대 아니며, 그냥 여기저기서 주워들은 이야기들과 자료들을 토대로 해서 작성한 것입니다. 동시접속이 몇백명에서 몇천명되는 서비스를 하려면 단순하게 커널 컴파일 한번 하고 끝나는 것이 아니라 여러가지 조정을 해주어야 할 것이 많습니다. 또한 하드웨어와 OS 제한이 있으므로 로드밸런싱(부하분산), 트래픽 분산 등을 하는 스위칭 장비, 클러스터링 시스템 구성이 필요할 수 있습니다. 그만큼 설계를 잘해야합니다. 여기에 언급한 것은 단지 쉽게 할 수 있는 맛보기 정도이지요. 이로 인해서 생기는 손해에 대해서는 본인이 절대 책임을 지지 않습니다. 또한 내용 중 틀린 부분도 많이 있을 것입니다.

  * 들어가며

 대규모 서비스를 준비하는 경우 운영체제의 제한사항을 먼저 확인해야 한다. 동시에 열수 있는 총파일 수, 한 프로세스가 열수 있는 파일 수 등등.

 예를 들어 대형 웹서버를 아파치로 서비스하는 경우를 생각해보자. 아파치는 기본적으로 프로세스 방식으로 서비스를 처리한다. 이건 사용자의 요구가 올때마다 하나의 프로세스를 띄우므로 만약 동시에 10명의 사용자가 접속을 하면 10개의 프로세스가 떠야한다는 것이다. 최근의 아파치 서버는 MaxClients 150 이라고 설정되어 있다. 이건 동시에 150 개의 프로세스를 띄울 수 있으며 결국 동시에 150명을 받아 들일 수 있다는 것이다(실제로 이정도만 하더라도 절대로 작은 규모는 아니다). 그런데 만약 nobody가 만들어낼 수 있는 최대 프로세스 개수가 그 이하라면? 당연히 문제가 생길 것이다. 물론 최근 레드햇 6.0 이상 버전은 그 이상으로 맞추어져 있어서 문제가 생기지는 않겠지만.

 문제는 프로세스가 많이 뜨면 프로세스뿐만 아니라 열 수 있는 파일 수에서도 문제가 된다.

 그러면 먼저 프로세스의 자원 한도에 대해서 알아보자.

 -주
 이 글을 작성하는 현재(2010.07.08) 많은 것이 바뀌어졌다. 현재 필자가 운용하는 아파치의 버전은 2.2.14 버전을 사용중이고, (원 글님이 글을 작성하셨을 10년전에는 아마 1.7.X 버전으로 사용되었으리라 생각한다) 아파치의 구동 방식도 하나의 요청마다 하나의 프로세스를 띄우는 방식이 아닌 메소드 및 기타 방식을 사용하는 형식으로 바뀌었다. 그리고 아울러 MaxClient의 수도 증가했음은 물론이다.

 * 프로세스의 자원한도

 프로세스의 자원한도를 리눅스에서는 ulimit 를 통해서 알 수 있다.

 ulimit 옵션

 -a 모든 제한 사항을 보여준다.
 -c 최대 코어 파일 사이즈
 -d 프로세스 데이터 세그먼트의 최대 크기
 -f shell에 의해 만들어질 수 있는 파일의 최대 크기
 -s 최대 스택 크기
 -p 파이프 크기
 -n 오픈 파일의 최대 수
 -u 프로세스 최대 수
 -v 최대 가상 메모리의 량

 # ulimit -a (또는 ulimit -Sa) —> soft 한도

jonathan@jonathan-laptop:~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 20
file size               (blocks, -f) unlimited
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

 # ulimit -Ha —-> Hard 한도

jonathan@jonathan-laptop:~$ ulimit -Ha
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 20
file size               (blocks, -f) unlimited
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) unlimited
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

 소프트 한도(soft)는 새로운 프로세스가 만들어졌을 때 디폴트로 적용되는 자원의 한도이다. 이것을 하드한도까지 등가시킬 수 있다. 그렇지만 이 한도를 넘어서 확장하는 것은 슈퍼유저만이 가능하다.

 즉, 하드한도는 절대적인 선이다.

 그렇다면 하드한도는 슈퍼유저라고 무한대로 늘릴 수 있는가?
-> 절대 아니다. 이건 커널차원에서 지정을 해야 한다.

 위에서의 각 항목을 살펴보자면…

core file size          -> 코어파일의 최대크기
data seg size           -> 프로세스의 데이터 세그먼트 최대크기
scheduling priority
file size               (blocks, -f) unlimited  -> 쉘에서 생성되는 파일의 최대 크기
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited  -> resident set size의 최대 크기(메모리 최대크기)
open files                      (-n) 1024    -> 한 프로세스에서 열 수 있는 open file descriptor의 최대 숫자(열수 있는 최대 파일 수)
pipe size            (512 bytes, -p) 8    -> 512-바이트 블럭의 파이프 크기
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited     -> 총 누적된 CPU 시간(초)
max user processes              (-u) unlimited   -> 단일 유저가 사용가능한 프로세스의 최대 갯수
virtual memory          (kbytes, -v) unlimited   -> 쉘에서 사용가능 한 가상 메모리의 최대 용량
file locks                      (-x) unlimited

 의 뜻을 가지고 있다.

 위의 내용 중 주의깊게 살펴볼 부분이 바로 한 프로세스에서 열 수 있는 file descriptor 의 갯수를 표시한 open files 항목과 한 유저가 생성 가능한 프로세스의 갯수 부분이다.

 사실 이미 한 유저가 생성 가능한 프로세스의 갯수가 무한정으로 되어 있으므로 file descriptor 의 갯수는 그다지 큰 의미가 없다. 하지만 file descriptor의 갯수를 늘리고 싶다면 다음의 방법으로 가능하다.

 1. 소스파일을 수정한 후, 커널 재컴파일을 하는 방법.

 2. /proc 를 이용하여 변경하는 방법.

 3. /etc/security/limits.conf 파일을 수정하는 방법

 사실 ulimit 명령으로 조절이 가능하나, 단지 보여주기만 할 뿐 실제적인 수정이 되지 않는다고 원글에는 나와있었다. 그래서 ulimit 관련 부분은 패스.

 그러나, 프로그래밍의 경우는 ulimit 함수를 통해서 수정이 가능하다.

NAME
       ulimit – get and set user limits

SYNOPSIS
       #include <ulimit.h>

       long ulimit(int cmd, long newlimit);

DESCRIPTION
       Warning: This routine is obsolete.  Use getrlimit(2), setrlimit(2), and
       sysconf(3) instead.  For the shell command ulimit(), see bash(1).

       The ulimit() call will get or set some limit for the  calling  process.
       The cmd argument can have one of the following values.

       UL_GETFSIZE
              Return the limit on the size of a file, in units of 512 bytes.

       UL_SETFSIZE
              Set the limit on the size of a file.

       3      (Not  implemented  for  Linux.)   Return  the  maximum  possible
              address of the data segment.

       4      (Implemented but no symbolic  constant  provided.)   Return  the
              maximum number of files that the calling process can open.

RETURN VALUE
       On  success,  ulimit()  returns  a non-negative value.  On error, -1 is
       returned, and errno is set appropriately.

ERRORS
       EPERM  A non-root process tried to increase a limit.

CONFORMING TO
       SVr4, POSIX.1-2001.  POSIX.1-2008 marks ulimit() as obsolete.

SEE ALSO
       bash(1), getrlimit(2), setrlimit(2), sysconf(3)

 2. proc를 이용한 방법

 proc를 이용하여 간단히 변경하는 방법이 있다.

pchero@MyNote:~$ cat /proc/sys/fs/file-max
6553600
pchero@MyNote:~$ sudo echo 7000000 > /proc/sys/fs/file-max

 하지만 /proc 를 사용하여 시스템 설정을 변경할 경우, 매 부팅시 설정을 다시 해주어야 한다는 단점이 있다.
 /etc/rc.local 파일을 이용하여 명령어를 설정하던가 아니면 다음에 나오는 limits.conf 파일을 이용하도록 한다.

 3. 사용자에 따른 자원 한도 설정 파일
/etc/security/limits.conf

# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain>        <type>  <item>  <value>
#
#Where:
#<domain> can be:
#        – an user name
#        – a group name, with @group syntax
#        – the wildcard *, for default entry
#        – the wildcard %, can be also used with %group syntax,
#                 for maxlogin limit
#        – NOTE: group and wildcard limits are not applied to root.
#          To apply a limit to the root user, <domain> must be
#          the literal username root.
#
#<type> can have the two values:
#        – “soft” for enforcing the soft limits
#        – “hard” for enforcing hard limits
#
#<item> can be one of the following:
#        – core – limits the core file size (KB)
#        – data – max data size (KB)
#        – fsize – maximum filesize (KB)
#        – memlock – max locked-in-memory address space (KB)
#        – nofile – max number of open files
#        – rss – max resident set size (KB)
#        – stack – max stack size (KB)
#        – cpu – max CPU time (MIN)
#        – nproc – max number of processes
#        – as – address space limit (KB)
#        – maxlogins – max number of logins for this user
#        – maxsyslogins – max number of logins on the system
#        – priority – the priority to run user process with
#        – locks – max number of file locks the user can hold
#        – sigpending – max number of pending signals
#        – msgqueue – max memory used by POSIX message queues (bytes)
#        – nice – max nice priority allowed to raise to values: [-20, 19]
#        – rtprio – max realtime priority
#        – chroot – change root to directory (Debian-specific)
#
#<domain>      <type>  <item>         <value>
#

#*               soft    core            0
#root            hard    core            100000
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#ftp             –       chroot          /ftp
#@student        –       maxlogins       4

# End of file

# Setting for oracle
oracle          soft    nproc           2047
oracle          hard    nproc           16383
oracle          soft    nofile          1023
oracle          hard    nofile          6553

  제일 아래 ‘oracle’ 과 같이 따로 설정된 부분과 같이 변경하면 된다. 이렇게 설정할 경우, 매 부팅시 자동 적용되어 별도로 적용하지 않아도 된다. 또한, 각각의 유저마다 다른 설정을 적용할 수 있으므로 보안 및 관리에도 용이하다.

 # 마지막으로 프로세스에서 열어놓은 파일을 확인하는 방법에 대해 알아보자.

 결론적으로 lsof 프로그램을 이용하면 된다.

 lsof는 ‘List Open File’의 약자로 해당 System에서 구동되고 있는 프로세스들에 의해서 열려진 파일들을 확인 할 수
있는 툴이다. 시스템의 의심스러운 프로세스에 대한 확인이 용이하고, 설치가 비교적 쉬워 많이 이용되고 있다.

 lsof에 관한 내용은 워낙 방대하여 아래에 해당 프로그램 사용에 대한 매뉴얼을 링크해둔다. 또한 man lsof를 이용하여 사용해도 무방하다.

http://www.superuser.co.kr/security/certcc/secu_certcc_15.htm

 

11.psad와 fwsnort의 결합

 * fwsnort 탐지와 psad 동작의 결합

 fwsnort는 공격을 탐지하면 iptables 로그 메시지를 생성한다. 이 메시지는 사용자에게 해당 로그 메시지를 촉발한 스노트 규칙 ID, fwsnort 체인내의 규칙 번호, 패킷이 수립된 TCP 세션의 일부인지 여부를 알려주는 로그 접두어를 포함한다.

 ** WEB-PHP Setup.php access 공격

 스노트 규칙 ID 2281은 미디어위키 소프트웨어(원래는 위키피디아를 보조하기 위해 설계된 소프트웨어다. http://en.wikipedia.org/wiki/Mediawiki 참조)의 입력 확인 취약점을 공격하려는 시도를 탐지하게 설계됐다. 이 취약점은 Bugtraq ID 9057에서 기술하고 있으며, 스노트 규칙 ID 2281은 이를 WEB-PHP Setup.php access 공격이라고 명명한다. 이 취약점을 성공적으로 공격하면 목표 시스템이 HTTP 요청 내의 특별히 구성된 URI 매개변수를 수신할 때 목표 시스템에서 승인 받지 않은 원격 코드를 실행할 수 있다. 내부 웹서버에 대해 WEB-PHP Setup.php access 취약점을 공격하게 설계된 공격을 가상으로 실행해보자. seclab 시스템에는 기본 iptables 정책이 배치돼 있으며, 가상 공격은 soft-ftp 시스템에서 수행한다고 가정한다.

 우선 텍스트 기반 웹 브라우저인 링크스(lynx)를 사용해서 seclab 시스템에서 iptables 방화벽을 통해 webserver로 웹 연결을 생성할 수 있는지 확인하자.

# lynx http://seclab.x.x.kr


 iptables 방화벽을 통한 웹 연결성을 확인했으니 공격에 대해 예상할 수 있는 응답을 보기 위해 fwsnort psad를 배치하기 전에 가상 공격을 수행해보자. 우선 Bugtraq ID 9057 취약점을 공격하려는 시도를 탐지하게 설계된 스노트 규칙 ID 2281은 다음과 같다.(원래 책에는 /etc/fwsnort/snort_rules/emerging-all.rules 파일에 적혀있다고 하였으나, 이상하게 필자의 서버에서는 그 내용을 찾을 수가 없었다. 그래서 아래와 같이 따로이 제일 마지막 라인에 해당 규칙을 기술해넣었다.)

 문자열 /Setup.php만 제외하면 위의 규칙은 웹서버로부터 요청된 URI 매개변수의 내용(이는 공격자가 달성하고자 하는 것에 따라 달라질 수 있다)을 신경쓰지 않는다. 이 서명은 웹 요청의 URI 부분에서 문자열 /Setup.php 를 엄격히 검색하며, 이 데이터는 flow 키워드에서 요구하는 대로 수립된 TCP 연결에서 보여야 한다. 이 덕분에 다음과 같이 취약점에 대한 가상 공격이 매우 시워진다.

soft-ftp:~# lynx http://seclab.X.X.kr/Setup.php

                                                                  404 Not Found

                                   Not Found

   The requested URL /Setup.php was not found on this server.
     _________________________________________________________________

    Apache/2.2.11 (Ubuntu) PHP/5.2.6-3ubuntu4.5 with Suhosin-Patch
    Server at seclab.kongju.ac.kr Port 80

 위로부터 내부 웹서버가 취약하지 않다는 것을 알 수 있으며(내부 웹서버는 미디어위키를 실행하고 있지 않다) 예상대로 요청된 페이지가 존재하지 않는다는 것을 의미하는 404 Not Found 오류를 돌려받는다. 가상 공격을 수행하고 있다는 점을 기억하자. 가상 공격에서는 스노트 서명이 찾고자 하는 것처럼 보이는 네트워크 트래픽만 생성하면 된다.

 – fwsnort 를 이용한 공격 탐지

 이제 iptables로 WEB-PHP Setup.php access 공격을 탐지하기 위해 (일단은) –ipt-drop 이나 –ipt-reject 인자 없이 fwsnort를 실행하자.


 /etc/fwsnort/fwsnort.sh 스크립트를 살펴보면 수립된 TCP 연결에서 /Setup.php 문자열을 탐지하기 위해 문자열 매칭 확장과 맞춤화 FWSNORT_FORWARD_ESTAB 체인을 탐지하기 위해 문자열 매칭 확장과 맞춤화 FWSNORT_FORWARD_ESTAB 체인을 사용하는 iptables 명령을 볼 수 있다. 이 명령은 아래와 같으며, 공격을 탐지하기 위해 상당한 연산을 수행한다.

$IPTABLES -A FWSNORT_FORWARD_ESTAB -p tcp –dport 80 -m string –string “/Setup.php” –algo bm -m comment –comment “sid:2281; msg:WEB-PHP Setup.php access; classtype:web-application-activity; reference:bugtraq,9057; rev:2; FWS:1.0.5;” -j LOG –log-ip-options –log-tcp-options –log-prefix “[1] SID2281 ESTAB “
$IPTABLES -A FWSNORT_INPUT_ESTAB -p tcp –dport 80 -m string –string “/Setup.php” –algo bm -m comment –comment “sid:2281; msg:WEB-PHP Setup.php access; classtype:web-application-activity; reference:bugtraq,9057; rev:2; FWS:1.0.5;” -j LOG –log-ip-options –log-tcp-options –log-prefix “[1] SID2281 ESTAB “

 굵게 나타낸 부분이 iptables 로그 접두어이다. 이 접두어를 통해 iptables 로그 메시지에서 해당 규칙의 실행 여부를 확인할 수 있다. 이제 다시 공격 트래픽을 생성해보자. 공격 트래픽 생성 후, 아래의 로그 메시지를 얻을 수 있을 것이다.

Jul 11 05:30:13 seclab kernel: [4540091.006611] [1] SID2281 ESTAB IN=eth0 OUT= MAC=00:21:5e:4e:bb:da:00:11:88:42:99:43:08:00 SRC=X.X.X.X DST=Y.Y.Y.Y LEN=414 TOS=0x00 PREC=0x00 TTL=62 ID=44542 DF PROTO=TCP SPT=47966 DPT=80 WINDOW=365 RES=0x00 ACK PSH URGP=0 OPT (0101080A2FED6AD91B0F2BDB)

 – psad를 이용한 경고

 fwsnort는 공격을 탐지했지만 iptables로부터 로그 메시지만 생성했다. fwsnort는 whois 검색이나 메일 경고 전송 등의 기능을 가지고 있지 않기 때문에 이를 수행하지 않았다.

 그러나 fwsnort가 iptables 로그 메시지를 생성하기 때문에 psad가 이를 분석한 후, 해당 이벤트에 자신의 경고와 보고 기능을 적용할 수 있다. 그러나 우선 psad는 fwsnort 로그 메시지를 적절히 처리해야 한다. 이 메시지는 애플리케이션 계층 데이터의 검사를 통해 생성된 것이지만 결국 데이터 자체는 로그 메시지에 포함되지 않는다.

 로그 메시지를 해석하는 데 중요한 것이 /etc/psad/psad.conf 파일의 SNORT_SID_STR 변수다. 이 변수는 psad가 로그 메시지 fwsnort에 의해 생성됐다는 것을 유추하기 위해 봐야 할 로그 접두어 부분을 기술한다. 기본적으로 SNORT_SOD_STR은 다음과 같이 설정된다.


 로깅 접두어에 부분 문자열 SID를 포함하는 iptables 로그 메시지는 fwsnort가 생성한 메시지로 거의 항상 애플리케이션 계층 공격에 대한 것이다.

 이제 psad를 확실해 실행하고(/etc/init.d/psad start 를 실행) 가상 공격을 다시 한 번 수행하자. 이번에는 psad 가 iptables 로그 메시지를 가로채서 구문 분석한 후 아래와 같은 메일 경고를 생성한다.

=-=-=-=-=-=-=-=-=-=-=-= Sun Jul 11 05:30:23 2010 =-=-=-=-=-=-=-=-=-=-=-=

         Danger level: [5] (out of 5)

    Scanned TCP ports: [80: 1 packets]
            TCP flags: [ACK PSH: 1 packets]
       iptables chain: FWSNORT_INPUT_ESTAB (prefix “[1] SID2281 ESTAB”), 1 packets
         fwsnort rule: 1

               Source: X.X.X.X
                  DNS: [No reverse dns info available]
             OS guess: SunOS:4.1::SunOS 4.1.x

          Destination: Y.Y.Y.Y
                  DNS: seclab.kongju.ac.kr

   Overall scan start: Thu Jul  1 23:50:42 2010
   Total email alerts: 23
   Complete TCP range: [1-65301]
      Syslog hostname: seclab

         Global stats: chain:   interface:   TCP:   UDP:   ICMP: 
                       INPUT    eth0         11182  0      0     

[+] TCP scan signatures:

   “MISC xfs communication attempt”
       dst port:  7100 (no server bound to local port)
       flags:     SYN
       sid:       1987
       chain:     INPUT
       packets:   2
       classtype: misc-activity

   “MISC Radmin Default install options attempt”
       dst port:  4899 (no server bound to local port)
       flags:     SYN
       psad_id:   100204
       chain:     INPUT
       packets:   2
       classtype: attempted-admin

   “WEB-PHP Setup.php access”
       dst port:  80 (no server bound to local port)
       flags:     ACK PSH
       content:   “/Setup.php”
       sid:       2281
       chain:     FWSNORT_INPUT_ESTAB
       packets:   1
       classtype: web-application-activity

=-=-=-=-=-=-=-=-=-=-=-= Sun Jul 11 05:30:23 2010 =-=-=-=-=-=-=-=-=-=-=-=

 위의 psad 메일 경고가 보통 psad가 생성하는 메일 경고라고 생각하면 되며, 여기에는 타임 스탬프, 패킷 수, TCP 플래그와 포트 등과 같은 표준 정보가 모두 포함된다.

 iptables 그 자체로는 LOG 타겟을 통해 패킷의 실제 내용을 보고하는 기능을 가지지 않으며, 접두어 문자열 길이는 29글자로 제한되기 때문에 일반적으로 단순히 로그 접두어에 내용 문자열을 포함시키는 것이 합당하다. syslog 메시지에 바이너리 패킷 데이터를 포함시키는 것 역시 좋은 생각이 아니다.

 * 다시 보는 능동적 응답

 ** psad와 fwsnort

 psad는 공격이 탐지되면 공격자에 대해 영속적인 시간 만료 기반 iptables 차단 규칙을 인스턴스화 할 수는 있지만 스스로 연결을 종료시키거나 애플리있케이션 계층 서명과 매칭되는 첫 번째 패킷이 전달되는 것을 막지는 못한다.한편 fwsnort의 경우 악의적인 패킷이나 세션을 개별적으로 무력화하기 위해 DROP이나 REJECT 타겟을 사용할 수는 있지만 일정 기간 동안 공격자를 차단하는 새로운 iptables 규칙을 생성하지는 못한다.

 각 도구의 강점을 고려하면 두 응답 방식을 결합하는 것이 좋다는 것을 알 수 있다. 결국 fwsnort는 특정 TCP 세션에 포함된 특정 공격을 탐지하고 저지하는 데 우수할 수 있지만 영속적인 차단 규칙을 관리하기 위한 psad가 없다면 공격자는 동일한 목표에 다른 공격을 자유롭게 시도할 수 있다. 첫 번째 공격 시도를 탐지했던 동작이 꽤 행운이었을 수 있으며, 다음 공격 시도는 전혀 탐지하지 못할 수도 있다. 이 때문에 차단 규칙이 중요하다. 공격자가 첫 번째 공격과 무관하며 서명도 존재하지 않는 취약잠에 대한 추가적인 공격을 가지고 있는 경우 특히 그렇다. 또 공격자가 TCP 서비스를 공격할 때 Tor 익명화 네트워크(http://tor.eff.org)를 사용하면 공격은 매번 다른 출구 라우터(Tor 가 각 TCP 세션마다 무작위로 선택한다)에서 오는 것처럼 보이기 때문에 개별적인 IP 주소를 차단하는 것은 의미가 없다.

 다시 한 번 이야기하자면 능동적 응답 기법을 잘 아는 능숙한 공격자는 이 기능이 목표 네트워크에 반하게 만들기 위해 이를 전복하려고 할 수도 있다. 또 공격자가 공격을 수행할 다수의 호스트를 제어하는 경우(공격자 사이에서는 개인이 봇넷[botnet]을 구성하기 위해 여러 호스트를 제어하는 것이 보통이다) 공격자는 목표를 공격하는데 아직 사용하지 않은 호스트로부터 새로운 공격을 수행할 수도 있다. 네트워크를 보호하려는 사람과 이를 공격하려는 사람간에는 항상 경쟁 관계가 존재하며, 이런 관점에서 공격 측이 상당한 무장을 갖추고 있다고 가정해야 한다.

 ** fwsnort가 탐지한 공격으로 psad 응답을 제한

 psad는 fwsnort가 생성한 로그 메시지에 대한 경고를 전송할 수 있다. 또 단순히 /etc/psad/psad.cnf 파일의 ENABLE_AUTO_IDS 를 Y 로 설정함으로써 psad는 fwsnort 로그 메시지에 대한 응답으로 iptables 차단 규칙을 설정할 수 있다.

 fwsnort에 의해 탐지된 공격이 psad 에 의해 공격자에게 할당된 위험 수준을 AUTO_IDS_DANGER_LEVEL 변수에 설정된 값보다 크게 하면 psad는 공격자의 IP 주소에 대해 자유재량의 DROP 규칙을 인스턴스화한다. 그러나 fwsnort가 공격을 기록하기 때문에 포트 스캔과 백도어를 위함 탐사도 위험 수준을 할당 받는다.

 하지만 쉽게 스푸핑되는 스캔과 탐사에 대해 psad 응답을 활성화하는 것은 위험하다. psad가 수립된 TCP 연결을 통한 애플리케이션 계층 데이터를 수반해야 하는 공격에만 응답하고 다른 유형의 공격에는 어떤 조치도 취하지 않게 하는 것이 좋다.

 AUTO_BLOCK_REGEX 변수는 대응되는 iptables 로그 메시지가 정규식과 매칭할때만 psad가 IP 주소 차단을 수행하게 강제하는 정규식을 포함한다. AUTO_BLOCK_REGEX의 기본 값은 문자열 ESTAB며, 이는 수립된 TCP 연결에 속하는 패킷과만 매칭하게 설계된 맞춤화 체인 중 하나에 의해 기록된 fwsnort 로그 메시지와 매칭된다. 이 기능을 활성화하려면 psad 설정 파일에서 ENABLE_AUTO_BLOCK_REGEX 변수를 Y로 설정해야 한다.

 psad 가 공격자를 방화벽에 접근할 수 없게 하려면 fwsnort를 실행하고 AUTO_BLOCK_REGEX 기능을 활성화해야 한다. 포트 스캔이나 기타 쉽게 스푸핑 가능한 트래픽에 응답하는 것은 너무나 쉽게 악용될 수 있다.