Linux #7 : Dos / DDos 공격에 대한 대처법. #1

수 많은 Site들이 Dos / DDos 공격으로 인해 피해를 보고 있다. 필자도 일본에선 별로 느껴보진 못했지만, 미국에 와서 Dos / Ddos 공격을 여러번 경험하고 실제 지금도 항상 Hacker들을 경계하고 있습니다. 그럼, Dos / DDos 공격이란 무엇인지 먼저 알아보죠.

Dos 공격이란 Daniel of Service attacks의 약자로 Network의 대역을 소비하게 만들거나, 대량의 request를 Server에 보내 connection을 증가시켜 Server를 사용 불능 상태로 만들거나, 더불어 Password를 알아내기 위해 여러 방법을 통해 접근을 시도하는 Brute Force 공격등도 행해지는데,  공격 주체가 1대의 host라면 특정가능하여 해당 IP를 제한하면 되지만 (여기까지가 Dos), 이 공격 주체가 특정할 수 없는 다수일 경우 DDos (Distributed Denial of Service) 공격이라하고, 이를 방지하기 위해선 다른 방법이 필요합니다.

그럼, Dos / DDos와 관련 된 여러 공격에 대한 대처 방법에 대해서 알아보도록 하죠.

SYN Flooding 공격

기본적으로 TCP Packet은 3 Way Handshaking에 의해 초기 Session이 이루어지게 되는데, 즉 SYN -> SYN / ACK -> ACK로 완료가 이루어져야 하지만 정상적인 Session으로 종료가 가능하지만, SYN Packet을 요청하고 SYN / ACK Packet을 Server에서 보내려고 할 때 보내려는 주소가 무의미한 주소여서 Server가 해당 Session을 대기상태 (SYN_RECV)에 놓게 되어 Server 대기 Queue의 증가로 인한 Server Resource가 증가로 정상동작을 할 수 없게 만드는 공격을 말합니다.

확인은 일단 Server가 비정상적으로 느려지고, 접속히 원활하지 않게 되며 netstat 명령어를 통해 SYN_RECV의 수를 체크 했을 시 SYN_RECV의 대기 Queue가 많이 증가하였다고 의심해 볼 필요가 있습니다.

# netstat -an | grep SYN_RECV
...
tcp        0      0 ::ffff:xxx.xxx.xxx.xxx:80    ::ffff:xxx.xxx.xxx.xxx:28719  SYN_RECV
tcp        0      0 ::ffff:xxx.xxx.xxx.xxx:80     ::ffff:xxx.xxx.xxx.xxx:61544   SYN_RECV
...

대처 방법은 아래와 같이 3가지가 있습니다.
첫번째는 Backlog size를 증가시켜 주는 방법으로 Default값에서 1024 ~ 그 이상의 값을 설정합니다.

# SYN Flooding attack block (need to increase backlog size)
net.ipv4.tcp_max_syn_backlog=16000

이 설정을 하게 됨으로 얼마정도 버틸 수 있게 되지만 지속적으로 공격을 당했을 경우 queue가 꽉차게 됨으로 두번째인 SYN Cookies도 활성화를 시켜야 합니다. SYN Cookies가 활성화가 되면 ACK 중에 포함된 확인 응답 번호를 계산하여, 올바른 Session인지를 확인하게 됩니다. Session이 올바른 경우 처리를 행하고, 그렇지 않은 경우의 Connection에 대해서는 System Resource를 낭비하는 걸 막을 수 있습니다.

# Activate SYN Cookies
net.ipv4.tcp_syncookies=1

1인 경우가 활성화된 상태이고, 0인 경우가 비활성 상태입니다. 이 두개의 값은

# echo '16000' > /proc/sys/net/ipv4/tcp_max_syn_backlog
# echo '1' > /proc/sys/net/ipv4/tcp_syncookies

와 같이 설정가능하고 또한,

# sysctl -w net.ipv4.tcp_max_syn_backlog=16000
# sysctl -w net.ipv4.tcp_syncookies=1

또, /etc/sysctl.conf에 추가를 한 뒤

# sysctl -p /etc/sysctl.conf

로도 가능합니다. /etc/sysctl.conf에 넣었을 경우 System Reboot시 자동으로 등록이 되게 됩니다. SYN Cookies를 활성화 하면 확인 응답번호의 계산에 따른 Packet처리에서 Overhead가 발생하게 되고, Packet 량에 따라 CPU 사용량이 증가하여 Bottleneck이 발생 할 가능성이 있습니다.
그리고, 마지막으로 Iptable을 이용하여 비정상적은 IP를 block하면 됩니다.

운영상의 편의를 위해 아래와 같이 Script를 작성해 보았습니다.

