본문 바로가기
운영체제 (LNX,WIN)

iptables 국가별 geoip 모듈 적용

by 날으는물고기 2009. 7. 1.

iptables 국가별 geoip 모듈 적용

작업 시나리오

1. 2.6.27.4 Kernel 소스 다운로드
    iptables 1.4.2 소스 다운로드
    patch-o-matic-ng 소스 다운로드


 각 소스는 아래 링크에서 다운로드
ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.27.4.tar.bz2
http://ftp.netfilter.org/pub/iptables/snapshot/iptables-20081028.tar.bz2
http://ftp.netfilter.org/pub/patch-o-matic-ng/snapshot/patch-o-matic-ng-20081028.tar.bz2

 상기 소스들은 /usr/src 디렉토리에 받아 놓고 압축을 풀어 둔다.
 커널 소스와 iptables 소스는 압축을 풀어 놓으면  디렉토리 명이 길기 때문에
 짧은 디렉토리 명으로 심볼릭 링크를 걸어 두는 것이 작업상 편리하겠다.

# tar xvfj linux-2.6.27.4.tar.bz2
# ln -s linux-2.6.27.4 linux
# tar xvfj iptables-20081028.tar.bz2
# ln -s iptables-20081028 iptables


2. patch-o-matic-ng 소스로 iptables 소스와 커널 소스에 패치를 가함.
    이 메뉴얼에서는 connlimit 와 geoip 모듈만 커널에 추가시키고 iptables 에서
    이 모듈들을 컨트롤할 수 있게 하는 방법만을 다룸.

# cd /usr/src/iptables
# ./configure

※ 반드시 iptables 소스 디렉토리에서 configure 커맨드로 컴파일 환경설정을 먼저 한 뒤에 patch-o-matic-ng 로 패치를 가해 주어야 한다. 그렇지 않을 경우 패치 과정에서 iptables 소스가 패치 소스에 적합치 않다는 에러를 내며 중단된다.

# cd /usr/src/patch-o-matic-ng-20081028
# ./runme --download
# ./runme geoip

 이 작업 과정을 보면 geoip 패치만 가하게 되는데 connlimit 모듈은 2.6.23 커널부터 기본 포함이 되어 있어서 커널 컴파일 시 활성화만 시켜주면 되며 iptables에도 기본 extension으로 포함되어 있기 때문에 iptables에도 따로 패치를 가할 필요가 없다. geoip는 커널에도, iptables의 기본 익스텐션으로도 포함되어 있지 않으므로 patch-o-matic-ng 로 수동 패치해 줘야 한다.


3. geoip 패치가 끝났으면 먼저 패치된 커널 소스를 컴파일하여 설치


# cd /usr/src/linux

 커널 소스 디렉토리로 들어갔으면 기존에 정상적으로 사용하던 커널의 환경옵션을 그대로 가져 와서 컴파일하는 것이 좋다. /boot 디렉토리 안을 보면 이름이 config... 로 시작하는 커널 환경 변수 정보가 담겨있는 파일들이 있는데 이 중 가장 최근까지 정상적으로 사용해 오던 파일을 복사해다가 /usr/src/linux 디렉토리 안에 .config 라는 이름의 파일로 저장해서 불러들이는 방식을 취하면 된다.

# make menuconfig

그 다음 제일 하단에서 2번째에 있는 Load an Alternate Configuration File 메뉴를 통해 .config 파일을 로드한 뒤

Networking --> Networking option --> Network packet filtering framework (Netfilter) 옵션으로 들어가서
Core Netfilter Configuration을 비롯하여 넷필터, iptables 관련 모듈을 모두 체크하고 빠져 나온다.
Core Netfilter Configuration 옵션 안의 모듈들은 가급적 <M> 체크하여 모듈 형태로 저장한다.
iptables관련 모듈들은 하나가 모듈로 컴파일되면 다른 것들도 모듈로 되기를 요구하는 것 같다.
geoip 모듈은 제일 하단에 옵션이 추가되어 있는 것을 확인할 수 있을 것이다. connlimit 모듈은 중간 쯤에 나온다.

# make bzImage
# make modules
# make modules_install
# make install

