강좌
클라우드/리눅스에 관한 강좌입니다.
해킹&보안 분류

iptables의 상태추적(Connection tracking 또는 Stateful Inspection)

작성자 정보

  • 관리자 작성
  • 작성일

컨텐츠 정보

본문

iptables의 상태추적(Connection tracking 또는 Stateful Inspection)






 

앞에서 언급한 바와 같이 개선된 iptables의 가장 큰 특징 중 하나는 바로 상태추적 기능을 제공한다는 것이었다.

 

 

 

 

상태추적 기능이 제공되지 않는(stateless) ipchains와 같은 이전의 방화벽 툴에서는 각각의 패킷을 별개로 따로 따로 파악하여 필터링하였지만, 상태 추적이 제공되는 iptables에서는 메모리에 남아있는 이전의 접속 목록(소스와 목적지 IP, 포트번호, 프로토콜 타입, 연결 상태 및 타임아웃 등)을 함께 참고하게 된다.

 

 

 

 

따라서 방화벽을 통과하는 패킷의 목록 테이블을 계산하고 유지하기 위해 어느 정도의 메모리를 소모하게 된다는 단점이 있기는 하지만 보안의 관점에서 stateless 방화벽보다 더욱 안전하다고 할 수 있다.

 

 

 

 

이때 소모하는 메모리 사이즈는 커널 버전 및 시스템의 설정에 따라 조금씩 다른데, 아래 예와 같이 cat /proc/slabinfo를 실행하면 확인할 수 있다.

 

 

 

 

 

 

# cat /proc/slabinfo

slabinfo - version: 2.1 (SMP)

 

ip_conntrack 848 1716 320 86 143 1 : 124 62

 

 

 

여기에서 위의 값이 의미하는 바는 각각 cache 이름, activeobject 개수, object 개수, object의 사이즈, objectactiveblocks의 개수, object slab의 개수, slab당 페이지 개수이다.

 

 

 

 

그리고 부팅 시 dmesg 또는 /var/log/dmesg 파일을 보면 얼마만큼 메모리를 소모하는지 알 수 있는데, 아래의 경우 한 conntrack208 byte를 소모하는 것을 알 수 있다.

 

 

 

 

 

ip_conntrack version 2.4 (4094 buckets, 32752 max) - 208 bytes per conntrack

 

 

 

 

참고로 상태추적 기능을 이용하려면 커널 2.6.x는 앞에서 살펴보았고 커널 2.4.x 계열의 경우 Networking options ---> IP: Netfilter Configuration ---> 메뉴에서

“<*> Connection state match support”가 선택되어야 하며 만약 모듈로 선택되어 있는 경우라면 ip_conntrack.o 모듈이 로딩되어 있어야 한다.

 

 

 

 

물론 커널에서 정적으로 선택되어 있거나 모듈로 올라와 있는 상태에서 상태추적 옵션인 "-m state --state"를 사용할 수 있으며 그렇지 않으면 사용할 수 없다.

 

 

 

 

물론 상태 추적을 사용하지 않는다면 모듈로 포함하였을 경우, 해당 모듈을 unload하면 되지만 커널에 정적으로 포함하였을 경우에는 비활성화 방법이 없으므로 커널 메뉴에서 Connection state match support를 선택하지 않아야 한다.

 

 

 

 

앞에서도 언급한 바와 같이 상태추적 기능을 커널에서 선택하였다면 iptables를 전혀 사용하지 않아도 상태추적을 하게 된다.

 

 

 

 

따라서 늘 접속이 있을 때마다 일정 정도의 메모리를 소모하게 되므로 방화벽의 용도로 사용하지 않는다면 커널에서 이 메뉴를 선택하지 않는 것이 좋다.

 

 

 

 

현재 시스템에서의 상태추적 테이블은 아래와 같이 실행하면 확인할 수 있다.

 

[root@www root]# cat /proc/net/ip_conntrack

 

149849bbc397a2fb9eb5e4b3545c54a1_1680569594_8855.png
 

[그림] 상태추적 테이블 조회

 

사실상 상태추적 테이블을 살펴볼 일은 없다.

 

 

 

 

그러나 살펴볼 필요가 있다면 위의 결과는 매우 알아보기 힘들기 때문에 상태추적을 쉽게 할 수 있도록 iptstate라는 별도의 프로그램을 이용할 수 있다.

 

 

 

 