### Block_SYN_Flooding.sh
#!/bin/sh
# ================================================================
# -script name
# Block_SYN_Flooding.sh
# -script desc
# Block DDos Attack through the SYN Flooding
# -how to use
# ./Block_SYN_Flooding.sh $1 $2
# $1 Type
# $2 List File
# -NOTE
#
# -directory
# /home/scripts/security
# -create date
# 2010/06/22 NHN USA)Jeff KIM
# -Update
#
# ----------------------------------------------------------------
# -internal variable
# BASE Common lib directory
# LIB_ENV Location of env file
# FUNCTION Location of function file
# SCRIPT_NAME Script name
# APP_VERSion Application & History Number
# ================================================================
BASE=/home/scripts
SCRIPT_NAME="Block_SYN_Flooding.sh"
LIB_ENV=$BASE/setenv.conf
FUNCTION=$BASE/function
APP_VERSION=$BASE/app_version
. $LIB_ENV
. $FUNCTION
. $APP_VERSION
##################################################################
# start script
Startscript
Whoamiroot
MENU_INIT="[ start | stop | start_pp | stop_pp ]"
function Read_Iplist_File {
if [ "${IPS}" == "" ];then
Printmsg "ERROR" "Please, Input IP List File Path!"
Endscript
else
if test -r ${IPS};then
iRC=$?
if [ ${iRC} -eq 0 ];then
chkFile=1
else
chkFile=0
Printmsg "ERROR" "${2} File is not existed."
fi
fi
fi
}
if [ "${1}" == "" ];then
Printmsg "ERROR" "Please, Input Type (Usage: ${MENU_INIT} ) correctly!"
Endscript
else
TYPE=${1}
IPS=${2}
case ${TYPE} in
start)
PRC_NAME="Start IPtables to block ${2}.........."
Startprocess
Read_Iplist_File
if [ "${chkFile}" == "1" ];then
for ipaddress in `cat ${2}`;do
Printmsg "NOTICE" "/sbin/iptables -A INPUT -s ${ipaddress} -j DROP"
/sbin/iptables -A INPUT -s ${ipaddress} -j DROP
done
/sbin/iptables -L
fi
/etc/init.d/iptables save
/etc/init.d/iptables restart
Endprocess
;;
stop)
PRC_NAME="Stop IPTables to remove ${2}.........."
Startprocess
Read_Iplist_File
if [ "${chkFile}" == "1" ];then
for ipaddress in `cat ${2}`;do
Printmsg "NOTICE" "/sbin/iptables -D INPUT -s ${ipaddress} -j DROP"
/sbin/iptables -D INPUT -s ${ipaddress} -j DROP
done
/sbin/iptables -L
fi
/etc/init.d/iptables save
/etc/init.d/iptables stop
Endprocess
;;
start_pp)
PRC_NAME="Start IPtables to block SYN,FIN,RST from ALL IPs.........."
Startprocess
Printmsg "NOTICE" "/sbin/iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP"
/sbin/iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
Printmsg "NOTICE" "/sbin/iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP"
/sbin/iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
Printmsg "NOTICE" "/sbin/iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP"
/sbin/iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
Printmsg "NOTICE" "/sbin/iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP"
/sbin/iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
/sbin/iptables -L
/etc/init.d/iptables save
/etc/init.d/iptables restart
Endprocess
;;
stop_pp)
PRC_NAME="Stop IPTables to remove SYN,FIN,RST from ALL IPs.........."
Startprocess
Printmsg "NOTICE" "/sbin/iptables -D INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP"
/sbin/iptables -D INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
Printmsg "NOTICE" "/sbin/iptables -D INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP"
/sbin/iptables -D INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
Printmsg "NOTICE" "/sbin/iptables -D INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP"
/sbin/iptables -D INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
Printmsg "NOTICE" "/sbin/iptables -D INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP"
/sbin/iptables -D INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
/sbin/iptables -L
/etc/init.d/iptables save
/etc/init.d/iptables stop
Endprocess
;;
*)
Printmsg "ERROR" "Please, Input Type (Usage: ${MENU_INIT} ) correctly!"
Endscript
;;
esac
fi
Endscript

위 Script에서 4개의 선택 메뉴가 있는데, MENU_INIT=”[ start | stop | start_pp | stop_pp ]”
start / stop은 Block_SYN_Flooding.sh start [IP_List_file]과 같이 IP List File을 지정하면 각 IP를 Block 할 수 있도록 되어 있습니다.
Stop을 하면 해제가 되구요. start_pp / stop_pp에 대해서는 IP가 너무많아 대응하기 힘든 경우 SYN Flooding과 관련 된 것들을 Iptable에서 몽땅 Drop 해버리는 겁니다. 실제 Web Service에서 문제없이 사용하고 있습니다. 그러나, 제가 다른 서비스에 대해서는 보장 못 해드립니다. ^ ^;

SYN Flooding 공격에 대한 대처법은 여기까지입니다.  Linux : Dos / DDos 공격에 대한 대처법. #2에서는 Smurf 공격 및 Spoofing 대처법 등에 대해서 다루도록 하겠습니다.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.