대략 1시간 안팎으로 시간이 소요될 것이다. 스타 배틀넷을 서너번 하고 돌아와 보면 어느덧 컴파일이 다 되어 있는 것을 확인할 수 있다. ^^
커널컴파일을 끝내면 /boot/grub/grub.conf 파일을 편집하여 새로운 커널로 부팅될 수 있도록 하고 시스템을 리부팅한다. lsmod 커맨드로 xt_geoip, xt_connlimit 모듈이 올라와 있나 확인하고 없다면...

# depmod -a
# modprobe xt_geoip
# modprobe xt_connlimit

위 커맨드들을 이용하여 모듈을 로딩해 본다. 잘 올라올 것이다.
이제 iptables 작업으로 넘어간다.


4. patch-o-matic-ng로 패치된 iptables 소스컴파일 설치

 여기서는 기존의 rpm 버전 iptables를 삭제하지 않고 그 위에 소스컴파일로 덮어씌우는 방식을 설명한다. 왜냐하면 rpm 버전을 삭제한 뒤 소스로 새롭게 설치하게 되면 기존의 rpm 버전에서 제공하던 system-config-securitylevel, lokkit, /etc/rc.d/init.d/iptables 와 같은 실행 스크립트 파일이 존재하지 않기 때문에 따로 스크립트로 구현하지 않는 한 일일이 iptables 룰을 추가해야 하는 불편함을 감수해야 한다. 다행스럽게도 iptables를 소스로 설치하게 되면 바이너리 파일, 환경설정 파일, 라이브러리 등이 rpm 버전과 거의 동일한 경로에 설치되므로 rpm 버전 위에 덮어 씌워 설치하면 기존의 관련 명령어를 그대로 활용할 수 있다는 장점이 있다.

# cd /usr/src/iptables
# ./configure
# make

여기까지 진행하였다면 아마 아래와 같은 에러를 내며 컴파일이 중단될 것이다.

CC       libxt_geoip.oo
libxt_geoip.c:28:38: warning: linux/netfilter/xt_geoip.h: 그런 파일이나 디렉토리가 없음
libxt_geoip.c: In function 'geoip_help':
libxt_geoip.c:44: error: 'IPTABLES_VERSION' undeclared (first use in this function)
libxt_geoip.c:44: error: (Each undeclared identifier is reported only once
libxt_geoip.c:44: error: for each function it appears in.)
libxt_geoip.c: At top level:
libxt_geoip.c:69: warning: no previous prototype for 'get_country_subnets'
libxt_geoip.c: In function 'get_country_subnets':
libxt_geoip.c:72: warning: declaration of 'index' shadows a global declaration
/usr/include/string.h:304: warning: shadowed declaration is here
libxt_geoip.c:99: warning: implicit declaration of function 'COUNTRY'
libxt_geoip.c:99: warning: too few arguments for format
libxt_geoip.c:119: error: invalid application of 'sizeof' to incomplete type 'struct geoip_subnet'
libxt_geoip.c:125: error: invalid application of 'sizeof' to incomplete type 'struct geoip_subnet'
libxt_geoip.c: In function 'load_geoip_cc':
libxt_geoip.c:137: error: invalid application of 'sizeof' to incomplete type 'struct geoip_info'
libxt_geoip.c:142: error: dereferencing pointer to incomplete type
libxt_geoip.c:142: error: dereferencing pointer to incomplete type
libxt_geoip.c:143: error: dereferencing pointer to incomplete type
libxt_geoip.c: In function 'parse_geoip_cc':
libxt_geoip.c:196: error: 'XT_GEOIP_MAX' undeclared (first use in this function)
libxt_geoip.c: In function 'geoip_parse':
libxt_geoip.c:228: error: 'XT_GEOIP_SRC' undeclared (first use in this function)
libxt_geoip.c:228: error: 'XT_GEOIP_DST' undeclared (first use in this function)
libxt_geoip.c:249: error: 'XT_GEOIP_INV' undeclared (first use in this function)
libxt_geoip.c:251: error: dereferencing pointer to incomplete type
libxt_geoip.c:251: error: dereferencing pointer to incomplete type
libxt_geoip.c:251: error: dereferencing pointer to incomplete type
libxt_geoip.c:252: error: dereferencing pointer to incomplete type
libxt_geoip.c:253: error: dereferencing pointer to incomplete type
libxt_geoip.c: In function 'geoip_print':
libxt_geoip.c:274: error: dereferencing pointer to incomplete type
libxt_geoip.c:274: error: 'XT_GEOIP_SRC' undeclared (first use in this function)
libxt_geoip.c:278: error: dereferencing pointer to incomplete type
libxt_geoip.c:282: error: dereferencing pointer to incomplete type
libxt_geoip.c:282: error: 'XT_GEOIP_INV' undeclared (first use in this function)
libxt_geoip.c:285: error: dereferencing pointer to incomplete type
libxt_geoip.c:286: error: dereferencing pointer to incomplete type
libxt_geoip.c:286: warning: too few arguments for format
libxt_geoip.c: In function 'geoip_save':
libxt_geoip.c:296: error: dereferencing pointer to incomplete type
libxt_geoip.c:296: error: 'XT_GEOIP_INV' undeclared (first use in this function)
libxt_geoip.c:299: error: dereferencing pointer to incomplete type
libxt_geoip.c:299: error: 'XT_GEOIP_SRC' undeclared (first use in this function)
libxt_geoip.c:303: error: dereferencing pointer to incomplete type
libxt_geoip.c:304: error: dereferencing pointer to incomplete type
libxt_geoip.c:304: warning: too few arguments for format
libxt_geoip.c: At top level:
libxt_geoip.c:311: error: 'IPTABLES_VERSION' undeclared here (not in a function)
libxt_geoip.c:312: error: invalid application of 'sizeof' to incomplete type 'struct xt_geoip_match_info'
libxt_geoip.c:313: error: invalid use of undefined type 'struct xt_geoip_match_info'
make[2]: *** [libxt_geoip.oo] 오류 1
make[2]: Leaving directory `/usr/src/iptables-20081028/extensions'
make[1]: *** [all-recursive] 오류 1
make[1]: Leaving directory `/usr/src/iptables-20081028'
make: *** [all] 오류 2
[root@localhost iptables]#

