IP Block, fail2ban with nginx 나쁜놈 피하기

00_8_3·2023년 8월 4일

엘라스틱서치 db가 랜섬웨어를 당한 이후
전체 서비스를 AWS로 마이그레이션을 했는데
여전히 서버 접근 트래픽에 이상한 ip들이 자주 보인다.
이런 나쁜 놈들을 차단하는 방법을 알아보려 합니다.

트래픽 flow

유저 -> EC2( nginx -> express ) -> RDS 또는 다른 서비스

방법

nginx의 access.log를 읽어 특정 route로 접근하는 ip 밴 시키기.

  • nginx log 위치 : /var/log/nginx/access.log

  • fail2ban 시작 : sudo service fail2ban start

  • 밴 리스트 확인 : sudo fail2ban-client status nginx-banroute

사전조건

  1. nginx 설치
  2. fail2ban 설치

sudo apt-get install fail2ban

아래 2개 설정파일을 넣고 fail2ban을 재시작.
sudo service fail2ban restart

jail.local

local 파일은 jail.conf 파일보다 우선순위가 높다.

/etc/fail2ban 위치에 넣자.

[nginx-banroute]
enabled  = true
filter   = nginx-banroute
logpath  = /var/log/nginx/access.log
maxretry = 1
findtime = 600
bantime  = -1
action   = iptables-multiport[name=NoNginx, port="http,https", protocol=tcp]

nginx-banroute.conf

/etc/fail2ban/filter.d 위치에 파일을 넣자.

[Definition]
failregex = ^<HOST> -.*GET /login.rsp
            ^<HOST> -.*GET /env
            ^<HOST> -.*GET /.env
            ^<HOST> -.*GET /backup
            ^<HOST> -.*GET /login
            ^<HOST> -.*GET /img
            ^<HOST> -.*GET /admin.php
            ^<HOST> -.*GET /.aws
            ^<HOST> -.*GET /admin
            ^<HOST> -.*GET /info.php
ignoreregex =

테스트, 확인, 삭제

  • 1 테스트
    GET <내 도메인>/admin

  • 2 확인
    sudo fail2ban-client status nginx-banroute

  • 3 삭제
    fail2ban-client set jail명 unbanip IP주소

예시) sudo fail2ban-client set nginx-banroute unbanip 162.158.178.120

nginx 앞에 프록시

nginx 앞에 프록시 서버가 있으면 프록시 ip가 노출되는 경우가 발생할수도 있다.
그러면 프록시 주소가 대신 밴당해서 계속 접근하게 된다.

나같은 경우 nginx에 x-forwarded-ip 를 설정해도 앞의 클라우드플레어 프록시 때문에
실제 ip가 노출되지 않고 127.0.0.1만 노출이 되어 fail2ban 설정이나
로거가 제대로 남지 않았다.

유저 -> 클라우드플레어 -> nginx -> 서버

cloudflare.conf을 작성 후 /etc/nginx 폴더에 넣어주고

/etc/nginx/nginx.conf 파일 http 블록에 추가해주면
유저의 실제 ip를 알수 있다.

# Cloudflare Real IP visitors
include /etc/nginx/cloudflare.conf;

해결1 nginx cloudflare.conf

#Cloudflare ip addresses

# - IPv4
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;

# - IPv6
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;

real_ip_header CF-Connecting-IP;

해결2 fail2ban cloudflare

나와 비슷한 이슈 레딧.

  • 2.1 클플 글로벌 토큰으로 필터 적용이 된다고 하는데
    엔터프라이즈 버전에서만 된다고 한다.

해결 3 (사용)

  • iptable을 확인하면 클플 헤더를 사용해서 real_ip가 reject 되도록 잘 등록된 것을 확인 할수 있지만
    막상 동일한 ip로 접근이 가능했다.
    이유를 찾아보니 iptable은 리버스 프록시(클플)에서 발생한 패킷만 볼수 있는데 실제 방문자 ip주소는 패킷에 가려져
    iptable이 real_ip를 reject 한다고 해도 대조할 때는 엉뚱한 프록시 ip를 검사하기 때문에 계속 접근이 가능하다.

  • 그래서 iptable에서 프록시 ip를 검사하는게 아닌 x-forwared-for와 같은 헤더를 검사하여 접근이 불가능하게 해야한다.

기존의 filter는 그대로 사용하고 action을 추가 해주자.

  • nginx-banroute-action.conf
[Definition]

actionban = iptables -I INPUT -m string --algo bm --string 'X-Forwarded-For: <ip>' -j DROP
 
actionunban = iptables -D INPUT -m string --algo bm --string 'X-Forwarded-For: <ip>' -j DROP

iptable 체인에는 input, output, forward 3가지가 존재하는데

input은 호스트로 들어오는 모든 패킷을 처리하기 위한 체인이다.
즉 어떠한 해당 헤더로 접근하는 ip가 iptable에 등록되어 있는경우 drop 한다.

  • local.conf
[nginx-banroute2]
enabled  = true
filter   = nginx-banroute
logpath  = /var/log/nginx/access.log
maxretry = 1
findtime = 600
bantime  = -1
action   = nginx-banroute-action

밴 리스트에 추가되고 삭제되는 것을 텔레그램과 같은 메신저에 알림을 줄수도 있다.

추가 23-08-12

클라우드 플레어 차단

위에서 ip access rules를 사용한 국가별 차단을 하려고 했다가 엔터프라이즈 이상만 가능해서 그만두었었는데

security-waf-사용자 지정 규칙을 사용해서 차단을 진행 할수 있었다.
(무료 티어면 5개 가능)

위와 같이 작성 후 아래 수행할 동작을 차단으로 설정 하고 배포 저장하면 된다.
잘되는지 테스트 해보려면 위의 연산자를 같음으로 해서 한국 트래픽이 차단되는지 확인 해보면 된다.

modsecurity waf

아파치나 nginx 등등 프록시에 적용 가능한 보안 플러그인이다.

마무리

서버 밖의 프록시가 제공해주는 ban list를 사용하면 간단하겠지만 (클플 유료로 바뀜)
유료인 경우 위와 같은 방법을 사용하면 된다.

0개의 댓글