이 프로그램은 홈페이지인 http://www.phildev.net/iptstate/에서 파일을 다운로드하여 압축 해제 후 make; make install로 설치하기만 하면 된다.

 

 

 

 

iptstate를 실행해보면 마치 top과 유사한 결과가 나오는 것을 확인할 수 있을 것이다.

 

 

 

 

사용할 수 있는 옵션은 다음과 같다.

 

# iptstate -b

d: 목적지 IP를 기준으로 분류

p: 프로토콜별로 분류

s: 상태별로 분류

t: TTL별로 분류

단지 “iptstate -b”만 실행하면 소스 IP를 기준으로 분류하게 되고 “iptstate -b d”를 실행하면 목적지 IP를 기준으로 분류하게 된다.

 

 

149849bbc397a2fb9eb5e4b3545c54a1_1680569611_5445.png
 

[그림] iptstate 실행화면

 

그러나 상태추적은 시스템에서 무한정 할 수 있는 것은 아니며 최대 수치로 지정된 만큼만 할 수 있는데, 만약 이 수치를 넘는 동시 접속이 있을 경우에는 더 이상의 상태 추적을 하지 않고 끝나는 것이 아니라 커널에서 아예 더 이상의 접속을 받아들이지 않게 된다.

 

 

 

 

따라서 접속이 많은 사이트는 접속이 되었다 안되었다를 반복하거나 아예 서버가 다운된 것처럼 보이게 되므로 주의하여야 한다.

 

 

 

 

현재 시스템에서 추적할 수 있는 최대 상태추적 테이블 개수는 아래와 같이 확인할 수 있다.

 

[root@www /root]# cat /proc/sys/net/ipv4/ip_conntrack_max

32768

참고로, 현재 위 시스템의 경우 상태추적 테이블이 총 32768개로 제한되어 있는데, 여기에서 주의해야 할 점이 있다.

 

 

 

 

, 상태추적 테이블에 목록이 있다고 해서 반드시 접속해 있는 상태만은 아니며 접속을 끊었다 하더라도 timeout내 일정 시간동안은 상태추적 테이블에 남아있게 된다는 것이다.

 

 

 

 

또한 대상 서버로 향하는 유니캐스트 패킷뿐만 아니라 브로드캐스트 패킷 등도 이 목록에 포함되어 있다는 점을 주의하기 바란다.

 

 

 

 

 

 

따라서 이러한 것을 고려하여 테이블 개수를 지정하여야 하는데, 만약 테이블 개수를 너무 높게 설정할 경우에는 불필요한 메모리를 낭비하게 되고, 테이블 개수를 너무 적게 설정할 경우에는 아예 접속이 되지 않는 문제가 발생할 수 있으므로 실제로 상태 추적을 서비스에 적용하기 전에 정상적인 최대 테이블 개수는 어느 정도인지 먼저 모니터링을 하기 바란다.

 

 

 

 

현재 상태추적 테이블 목록의 개수를 확인하려면 커널 2.6.에서는 “sysctl -n

net.ipv4.netfilter.ip_conntrack_count“ 값을 보면 실시간으로 확인 가능하고 커널 2.4에서는 별도의 방법이 없으므로 “cat /proc/net/ip_conntrack|wc -l”를 실행해 보면 되는데, 접속이 많은 사이트에서는 목록을 계산하느라 일시적으로 서비스가 중지될 수 있으니 주의하기 바란다.

 

 

 

 

일반적인 웹 서버라면 32768 정도면 충분할 것이다.

 

 

 

 

다시 한 번 강조하지만 상태추적을 필요로 하는 방화벽을 사용하지 않는다면 이 설정을 반드시 off할 것을 권장한다.

 

앞에서 한 conntrack208byte 정도를 소모한다고 하였으므로 현재의 conntrack 수를 계산하면 방화벽에서 상태 추적시 최소한 어느 정도의 커널 메모리를 소모 하는지 계산할 수 있다.

 

 

 

 

,

# sysctl -n net.ipv4.netfilter.ip_conntrack_count

위의 결과가 17000일 경우

(17000*208)/1024/1024 = 3M 정도 커널 메모리를 소모하는 것을 알 수 있다.

 

 

 

 