아래와 같이 작업하고 난 뒤 다시 컴파일해 보자.

# cp /usr/src/patch-o-matic-ng-20081028/patchlets/geoip/linux-2.6/include/linux/netfilter/xt_geoip.h /usr/src/iptables-20081028/include/linux/netfilter/
# make

그러면 또 아래와 같은 에러에 가로막힐 것이다.

make  all-recursive
make[1]: Entering directory `/usr/src/iptables-20081028'
Making all in extensions
make[2]: Entering directory `/usr/src/iptables-20081028/extensions'
  CC       libxt_geoip.oo
libxt_geoip.c: In function 'geoip_help':
libxt_geoip.c:44: error: 'IPTABLES_VERSION' undeclared (first use in this function)
libxt_geoip.c:44: error: (Each undeclared identifier is reported only once
libxt_geoip.c:44: error: for each function it appears in.)
libxt_geoip.c: At top level:
libxt_geoip.c:69: warning: no previous prototype for 'get_country_subnets'
libxt_geoip.c: In function 'get_country_subnets':
libxt_geoip.c:72: warning: declaration of 'index' shadows a global declaration
/usr/include/string.h:304: warning: shadowed declaration is here
libxt_geoip.c: At top level:
libxt_geoip.c:311: error: 'IPTABLES_VERSION' undeclared here (not in a function)
make[2]: *** [libxt_geoip.oo] 오류 1
make[2]: Leaving directory `/usr/src/iptables-20081028/extensions'
make[1]: *** [all-recursive] 오류 1
make[1]: Leaving directory `/usr/src/iptables-20081028'
make: *** [all] 오류 2
[root@localhost iptables]#

iptables 의 소스에서 /{iptables}/include/xtables.h 를 다음과 같이 수정하면 된다.

[기존 코드]
#define XTABLES_VERSION "1.4.1.1"
#define XTABLES_VERSION_CODE (0x10000 * 1 + 0x100 * 4 + 1)
#define XTABLES_API_VERSION(x,y,z)    (0x10000*(x) + 0x100*(y) + z)

[추가할 코드]
#define IPTABLES_VERSION "1.4.2"

다시 컴파일해 보면 이제 문제없이 넘어간다.

# make
# make install

