자동화 slecs

봇 차단과 블랙리스트 자동 등록으로 보안 필터 강화

목차

보안 필터는 조용히 잘 돌아갈 때는 아무도 눈치 못 채고, 뭔가 잘못됐을 때만 존재감이 드러나는 컴포넌트다. 이번 작업도 그런 맥락에서 시작됐다. 운영 서버에 붙어 있는 보안 필터가 세 가지 축으로 동작하고 있는데 - IP 기반 Rate Limit, 봇/공격 패턴 감지, 블랙리스트 자동 등록 - 이 중 특히 블랙리스트 쪽이 문제였다. UA로 봇이라고 판별은 하는데, 그 결과가 DB에 남지 않고 그냥 그 요청만 막고 끝이었다. 다음에 같은 IP가 다시 오면 처음부터 다시 감지 로직을 태워야 하는 구조.

수동 블랙리스트는 관리 비용도 문제지만 타이밍이 더 문제다. 공격 트래픽은 짧은 시간 안에 많이 치고 들어오는 패턴이 많아서, 사람이 확인하고 등록하는 사이에 이미 부하가 올라가 있는 경우가 생긴다. 자동화하는 게 맞다고 판단해서 이번에 DB 자동 등록으로 바꿨다.

이번에 바꾼 것들

변경 내역을 정리하면 아래 표 정도로 요약된다.

항목 기존 변경 후
Rate Limit 임계값 완화 상태 강화 (1분 기준 하향)
공격 패턴 감지 기본 경로만 의심 경로 + 페이로드 확장
블랙리스트 등록 수동 UA 봇 감지 시 DB 자동 등록
예외 경로 미정의 헬스체크·모니터링 경로 명시 제외
AJAX 요청 Rate Limit 포함 카운트 제외 옵션 추가

처리 흐름은 아래 순서로 진행된다.

요청 수신
  → 화이트리스트 IP 확인
  → 봇 UA / 의심 경로 감지  ← 여기서 걸리면 DB 블랙리스트에 바로 적재
  → Rate Limit 체크 (Redis 슬라이딩 윈도우)
  → 차단 / 블랙리스트 등록 / 통과

UA 봇 감지 단계에서 차단되는 경우 이제 그냥 요청만 드롭하는 게 아니라 해당 IP를 DB에 남긴다. 다음 요청부터는 감지 로직 전에 블랙리스트 조회가 먼저 튀어나오도록 짜면 처리 비용도 줄어든다. 당장 이번에 그 부분까지 최적화하진 않았지만, 적재 자체가 돼 있으면 나중에 적용은 쉽다.

예외 경로와 AJAX - 오탐 줄이는 게 핵심

Rate Limit을 강화할 때 가장 조심해야 하는 부분은 정상 트래픽 오탐이다. 공격 하나 막으려다 모니터링 수집기나 헬스체크 응답이 503 뜨기 시작하면 오히려 운영 가시성이 떨어진다. 이번에 헬스체크 엔드포인트와 모니터링 수집 경로를 명시적으로 필터 스킵 대상으로 박아둔 이유가 그거다. 암묵적으로 "이 경로는 안 막히겠지"가 아니라 코드에 명시적으로 제외 목록을 들고 가는 게 낫다. 나중에 필터 로직 건드릴 때 실수로 빠질 가능성을 줄여준다.

AJAX 요청 제외 옵션은 판단이 좀 필요한 부분이었다. 페이지 로드 타이밍에 AJAX가 여러 개 동시에 나가는 구조인 경우, 1분 기준 임계값을 정상 사용자도 순식간에 넘길 수 있다. 그냥 일괄 적용하면 실사용자 막는 게 오히려 잦아진다. 그래서 AJAX 요청은 카운트에서 빼는 옵션을 추가했다. 단, AJAX만 무제한으로 허용하면 그쪽으로 공격 벡터가 생길 수 있으니, 별도 임계값을 두거나 AJAX 요청 자체에도 다른 기준을 적용하는 방향을 고려해야 한다. 이번 작업 범위에선 일단 제외 옵션만 추가했고, 세밀한 조정은 이후 트래픽 패턴 보면서 할 예정이다.

Redis 슬라이딩 윈도우, 쓸 때 같이 챙겨야 하는 것

Rate Limit 구현으로 Redis 슬라이딩 윈도우를 쓰는 이유는 고정 윈도우 방식의 경계 구간 버스팅 취약점을 피할 수 있어서다. 고정 윈도우 방식은 00:59에 100요청, 01:00에 100요청을 2초 사이에 날리는 식으로 윈도우 경계에서 2배 트래픽을 허용하는 구조가 생긴다. 슬라이딩 윈도우는 매 요청 시점 기준으로 과거 N초를 보기 때문에 이 구멍이 없다.

다만 Redis에 너무 의존하면 Redis 장애 시 필터 전체가 동작 불가가 된다. 연결 풀 크기와 타임아웃 설정은 같이 잡아야 한다. 타임아웃이 너무 길면 Redis 응답이 느려질 때 웹 요청 자체가 줄줄이 block되고, 너무 짧으면 순간 지연에도 fallback이 계속 튀어나온다. 일반적으로는 커넥션 타임아웃 200-500ms, 읽기 타임아웃 100-300ms 범위에서 잡는다. 그리고 Redis 장애 시 어떻게 할지 - 전부 통과시킬지, 전부 차단할지 - 정책을 미리 결정해두는 게 좋다. 대부분의 경우 "장애 시 통과"를 선택하지만, 보안 민감도에 따라 다르다.

작업 규모 자체는 크지 않았다. 임계값 조정, 예외 경로 명시, 블랙리스트 자동 등록 연결 정도라서 코드 양으로 치면 많지 않음. 그런데 이런 설정 레벨 변경이 실제 운영에서 체감 차이가 크게 나는 경우가 많다. 필터 설정은 한 번 맞게 잡아두면 한동안 안 건드려도 되지만, 처음 잘못 잡으면 계속 이상한 곳에서 문제가 나온다. 작업 후 로그 모니터링을 일정 기간 같이 챙기는 게 습관적으로 필요하다.

댓글 0

첫 댓글 달아줘.