본문으로 바로가기



안녕하세요, SATAz입니다.

이번 포스팅은 IPTables에 대해서 소개드리는 일곱 번째 내용입니다.



지난 포스팅에서는 IPTables 때문에 접속속도가 느려지는 것에 대한 비교 및 조치방법에 대해서 다루었는데요,

이번 포스팅은 IPTables를 활용한 Flooding 공격을 방어하는 방법에 대해서 알려드리고자 합니다.


다만 IPTables에서는, Flooding 공격을 방어하는 데에 다양한 방법이 사용되기 때문에 여러 포스팅에 나눠서 설명드리려고 합니다.

오늘의 포스팅은  [IPTables] 4. -m 옵션의 사용 방법 [INPUT]  포스팅에 잠시 언급되었던

connlimit 매치를 이용해서 Flooding 공격 피해를 완화시키는 방법에 대해서 설명드리겠습니다. (connlimit는 완화라는 표현이 더 어울리겠네요 ;;)



▣주의!!! : 이 블로그에 작성된 IPTables 포스팅들은 교육용으로 작성된 내용입니다. 

 서비스 중인 서버에 아래의 내용만 갖고 바로 적용하지 마시고, 서버에 적용 전에 반드시 테스트를 거치시기 바랍니다.  IPTables도 방화벽인지라, 무턱대고 서버에 적용했다가는 서비스 중단되는 사태가 발생할 수 있습니다. 필히 주의하셔야합니다!!!


#IPTables 설정를 위한 환경


- 테스트 머신 : VMware WorkStation 12 Player

- 운영체제 : CentOS/RHEL 7 - 64bit ( Minimal 설치 )

- 메모리 : 2GB

- IPTables Version : iptables v1.4.21

- 서버 아이피 : 192.168.0.18


# 공격을 위한 서버 설정 환경

- 공격자 테스트 머신 : VMware WorkStation 12 Player

- 공격자 운영체제 : CentOS/RHEL 6 - 64bit ( Minimal 설치 )

- 공격자 메모리 : 2GB

- 공격자 서버 아이피 : 192.168.0.19


1. 튜토리얼로 connlimit 를 이용하여 SSH 세션 연결 제한을 걸어보자

 IPTables에는 connlimit라는 매치가 있습니다. connlimit는, 동시에 특정 갯수 이상의 세션을 연결하지 못하도록 설정합니다. 


# connlimit를 이용한 패킷 차단 명령어

iptables -I INPUT -p tcp -d 192.168.0.18  --dport 22 -m connlimit --connlimit-above 3 -j DROP


위의 명령어를 해석하게될 경우, 192.168.0.18 아이피의 22/tcp로 동시에 3번을 초과해서 접속하면, 그 이후의 연결부터는 차단하겠다는 의미가 됩니다.


# 명령어의 적용

[root@localhost ~]# iptables -I INPUT -p tcp --dport 22 -d 192.168.0.18 -m connlimit --connlimit-above 3 -j DROP

[root@localhost ~]# iptables -nL

Chain INPUT (policy ACCEPT)

target     prot opt source               destination         

DROP       tcp  --  0.0.0.0/0            192.168.0.18         tcp dpt:22 #conn src/32 > 3

ACCEPT     all  --  0.0.0.0/0            192.168.0.18         state RELATED,ESTABLISHED

ACCEPT     tcp  --  192.168.0.2          192.168.0.18         tcp dpt:22

ACCEPT     all  --  192.168.0.1          192.168.0.18        

ACCEPT     all  --  8.8.8.8              192.168.0.18        

DROP       all  --  0.0.0.0/0            192.168.0.18        


Chain FORWARD (policy ACCEPT)

target     prot opt source               destination         


Chain OUTPUT (policy ACCEPT)

target     prot opt source               destination   


여기에서 동시에 3번 초과 접속의 의미는, source ip당 세션 3개 까지는 연결하고 있을 수 있지만 4번째 세션부터는 연결할 수가 없다는 것을 의미합니다. 따라서 SSH의 경우에는 4개 세션 이상을 연결할 수가 없습니다.

다시말해서, Established 상태인 것이 3개까지는 유지되고 나머지는 차단한다는 뜻입니다.


# netstat 상태

[root@localhost ~]# netstat -anp | more

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1167/sshd           

tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1906/master         

tcp        0      0 192.168.0.18:22         192.168.0.2:56220       ESTABLISHED 3772/sshd: root@pts 

tcp        0      0 192.168.0.18:22         192.168.0.2:56224       ESTABLISHED 3789/sshd: root@pts 