※ 컴파일 중 중간에 아래와 같은 경고 구문이 뜨긴 하는데 의미는 모르겠음...
설치는 무난하게 되는 듯 하다.

CCLD     libxt_dscp.so
  CC       libxt_esp.oo
  CCLD     libxt_esp.so
  CC       libxt_geoip.oo
libxt_geoip.c:69: warning: no previous prototype for 'get_country_subnets'
libxt_geoip.c: In function 'get_country_subnets':
libxt_geoip.c:72: warning: declaration of 'index' shadows a global declaration
/usr/include/string.h:304: warning: shadowed declaration is here

  CCLD     libxt_geoip.so
  CC       libxt_hashlimit.oo

이제 기존의 rpm 버전 iptables에서 사용되던 명령어들을 삭제하고 새로이 설치한 소스 버전의 명령어들로 교체하는 작업이 필요하다.
/sbin 디렉토리안의 iptables 관련 명령 삭제 후, /usr/local/sbin 아래에 생성된 iptables 관련 명령들을 심볼릭 링크한다.(총 8개 명령)

# ls /usr/local/sbin
ip6tables        ip6tables-restore  iptables        iptables-restore
ip6tables-multi  ip6tables-save     iptables-multi  iptables-save
# ln -s /usr/local/sbin/ip6tables /sbin
# ln -s /usr/local/sbin/ip6tables-restore /sbin
# ln -s /usr/local/sbin/iptables /sbin
# ln -s /usr/local/sbin/iptables-restore /sbin
# ln -s /usr/local/sbin/ip6tables-multi /sbin
# ln -s /usr/local/sbin/ip6tables-save /sbin
# ln -s /usr/local/sbin/iptables-multi /sbin
# ln -s /usr/local/sbin/iptables-save /sbin

이제 iptables 버전을 확인해 보면 업그레이드된 버전임을 알 수 있다.

# iptables -V
iptables v1.4.2


5. geoip database 설치

국가 DB 생성 및 최신 정보로 업데이트

일단 알아두어야 할것은 geoip 모듈은 /var/geoip 경로의 DB파일 참조한다.
cvs2bin 툴을 이용하여 매월1일 업데이트 되는 geoip database를 생성한다.
   
툴 다운로드후 설치 및 CSV 파일 변환
wget http://people.netfilter.org/peejix/geoip/tools/csv2bin-20041103.tar.gz

# tar -xvzf csv2bin-20041103.tar.gz
# cd csv2bin
# make

국가별 DB를 다운로드한다.
# wget http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip

unzip GeoIPCountryCSV.zip
압축을 풀면 GeoIPCountryWhois.csv 파일이 나온다. csv2bin 폴더 안에 넣어주고,

실행파일로 만들어 준다. chmod 755 GeoIPCountryWhois.csv

그다음  ./csv2bin ./GeoIPCountryWhois.csv 동시에 실행해 주면 geoipdb.bin 과 geoipdb.idx 파일이 생성된다.

mkdir /var/geoip   -> var 에 geoip 폴더는 만들고
cp geoipdb.bin /var/geoip/   -> 방금 생성되었던 두 파일을 /var/geoip/ 에 복사해준다.
cp geoipdb.idx /var/geoip/


참고로 이 메뉴얼 그대로 적용해서 성공하셨다면 recent, strings 모듈도 사용 가능합니다. 커널 컴파일 시 Core Netfilter Configuration 의 메뉴 전체를 <M> 체크하고 컴파일하셨다면 말입니다. 다행히도 요즘 iptables에는 recent, strings도 기본 익스텐션 포함이 되어 있는 관계로 patch-o-matic-ng로 별도 패치할 필요가 없네요.
strings 룰 설정 시 아래와 같은 에러가 난다면...

iptables v1.3.4: STRING match: You must specify `--algo'
Try `iptables -h' or 'iptables --help' for more information.

iptables -A INPUT -p tcp --dport 80 -m string --string "/default.ida?" --algo kmp -j REJECT

geoip만 신경써서 수동으로 패치해 쓰면 iptables로 외부 침입에 대비할 수 있는 웬만한 룰 설정은 모두 가능해지겠습니다. DDOS 공격 대비에 조금이나마 도움이 되는 글이 되었음 하는 바입니다.^^


출처 : https://www.sulinux.net/
728x90

댓글