안녕하세요, SATAz입니다.
이번 포스팅은 IPTables에 대해서 소개드리는 일곱 번째 내용입니다.
지난 포스팅에서는 IPTables 때문에 접속속도가 느려지는 것에 대한 비교 및 조치방법에 대해서 다루었는데요,
이번 포스팅은 IPTables를 활용한 Flooding 공격을 방어하는 방법에 대해서 알려드리고자 합니다.
다만 IPTables에서는, Flooding 공격을 방어하는 데에 다양한 방법이 사용되기 때문에 여러 포스팅에 나눠서 설명드리려고 합니다.
오늘의 포스팅은 [IPTables] 4. -m 옵션의 사용 방법 [INPUT] 포스팅에 잠시 언급되었던
connlimit 매치를 이용해서 Flooding 공격 피해를 완화시키는 방법에 대해서 설명드리겠습니다. (connlimit는 완화라는 표현이 더 어울리겠네요 ;;)
지난 포스팅보기
[IPTables] 1.공짜방화벽 IPTables 설치하기 - CentOS 6/7 - 2017.06.24
[IPTables] 2.특정 아이피의 차단과 허용 [INPUT] - 2017.06.25
[IPTables] 3.특정 서비스 포트의 차단과 허용 [INPUT] - 2017.07.02
[IPTables] 4. -m 옵션의 사용 방법 [INPUT] - 2017.07.08
[IPTables] 5. IPTables에 의해 FTP가 차단되는 경우를 확인하자 [INPUT] - 2017.07.22
[IPTables] 6. IPTables를 사용해서 접속이 느려진다면? [INPUT] - 2017.07.23
▣주의!!! : 이 블로그에 작성된 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 GET Flooding 공격 툴을 하나 입수하여, 공격을 진행해보도록 하겠습니다.
공격 프로그램은 따로 공개하지 않고, 그의 결과가 어떻게 나오는지 확인해보도록 하겠습니다.
# netstat 상태 - DOS 공격 (SYN Flooding GET 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 GET 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
차단되었다는 메시지가 확인되실 것입니다. (DoS성 SYN Flooding 동격도 동일합니다.)
3. 방화벽 설정을 걸기 전에! connlimit의 한계를 알고, 실 서비스에 적용하자
위와같이... 패킷이 차단되는 것을 확인하실 수 있습니다. 하지만 여기에는 함정이 두가지 있습니다.
1. 공격자가 3번 이상 공격을 못하는 만큼!! 정상적인 서비스 이용자도 동시에 3번 이상 세션을 맺을 수 없다.
2. 특정 아이피에 대해서 3번이상 접근하는 것을 차단하기 때문에, 아이피를 변조하게되면 차단할 수가 없다.
1번 함정의 경우, 세션 1개를 끊지 않는 이상 새로운 세션이 연결될 수가 없습니다.
해결 방법으로는 세션 연결 개수를 늘려주는 방법도 있겠지만... 무작정 세션 개수를 늘리는 것도 공격을 방어하는데에 아무런 의미가 없을 수도 있습니다.
이런 경우에는 -m 옵션에서 limit, hashlimit, recent 매치를 이용해서 방어가 가능합니다.
다른 매치로 방어하는 방법은 다음 포스팅에서 설명드리도록 하겠습니다.
2번 함정의 경우, POSTROUTING을 이용해서 방어가 가능한 것으로 알고있습니다.
이정도되면 정말 DDOS 방어 장비를 iptables로 만든다고 할 수 있을 것 같네요.... 2번 함정에 대해서는 제가 더 iptables에 대해서 공부한다음에 말씀 드릴 수 있을 것 같습니다.
4. 안되는 것은 알지만... DDOS가 들어오면 어떻게 될까?
제가 누구입니까!!! DDOS 공격 툴을 하나 입수했습니다.
2번의 경우에는 어떠한 상태가 나오는지 확인해보도록 하겠습니다.
공격 프로그램은 따로 공개하지 않고, 그의 결과가 어떻게 나오는지 확인해보도록 하겠습니다.
# netstat 상태 - DDOS 공격 (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번 함정의 제한 없이 사용하는 방법에 대해서 설명드리도록 하겠습니다.
긴 글 읽어주셔서 감사합니다 ^^
'보안 Story > IPTables' 카테고리의 다른 글
[IPTables] 9. IPTables로 Flooding 공격을 막아보자! - 3 [INPUT / hashlimit] (9) | 2017.08.05 |
---|---|
[IPTables] 8. IPTables로 Flooding 공격을 막아보자! - 2 [INPUT / recent] (0) | 2017.07.30 |
[IPTables] 6. IPTables를 사용해서 접속이 느려진다면? [INPUT] (2) | 2017.07.23 |
[IPTables] 5. IPTables에 의해 FTP가 차단되는 경우를 확인하자 [INPUT] (4) | 2017.07.22 |
[IPTables] 4. -m 옵션의 사용 방법 [INPUT] (3) | 2017.07.08 |