사실상 메모리를 그렇게 많이 소모하는 것은 아니라는 것을 알 수 있다.

 

만약 서버 운영 중 서버가 다운된 것은 아닌데, 접속이 안되거나 ping을 해 보면 packet loss가 심한 경우가 있다.

 

 

 

 

이러한 경우 dmesg를 실행해 보거나 /var/log/messages 파일을 살펴보고서 아래와 같은 메시지가 보이는지 확인해 보기 바란다.

 

 

 

 

 

ip_conntrack: table full, dropping packet.

 

이는 앞에서 말한 바와 같이 ip_conntrack_max 값을 초과한 접속 시도가 있었기 때문인데, 이러한 경우 이 값을 적절히 늘려줄 필요가 있다.

 

 

 

 

 

 

최대 테이블 개수를 설정하는 명령어는 다음과 같다.

 

[root@www /root]# sysctl -w net.ipv4.ip_conntrack_max=100000

또는

[root@www /root]# echo 100000 > /proc/sys/net/ipv4/ip_conntrack_max

 

위는 이 값을 10만으로 설정해 준 것이며 이 설정을 rc.local에도 설정해 주어야 재부팅 후에도 적용이 된다.

 

 

 

 

만약 위와 같이 테이블이 full되었다는 메시지가 나면 기존의 값에 3-5배 정도의 값을 설정해 준 후 full 메시지가 나는지 확인해 보고, 여전히 메시지가 나면 적절히 조금씩 값을 늘려주면 된다.

 

 

 

 

아마 게임 서버 등 특정한 컨텐츠를 제공하는 서버에서 패킷의 양이 많은 일부 서비스를 제외하고는 일반적인 서비스를 하는 서버라면 이 값을 늘려줄 필요는 없을 것이다.

 

 

 

 

 

 

그렇다면 상태추적은 언제까지 진행될까? 물론 상태 추적에도 timeout이 정의되어 있어 이 시간 동안에만 상태 추적을 하도록 되어 있다.

 

 

 

 

각 패킷의 상태에 대한 상태 추적 timeoutudp 패킷의 경우 /usr/src/linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c

tcp 패킷의 경우 /usr/src/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 파일에 정의되어 있다.

 

 

 

 

아래는 tcp 패킷의 timeout 예이다.

 

 

 

 

 

 

TCP_CONNTRACK_ESTABLISHED: 5

TCP_CONNTRACK_SYN_SENT : 2   

TCP_CONNTRACK_SYN_RECV : 60   

TCP_CONNTRACK_FIN_WAIT : 2   

TCP_CONNTRACK_TIME_WAIT : 2     

TCP_CONNTRACK_CLOSE : 10   

TCP_CONNTRACK_CLOSE_WAIT : 60     

TCP_CONNTRACK_LAST_ACK : 30 

TCP_CONNTRACK_LISTEN : 2

 

또는, 최근의 patch-o-matic에서는 sysctl을 통해 timeout을 지정할 수 있는 기능을 제공하는데, 이 기능을 설정할 경우 다음과 같이 conntrack timeout을 지정할 수 있는 것을 알 수 있다.

 

 

 

 

물론 정상적인 상황에서 이 값을 변경할 필요는 없을 것이다.

 

# sysctl -a|grep conntrack

net.ipv4.ip_conntrack_max = 32768

net.ipv4.netfilter.ip_conntrack_generic_timeout = 600

net.ipv4.netfilter.ip_conntrack_icmp_timeout = 30

net.ipv4.netfilter.ip_conntrack_udp_timeout_stream = 180

net.ipv4.netfilter.ip_conntrack_udp_timeout = 30

net.ipv4.netfilter.ip_conntrack_tcp_timeout_close = 10

net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120

net.ipv4.netfilter.ip_conntrack_tcp_timeout_last_ack = 30

net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60

net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120

net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 432000

net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_recv = 60

net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_sent = 120

net.ipv4.netfilter.ip_conntrack_max = 32768

 

 

관련자료

댓글 0
등록된 댓글이 없습니다.

공지사항


뉴스광장


  • 현재 회원수 :  60,037 명
  • 현재 강좌수 :  35,803 개
  • 현재 접속자 :  133 명