tcp        0     52 192.168.0.18:22         192.168.0.2:59563       ESTABLISHED 2063/sshd: root@pts 


SSH를 4개 이상 연결하려 했을 때의 netstat 상태입니다. 3개까지만 연결되고, 나머지는 연결되지 않습니다.


2. 본 게임으로 connlimit 를 이용하여 Flooding을 막아보자

그럼 80/tcp (web service)에 적용했을 때에는 어떻게 될까요?


# connlimit를 이용한 패킷 차단 명령어

iptables -I INPUT -p tcp -d 192.168.0.18  --dport 80 -m connlimit --connlimit-above 3 -j DROP

iptables -I INPUT -p tcp --dport 80 -d 192.168.0.18 -m connlimit --connlimit-above 3 -j LOG --log-level 7 --log-prefix "[Im Attacking]"


# 명령어의 적용

[root@localhost ~]# iptables -I INPUT -p tcp -d 192.168.0.18 --dport 80 -j ACCEPT

[root@localhost ~]# iptables -I INPUT -p tcp --dport 80 -d 192.168.0.18 -m connlimit --connlimit-above 3 -j DROP

[root@localhost ~]# iptables -I INPUT -p tcp --dport 80 -d 192.168.0.18 -m connlimit --connlimit-above 3 -j LOG --log-level 7 --log-prefix "[Im Attacking]"

[root@localhost ~]# iptables -nL

Chain INPUT (policy ACCEPT)

target     prot opt source               destination         

LOG        tcp  --  0.0.0.0/0            192.168.0.18         tcp dpt:80 #conn src/32 > 3 LOG flags 0 level 7 prefix "[Im Attacking]"

DROP       tcp  --  0.0.0.0/0            192.168.0.18         tcp dpt:80 #conn src/32 > 3

ACCEPT     tcp  --  0.0.0.0/0            192.168.0.18         tcp dpt:80

ACCEPT     all  --  0.0.0.0/0            192.168.0.18         state RELATED,ESTABLISHED

ACCEPT     tcp  --  192.168.0.2          192.168.0.18         tcp dpt:22

ACCEPT     all  --  192.168.0.1          192.168.0.18        

ACCEPT     all  --  8.8.8.8              192.168.0.18        

DROP       all  --  0.0.0.0/0            192.168.0.18        


Chain FORWARD (policy ACCEPT)

target     prot opt source               destination         


Chain OUTPUT (policy ACCEPT)

target     prot opt source               destination  


일반적으로 사용하시는 것 과 같이, 80번포트에 대해서는 모든 사용자가 접근 가능하도록 설정한 다음에 3번 이상 동시에 접근을 하게 될 경우에 차단하도록 설정했습니다. 거기에 추가적으로, iptables 로그를 남기도록 설정했습니다.

*주의. iptables 로그 남기는 설정은 추가적으로 해주셔야할 것이 있습니다. 이거는 따로 포스팅에서 알려드리겠습니다.

"왜 나는 로그가 쌓이지 않는 것인가?"하시는 분들은 댓글 남겨주시면 미리 알려드리겠습니다.


제가 SYN_Flooding 공격 툴을 하나 입수하여, 공격을 진행해보도록 하겠습니다.

공격 프로그램은 따로 공개하지 않고, 그의 결과가 어떻게 나오는지 확인해보도록 하겠습니다.


# netstat 상태 - DOS 공격 (SYN Flooding)

[root@localhost ~]# netstat -anp | more

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1167/sshd                

tcp        0      0 192.168.0.18:22         192.168.0.2:56220       ESTABLISHED 3772/sshd: root@pts 

tcp        0      0 192.168.0.18:22         192.168.0.2:56224       ESTABLISHED 3789/sshd: root@pts 

tcp        0     52 192.168.0.18:22         192.168.0.2:59563       ESTABLISHED 2063/sshd: root@pts 

tcp6       0      0 :::80                   :::*                    LISTEN      2127/httpd          

tcp6       0      0 :::22                   :::*                    LISTEN      1167/sshd                  

tcp6    1920      0 192.168.0.18:80         192.168.0.19:53119      FIN_WAIT2   2564/httpd          

tcp6       0      0 192.168.0.18:80         192.168.0.19:53117      FIN_WAIT2   2129/httpd          

tcp6       0      0 192.168.0.18:80         192.168.0.19:53118      FIN_WAIT2   2565/httpd      


