근래들에 멀웨어 감염되는 등 사이트에 심각한 문제가 발생했길래 서버 보안 및 사이트 보안에 대해 추가 조치를 하고 있습니다. 이중 워드프레스 로그인 시도를 제한해 워드프레스 해킹 방지하는 Fail2Ban 설정을 Iptables 방화벽과 연계 설정 방법에 대해서 알아보겠습니다.
Fail2Ban은 로그를 분석해 의심스러운 사이트 접근을 막는 방법으로 SSH, Apache, Nginx, FTP 등의 의심스러운 접근을 차단할 수 있습니다.
또한 워드프레스 로그인 실패 로그 기록을 기반으로 워드프레스 관리자 로그인 시도 등을 막을 수도 있습니다.
Fail2Ban에 대한 소개나 사용법에 대한 소개 자료는 많이 있지만 이중에서 워드프레스 해킹 방지 방법에 대해서는 조금 낮선 것 같아서 이번 사이트 보안 대책 수립하면서 자세하게 확인해 보았습니다.
특잏 이러한 Fail2Ban 설정을 Iptables 방화벽과 연계해 보안을 강화하는 방법까지 살펴보겠습니다.
워드프레스 로그인 감시를 위한 Fail2Ban 설정 – 필터 정의
Fail2Ban에서 워드프레스 관리자 로그인으로 워드프레스 해킹하려는 시도를 막기 위해서는 우선 워드프레스 로그인 실패를 모니터링할 수 있는 필터를 추가합니다.
Fail2Ban 필터는 /etc/fail2ban/filter.d 폴더에 존재하는데요. Fail2Ban에는 워드프레스 로그인 시도를 모니터링할 필터가 없기 때문에 수작업으로 만들어 줍니다.
필터 이름은 구분하기 적당하게 지으면 되는데요. 설명 자료등에서 wordpress를 많이 사용하고 있기 때문에 저도 wordpress 이름을 사용해 wordpress.conf 파일에 필터 옵션을 추가했습니다.
nano /etc/fail2ban/filter.d/wordpress.conf
Code language: PHP (php)
wordpress 필터에는 다음과 같은 내용이 들어갑니다.
[Definition]
failregex = ^<HOST> .* "(GET|POST) /wp-login.php
^<HOST> .* "(GET|POST) /xmlrpc.php
Code language: PHP (php)
워드프레스 로그인 감시 옵션
그 다음에는 위에서 정의한 Fail2Ban 필터를 기반으로 워드프레스 로그인을 감시하고 조치할 옵션을 정의합니다.
이는 /etc/fail2ban/jail.d 폴더 내 적절한 이름 + .conf 형식으로 로그인 감시 옵션을 추가합니다. 별도 파일을 만들지 않고 local.conf와 같은 파일안에 모든 종류 옵션을 추가해도 좋을 것입니다.
nano /etc/fail2ban/jail.d/local.conf
Code language: PHP (php)
여기에 아래와 같은 내용을 주가합니다. 하루 24시간동안 3번 로그인 실패하면 IP를 영구 금지시키는 다소 엄격한 조건을 설정했습니다.
[wordpress]
enabled = true
port = http,https
filter = wordpress
action = iptables-multiport[name=wordpress, port="http,https", protocol=tcp], %(action_mw)s
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 86400
bantime = -1
Code language: PHP (php)
위 내용을 항목별로 해석해 보죠.
- enabled = true : 워드프레스를 모니터링하라는 옵션, 반드시 true로 설정되어야 모니터링을 시작함
- port = http,https : SSL이 적용된 443 포트나 일반 80 포트로 들어와서 시도되는 행동들을 모니터링
- filter = wordpress : 사용할 필터
- action = iptables-multiport : 문제를 감지 시 어떻게 할지는 iptables-multiport에서 정의한 대로 조치
- logpath = /var/log/nginx/access.log : Fail2B이 참조해야하는 로그 파일
- maxretry = 3 : 3번 이상 시도해서도 실패 시 조치를 취함
- findtime = 86400 : 로그인 실패등이 일어났는지 확인할 시간, 86400은 1일로 로그를 검색해 조치 여부 판단
- bantime = -1 : 조치를 지속하는 시간, -1은 무기한 금지
검색 봇 조치
구글 등의 검색 엔진의 봇들이 사이트를 돌아다니다 파일들을 테스트하면서 잘못해 구글 봇 ip가 블락될 가능성도 있기 때문에 robots.txt에 아래 내용을 추가해 줍니다.
User-agent: *
Disallow: /wp-login.php
Disallow: /xmlrpc.php
Code language: PHP (php)
Fail2Ban 설정 결과
위와같이 Fail2Ban 설정에 wordpress 옵션을 추가한 1일 후 아래처럼 264개 ip가 블럭당했음을 볼 수 있습니다.
# fail2ban-client status wordpress
Status for the jail: wordpress
|- Filter
| |- Currently failed: 87
| |- Total failed: 2282
| `- File list: /var/log/nginx/access.log
`- Actions
|- Currently banned: 264
|- Total banned: 264
`- Banned IP list: 139.59.43.196 162.241.29.139 167.71.139.8 178.116.22.137 178.128.82.148 178.135.93.158 212.116.102.246 213.5.78.240 45.55.135.88 159.89.110.45 51.15.180.70 70.113.11.186 67.205.161.59 62.210.88.90 165.22.191.129 49.145.70.15 107.179.19.68 134.122.120.74 139.99.121.6 142.4.22.236 178.62.33.222 159.203.36.107 213.149.103.132 128.199.158.182 103.83.36.101 166.62.80.109
Code language: PHP (php)
저의 경우 SSL 공격은 많지 않은데요. 아마 포트를 22번이 아닌 별도의 포트를 사용하기 때문이 아닐까 싶습니다. 워드프레스 로그인을 통한 공격이 굉장히 많다는 점에 놀랬습니다.
한때는 보안 플러그인 워드펜스(wordfence)를 같이 사용했는데요. 워드펜스에서 막는 것보다 Fail2Ban에서 막는 것이 훨씬 더 많더군요. 워드프레스 로그인 보안 관련해서는 Fail3Ban을 활용하는 것이 훨씬 낫다는 생각을 했습니다.
Fail2Ban 설정을 Iptables 방화벽과 연계 방법
그러면 이렇게 Fail2Ban 설정을 통해서 막았던 ip들을 Iptables 방화벽에게 알려주어 보다 근본적으로 서버 접근 자체를 막아버리는 방법에 대해서 살펴보도록 하겠습니다.
여기서 목적은 Fail2Ban에서 IP 금지 리스트에 등록되면 Iptables 방화벽에도 자동으로 등록, 방화벽에서 ip를 금지 시키도록 변경하고 나중에 Fail2Ban을 다시 설치해도 Block ip list를 활용할 수 있도록 만드는 것입니다.
아시다시피 Fail2Ban은 다시 시작하면 기존에 막았던 ip 리스트들은 전부 초기화됩니다. 그때부터 다시 ip를 관리하기 시작합니다.
이를 막기 위해서는 아래와 같이 Fail2Ban 액션을 추가합니다.
nano /etc/fail2ban/action.d/iptables-repeater.conf
Code language: PHP (php)
여기에 아래와 같은 내용을 추가합니다.
# Fail2Ban configuration file
# Author: WireFlare
# https://wireflare.com/blog/permanently-ban-repeat-offenders-with-fail2ban/
[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = iptables -N fail2ban-
iptables -A fail2ban- -j RETURN
iptables -I -p -j fail2ban-
# Establish chain and blocks for saved IPs
iptables -N fail2ban-ip-blocklist
iptables -A fail2ban-ip-blocklist -j RETURN
iptables -I -p -j fail2ban-ip-blocklist
cat /etc/fail2ban/ip.blocklist. |grep -v ^\s*#|awk '{print $1}' | while read IP; do iptables -I fail2ban-ip-blocklist 1 -s $IP -j REJECT --reject-with icmp-port-unreachable; done
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop = iptables -D -p -j fail2ban-
iptables -F fail2ban-
iptables -X fail2ban-
# Remove chain and blocks for saved IPs to prevent duplicates on service restart
iptables -D -p -j fail2ban-ip-blocklist
iptables -F fail2ban-ip-blocklist
iptables -X fail2ban-ip-blocklist
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck = iptables -n -L | grep -q 'fail2ban-[ \t]'
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionban = VERIFY="*"
ADD=" # fail2ban/$( date '+%%Y-%%m-%%d %%T' ): Perma-Banned"
FILE=/etc/fail2ban/ip.blocklist.
grep -q "$VERIFY" "$FILE" || iptables -I fail2ban- 1 -s -j DROP
grep -q "$VERIFY" "$FILE" || echo "$ADD" >> "$FILE"
# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: See jail.conf(5) man page
# Values: CMD
#
actionunban = # Do nothing becasuse their IP is in the blocklist file
# To manually unban from the ip blocklist file run this command:
# Be warned that if the ip is in log rotated files it must be whitelisted
#
# sed -i '/^/d' /etc/fail2ban/ip.blocklist.repeatoffender
#
[Init]
# Default name of the chain
#
name = default
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be
# added
# Values: STRING Default: INPUT
chain = INPUT
Code language: PHP (php)
이러한 설정을 적용하려면 Fail2Ban을 다시 시작합니다.
sudo service fail2ban restart
Code language: PHP (php)
[참고] 이메일로 받아보기
Fail2Ban에서는 사이트 공격으로 IP가 블락되면 이를 이메일로 알려주라고 설정할 수 있습니다.
이를 위해서는 두가지 조치가 필요합니다. 하나는 어떤 이벤트가 발생 시 이메일로 알려다오라고 설정하는 것이고, Fail2Ban에게 이메일 주소를 알려주어야겠죠.
물론 서버에서 외부로 메일을 보낼 수 있는 상태가 되어 있어야 합니다. 이는 구글 지메일 이용 우분투 메일 서버 구축하기라는 포스팅을 참조해 보시기 바랍니다.
먼저 action에서 %(action_mw)s를 추가하는 것인데요. [DEFAULT] 섹션에서 추가할 수도 있고 [wordpress]와 같은 특정 필터를 커스텀 정의하는 섹션에서 추가할 수도 있습니다.
마찬가지로 메일 주소를 destemail과 sender로 나누어 이메일 주소를 세팅해 줄 수 있습니다. 아래는 제가 세팅한 모습니다.
[DEFAULT]
ignoreip = ***.***.***.*** ***.***.***.*** ***.***.***.***
bantime = -1
findtime = 86400
maxretry = 5
action = %(action_mw)s
# Mail
destemail = *****@gmail.com
sender = YYYYY@gmail.com
Code language: PHP (php)
그러면 IP가 블럭되었을 때마다 아래와 같은 이메일을 받을 수 있습니다. 이메일을 받으면 별도 조치는 할 수는 없지만 경각심을 가질 수 있겠죠.
참고
해킹 시도 악성 IP 차단 리스트 관리 방법 – NGINX 기준
가성비가 뛰어난 Vultr 가상서버호스팅(클라우드호스팅,VPS) 사용기
Vultr 가상서버호스팅의 새상품 High Frequency 사용기
가상 서버를 운영하고픈 勇者에게 전하는 가상 서버 운영 입문 노하우 – Vultr 가상서버호스팅(VPS)를 중심으로
해외 가상서버호스팅(VPS)이 국내 호스팅보다 빠르다? – 아이비호스팅과 해외 가상서버호스팅 VULTR간 비교
사이트 운영을 위한 안내 – 웹서버 세팅에서 워드프레스 설치까지(우분투 17.10, NGINX 1.13.6, Marian DB 10.2, PHP7.2)