최근 관리하고 있는 서버에 DoS성 공격이 유입되어 급하게 상단에 있는 HA Proxy에 Access Log를 기반으로 Request 횟수에 따른 IP Block 기능을 추가 하였다.
현재 서버 운영은 User --> HA Proxy --> Web Server 로 구성이 되어 있다.
전반적인 Process를 아래와 같이 처리 하였다.
1. Proxy 서버에서 ipset을 이용하여 iptables에 Source IP 차단 설정
2. 웹서버에서 Access Log 읽어 지정한 횟수 이상으로 Request 유입시 Block List로 체크 (매분 스크립트로 체크)
# Proxy Server
ipset 기능을 이용하여 list group을 white list, block list 이렇게 2개의 그룹을 생성 하였다. 그룹의 경우 처리 목적에 따라서 적절하게 나눠서 처리 하면 이후 각 리스트별로 구분이 가능하기 때문에 목적에 맞게 구분하면 좋다.
여기서 ipset 기능을 이용한 이유는 iptable에 drop으로 source ip를 무작정 넣게 되면 룰의 수가 많아지게 되면 netfiler의 성능이 저하 되어 서비스가 느려지는 현상이 발생할수 있기 때문에 ipset 기능을 이용해서 처리 하였다.
명령어는 아래와 같이 처리 하였다.
# White List Group 생성 (Group 이름변경시 "officeip"를 변경)
ipset create officeip hash:ip hashsize 4096
# White List Group IPtable에 적용.
iptables -I INPUT -m set --match-set officeip src -j ACCEPT
# Block List Group 생성 (Group 이름변경시 "ddos_blockedip"를 변경)
ipset create ddos_blockedip hash:ip hashsize 4096
# Block List Group IPtable에 적용.
iptables -A INPUT -m set --match-set ddos_blockedip src -j DROP
# Web Server
웹 서버에서는 아래와 같은 Script를 매분 실행하게 하였다. (자세한 내용 주석 참고)
#!/bin/bash
# Access Log의 날자 구분을 위한 DATA 변수
DATE=`date +%Y%m%d`
# Slack의 Notification을 위한 System 시간 처리
SYS_DATE=$(date)
# Access Log의 경로
LOG=[ACCESS LOG Location].access.$DATE
# 중복 등록 방지를 위한 Blocke List IPs List
IPS=[Script Location for Duplicate IP add to list]/ips.txt
# Proxy IP
PROXY_IP=123.123.123
# Slack Web Hook Address
SLACK_WEBHOOK="https://hooks.slack.com/services/~~~~~~~~~~~~~~~~~~~~~~~~"
# 개행 처리를 위한 변수
IFS=$'\n'
# Tail을 이용해서 로그를 읽은 후
# grep의 -v 옵션을 사용하여 Static 확장자 제외
# 아이피($1)와 로그 시간($4)을 awk를 이용해서 처리 (이 부분은 각 시스템 마다 로그의 기록이 틀릴수 있기 때문에 적절히 확인 필요)
# sed를 이용해서 맨 뒤의 초단위 제거
# uniq한 값만 추출 및 정렬
# Count가 100개 이상의 IP만 추출
for ip in `tail -n 10000 $LOG | grep -v ".png\|.svg\|.eot\|.woff\|.ttf\|.jpg\|.gif\|.ico" | awk '{print $1 "\t" $4}' | sed -r "s/...$//" | sort -n | uniq -c | sort -r | awk '{if($1 >= 100) print $2;}'`
do
# IP가 ips.txt에 존재할 경우 Pass
exist=`grep $ip $IPS`
if [ -z "$exist" ]
then
# Proxy IP 및 Host에 ipset 명령어를 이용해서 Block IP 추가
# 사전에 root로 로그인 할수 있도록 ssh key가 proxy 서버에 등록 되어 있어야 한다.
ssh $PROXY_IP "ipset add ddos_blockedip $ip && ipset save"
echo "$ip" >> $IPS
# Proxy에 등록된 Block IP 등록된 Count Check
IP_BLOCK_CNT=$(ssh $PROXY_IP "ipset list ddos_blockedip | grep "^[0-9]" | wc -l")
# Slack 메시지에 표시될 내용
SLACK_PAYLOAD="{\"username\": \"[PROXY]\", \"text\": \"System Time : $SYS_DATE $IFS Source IP : $ip \t Total Count of Block Count : $IP_BLOCK_CNT $IFS \"}"
echo "json : " $SLACK_PAYLOAD
# Slack Web Hook Request
curl -X POST -H 'Content-type: application/json' --data "$SLACK_PAYLOAD" $SLACK_WEBHOOK
fi
done
Crontab에 분단위로 실행되도록 등록
* * * * * /root/add_iptables_using_ipset.sh
# iptables 명령어 참조
# iptables 룰 라인 넘버 확인
iptables -nL --line-number
# iptables 지정한 룰 라인 삭제
iptables -D INPUT [Line Number]
'Linux, Shell Script' 카테고리의 다른 글
공개키 인증으로 SSH Password 없이 접속하기 (0) | 2020.06.27 |
---|---|
Crontab 설치 및 사용법 (0) | 2020.06.25 |
VIM 유용한 단축키 및 사용법 (0) | 2020.04.05 |
process infomation 명령어(ps command) 오류시 대처 방법 (0) | 2019.09.04 |
Ubuntu / Windows 멀티부팅 순서 조정하기 (0) | 2019.06.04 |