netstat 상태에서는 세션이 3개 이상 연결되지 않는 것으로 확인되고 있습니다. 그럼 로그는 어떻게 찍히는지 확인해볼까요?


# 로그 상태 - DOS 공격 (SYN Flooding)

[root@localhost log]# tail -f iptables_log 

Jul 29 15:02:01 localhost kernel: [Im Attacking]IN=ens33 OUT= MAC=00:0c:29:a9:76:18:00:0c:29:3d:ed:2e:08:00 SRC=192.168.0.1 DST=192.168.0.18 LEN=45 TOS=0x10 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=3055 DPT=80 WINDOW=65535 RES=0x00 PSH SYN URGP=0 

Jul 29 15:02:01 localhost kernel: [Im Attacking]IN=ens33 OUT= MAC=00:0c:29:a9:76:18:00:0c:29:3d:ed:2e:08:00 SRC=192.168.0.1 DST=192.168.0.18 LEN=45 TOS=0x10 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=9000 DPT=80 WINDOW=65535 RES=0x00 PSH SYN URGP=0 



차단되었다는 메시지가 확인되실 것입니다.


3. 방화벽 설정을 걸기 전에! connlimit의 한계를 알고, 실 서비스에 적용하자

위와같이... 패킷이 차단되는 것을 확인하실 수 있습니다. 하지만 여기에는 함정이 두가지 있습니다.

1. 공격자가 3번 이상 공격을 못하는 만큼!! 정상적인 서비스 이용자도 동시에 3번 이상 세션을 맺을 수 없다.

2. 특정 아이피에 대해서 3번이상 접근하는 것을 차단하기 때문에, 아이피를 변조하게되면 차단할 수가 없다.


1번 함정의 경우, 세션 1개를 끊지 않는 이상 새로운 세션이 연결될 수가 없습니다.

해결 방법으로는 세션 연결 개수를 늘려주는 방법도 있겠지만... 무작정 세션 개수를 늘리는 것도 공격을 방어하는데에 아무런 의미가 없을 수도 있습니다.

이런 경우에는 -m 옵션에서 limit, hashlimit, recent 매치를 이용해서 방어가 가능합니다.

다른 매치로 방어하는 방법은 다음 포스팅에서 설명드리도록 하겠습니다.


2번 함정의 경우, POSTROUTING을 이용해서 방어가 가능한 것으로 알고있습니다.

이정도되면 정말 DDOS 방어 장비를 iptables로 만든다고 할 수 있을 것 같네요.... 2번 함정에 대해서는 제가 더 iptables에 대해서 공부한다음에 말씀 드릴 수 있을 것 같습니다.


4. 안되는 것은 알지만... DDOS가 들어오면 어떻게 될까?


제가 누구입니까!!! DDOS 공격 툴을 하나 입수했습니다.

2번의 경우에는 어떠한 상태가 나오는지 확인해보도록 하겠습니다.

공격 프로그램은 따로 공개하지 않고, 그의 결과가 어떻게 나오는지 확인해보도록 하겠습니다.


# netstat 상태 - DOS 공격 (SYN Flooding)

[root@localhost log]# netstat -anp | more

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    

tcp        0      0 192.168.0.18:80         213.217.219.229:9000    SYN_RECV    -                   

tcp        0      0 192.168.0.18:80         217.211.223.223:1739    SYN_RECV    -                   

tcp        0      0 192.168.0.18:80         220.224.213.210:20000   SYN_RECV    -                   

tcp        0      0 192.168.0.18:80         214.214.210.225:1234    SYN_RECV    -                   

tcp        0      0 192.168.0.18:80         216.213.214.210:4055    SYN_RECV    -                   

tcp        0      0 192.168.0.18:80         211.211.225.216:1739    SYN_RECV    -                   

tcp        0      0 192.168.0.18:80         215.222.214.228:1026    SYN_RECV    -                   

tcp        0      0 192.168.0.18:80         214.219.223.217:20000   SYN_RECV    -                   

tcp        0      0 192.168.0.18:80         213.212.225.222:9000    SYN_RECV    - 

......


이것들 말고... 변조된 아이피 개수 만큼 SYN_RECV를 계속해서 생성하고 있습니다....

물론 IPTables 로그에서도 어떠한 로그가 쌓이지를 않습니다;;




다음 시간에는 connlimit가 아닌 recent 매치를 이용하여, 1번 함정의 제한 없이 사용하는 방법에 대해서 설명드리도록 하겠습니다.

긴 글 읽어주셔서 감사합니다 ^^




댓글을 달아 주세요