목차
개요
nginx에서 특정 아이피들을 차단했지만 문을 닫더라도 두드릴 수는 있기 때문에 지속적으로 시스템 리소스를 사용한다.
따라서 지속적으로 접속을 시도하는 IP는 운영체제에서 차단을 하기로 결정했다.
처음에는 오라클의 VCN 설정만 믿고 iptables는 규칙을 다 제거했었다.
그래도 못 미더워 보통 iptables를 설정하는 것처럼 허용할 포트와 막을 포트부터 설정하려 했으나...
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
80 포트와 443 포트를 허용해줘도 실제로 사이트에 접속해보면 접속이 안된다.
아래와 같이 오라클 클라우드에서 안된다고 한다.
Chain InstanceServices (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere xxx.xxx.xxx.xxx owner UID match root tcp dpt:iscsi-target /* See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule */
ACCEPT tcp -- anywhere xxx.xxx.xxx.xxx/x owner UID match root tcp dpt:iscsi-target /* See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule */
ACCEPT tcp -- anywhere xxx.xxx.xxx.xxx/x owner UID match root tcp dpt:iscsi-target /* See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule */
ACCEPT tcp -- anywhere xxx.xxx.xxx.xxx/x owner UID match root tcp dpt:iscsi-target /* See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule */
IP 차단 방법
우선 지속적으로 php 관련 링크로 접속을 시도하는 악질 45.146부터 처리하려고 한다.
아래의 명령어를 입력한다.
$ sudo iptables -A INPUT -s 45.146.165.157 -j DROP
잘 설정이 됐는지 보려면 아래의 명령어를 입력한다.
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP all -- 45.146.165.157 anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain InstanceServices (0 references)
target prot opt source destination
설정을 저장하기 위해 아래의 명령어를 입력한다.
$ sudo netfilter-persistent save
혹시라도 시스템을 재시작했을 때 규칙이 날아갔다면 아래 명령어로 다시 로드한다.
$ sudo netfilter-persistent reload
fail2ban 설치
이제야 알게 됐는데, /var/log/auth.log 파일을 확인해보면 내 서버에 접속을 시도한 기록이 남는다.
nginx 로그는 조족지혈이고 여기가 진짜였다..
이 무수한 IP를 다 차단하기는 너무 빡세서 내 대신 차단해줄 툴을 설치하기로 했다.
아래의 명령어로 fail2ban을 설치한다.
$ sudo apt-get install fail2ban
fail2ban 설정 파일 작성
설치 후 아래 명령어로 설정 파일을 작성한다.
$ sudo nano /etc/fail2ban/jail.local
아래 내용을 그대로 넣어준다.
# SSH servers
[sshd]
enable = true
bantime = 3600m
findtime = 60m
maxretry = 5
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
ignoreip = 127.0.0.1/8 아이피추가입력
- enable - 활성화
- bantime - 차단할 기간, -1이면 영구
- findtime - 설정한 시간 내에 maxretry 횟수만큼 실패 시 차단
- maxretry - findtime 내에 허용할 시도 횟수
- ignoreip - 차단하지 않을 IP
[주의!] maxretry의 최소값은 1이다. (즉시 차단)
fail2ban 활성화
작성한 설정 파일은 시스템을 재시작하거나 fail2ban을 재시작해야 적용된다.
아래의 명령어로 fail2ban을 재부팅 후에도 켜지게 설정하고 재시작한다.
$ sudo systemctl enable fail2ban
$ sudo systemctl restart fail2ban
아래의 명령어로 fail2ban이 정상적으로 작동 중인지 확인한다.
이때 나오는 화면에서 차단된 IP도 확인할 수 있다.
$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: 194.165.16.0
차단을 해제하려면 아래의 명령어를 입력하면 된다.
$ sudo fail2ban-client set sshd unbanip 해제할IP
반대로 직접 차단하려면 ban으로 입력하면 된다.
$ sudo fail2ban-client set sshd banip 차단할IP
fail2ban의 작동 로그는 아래의 명령어로 확인할 수 있다.
$ tail -f /var/log/fail2ban.log
nginx와 fail2ban 연동
우선 차단할 문자열을 로그에서 찾아본다.
내 경우에는 아래 목록의 경로들이 있었다.
- /wp-login.php
- /xmlrpc.php
- /manager/html
- /jenkins/login
- /vendor/phpunit
- /_ignition/execute-solution
- /humans.txt
- /ads.txt
차단할 문자열을 설정 파일로 만들어준다.
$ sudo nano /etc/fail2ban/filter.d/nodebb.conf
아래 내용을 넣어주면 된다.
^<HOST>는 접속자의 IP, .*는 IP에서 * 으로 대역을 지정하는 것과 똑같이 작용한다.
[Definition]
failregex = ^<HOST> .* "(GET|POST) /wp-login.php
^<HOST> .* "(GET|POST) /xmlrpc.php
^<HOST> .* "(GET|POST) /manager/html
^<HOST> .* "(GET|POST) /jenkins/login
^<HOST> .* "(GET|POST) /vendor/phpunit
^<HOST> .* "(GET|POST) /_ignition/execute-solution
^<HOST> .* "(GET|POST) /humans.txt
^<HOST> .* "(GET|POST) /ads.txt
차단 설정이 적용되는지 알아보려면 아래의 명령어를 입력한다.
$ fail2ban-regex /var/log/nginx/도메인.access.log /etc/fail2ban/filter.d/nodebb.conf
Running tests
=============
Use failregex filter file : nodebb, basedir: /etc/fail2ban
Use log file : /var/log/nginx/도메인.access.log
Use encoding : UTF-8
Results
=======
Failregex: 0 total
Ignoreregex: 0 total
...
파일을 저장하고 fail2ban에서 새로운 jail을 생성하기 위해 jail.local 파일을 수정해야 한다.
$ sudo nano /etc/fail2ban/jail.local
기존에 있던 내용 아래에 다음과 같이 입력한다.
# ban fucking bot from nodebb
[nodebb]
enabled = true
bantime = 100
findtime = 86400
maxretry = 3
port = http,https
logpath = /var/log/nginx/도메인.access.log
# 로그 여러 개 할 경우 엔터치고 입력, 아니면 이거 지우기
filter = nodebb
action = iptables-multiport[name=nodebb, port="http,https", protocol=tcp], %(a>
ignoreip = 127.0.0.1/8 제외할IP
테스트를 위해 차단 기간을 100초로 설정했다.
적용을 위해 fail2ban을 재시작한다.
$ sudo systemctl restart fail2ban
재시작 후에 잘 되는지 확인을 위해 vpn을 켜고 [도메인.com/wp-login.php]에 접속을 3회 해보니 바로 차단에 성공했다.
$ sudo fail2ban-client status nodebb
Status for the jail: nodebb
|- Filter
| |- Currently failed: 2
| |- Total failed: 19
| `- File list: /var/log/nginx/도메인.access.log
`- Actions
|- Currently banned: 1
|- Total banned: 1
`- Banned IP list: ***.***.***.***
다시 jail.local을 열어 bantime을 -1로 설정해준다. (영구차단)
$ sudo nano /etc/fail2ban/jail.local
이제 fail2ban을 재시작하면 적용된다.
$ sudo systemctl restart fail2ban
구글봇의 차단 방지
혹시라도 구글 봇이 설정한 경로로 접속해서 차단당할 수 있다.
잊지말고 robots.txt에 아래의 내용을 추가해준다.
Disallow: /wp-login.php
Disallow: /xmlrpc.php
Disallow: /manager/html
Disallow: /jenkins/login
Disallow: /vendor/phpunit
Disallow: /_ignition/execute-solution
Disallow: /humans.txt
Disallow: /ads.txt
hex 코드 차단
아래와 같이 hex 코드로 쉘 명령어를 보내는 로그도 자주 남는다.
\xBA\xABd\xA1EZC\xDBM...
처음에는 백슬래시를 차단하려고 했는데, failregex에 백슬래시를 넣으면 정규식이 아니라면서 오류가 난다.
fail2ban이 파이썬으로 만들어져서 그렇다고 한다.
검색을 해서 겨우 해결책을 찾았는데, 파이썬에서 백슬래시를 2번 쓰면 하나로 인식한다고 한다.
failregex에 아래의 내용을 추가해서 차단에 성공했다.
^<HOST> .* "\\