자동화 slecs

보안 필터 강화로 의심 경로·페이로드·404 누적 자동 차단 도입

목차

운영 서버에 붙어있는 보안 필터를 손봤다. 크게 세 가지 레이어를 다루는 구조인데 - IP 기반 Rate Limit, 봇/공격 패턴 감지, 블랙리스트 자동 등록 - 이번 작업에서는 임계값을 조정하고, 예외 경로를 정리하고, 패턴 감지 범위를 넓혔다.

처음부터 이 세 레이어가 다 갖춰진 건 아니었다. Rate Limit 먼저 달고, 패턴 감지 나중에 붙이고, 블랙리스트는 한동안 수동으로 관리했다. 그러다 보면 공격 트래픽이 들어오는 속도보다 사람이 대응하는 속도가 느려지는 순간이 온다. 그 순간을 위해 자동 등록 구조를 마련해뒀던 건데, 이번엔 임계값과 패턴 쪽을 실제 운영 트래픽에 맞게 다시 조였다.

Redis 슬라이딩 윈도우로 Rate Limit을 구현한 이유도 짚고 넘어갈 만하다. 고정 윈도우 방식은 윈도우 경계에서 순간적으로 두 배 트래픽을 허용하는 구조적 취약점이 있다. 1분당 100요청 제한이라면 00:59에 100개, 01:00에 100개가 연달아 들어와도 윈도우 기준으론 둘 다 허용된다. 슬라이딩 윈도우는 이 경계 문제를 없애고 매 요청마다 직전 1분 구간을 실시간으로 계산한다. Redis의 원자적 연산과 TTL을 같이 쓰면 분산 환경에서도 카운터가 꼬이지 않고 상태 관리가 깔끔하다.

처리 흐름과 이번 변경 내용

필터 파이프라인 구조:

요청 수신
  → 화이트리스트 IP 확인
  → 봇 UA / 의심 경로 감지
  → Rate Limit 체크 (Redis 슬라이딩 윈도우)
  → 차단 / 블랙리스트 등록 / 통과

순서가 중요하다. 화이트리스트를 맨 앞에 둬서 신뢰 IP는 나머지 체크를 통째로 건너뛰게 한다. 그 다음이 UA/경로 감지인데, 여기서 잡히면 Rate Limit 카운트조차 올리지 않고 바로 탈락시킨다. 이 순서를 뒤집으면 패턴이 분명한 공격 요청에도 Redis 조회와 카운터 소모가 생긴다. 파이프라인 비용을 줄이려면 싸게 판단할 수 있는 것부터 앞에 두는 게 맞다.

이번 변경 요약:

항목 기존 변경 후
Rate Limit 임계값 완화 상태 강화 (1분 기준 하향)
공격 패턴 감지 기본 의심 경로 + 페이로드 확장
블랙리스트 수동 DB 자동 등록

Rate Limit 임계값이 완화 상태였던 건 이유가 있었다. 예전에 정상 트래픽이 막혀서 급하게 풀었던 거다. 그 상태로 꽤 오래 방치됐는데, 이번엔 순서를 바꿔서 AJAX 예외 처리와 예외 경로 정리를 먼저 끝낸 뒤에 임계값을 내렸다. 그 순서가 맞았다. 임계값부터 내렸다면 헬스체크나 모니터링 경로가 또 막혔을 거다.

의심 경로·페이로드 패턴 확장은 잘 알려진 스캐너 경로 목록과 공격 시그니처를 추가한 수준이다. /.env, /wp-admin, /phpMyAdmin, 각종 .git 노출 경로 같은 것들, SQL Injection이나 path traversal 시도가 담긴 파라미터들. 정상 사용자가 이런 경로를 요청할 이유가 없어서 임계값 없이 즉시 차단해도 된다. Rate Limit 레이어로 처리하면 임계값까지 채운 뒤에야 막히지만, 패턴 단계에서 먼저 잡으면 카운터 소모 없이 훨씬 빠르게 걸러진다. 404가 특정 IP에서 짧은 시간 안에 연달아 쌓이는 것도 이번에 감지 기준으로 추가했다. 스캐너가 경로 목록을 순차적으로 두드리는 패턴이라 잡기가 어렵지 않다.

예외 경로 처리와 AJAX 카운트

예외 처리를 빼먹으면 보안 강화가 운영 장애로 이어진다. 헬스체크 경로가 필터에 막혀서 모니터링 알림이 오발한 적 있었다. 그 이후로 필터 변경 전에 예외 경로 목록 점검을 먼저 한다.

이번에 명시적으로 필터 스킵 처리한 유형:
- 헬스체크 엔드포인트 (/health, /ping 계열)
- 내부 모니터링 수집 경로
- 특정 내부 IP 대역에서 들어오는 관리 요청

이 경로들은 파이프라인 진입 전 화이트리스트 단계에서 걸러낸다. 진입 자체를 차단하는 방식이라 다른 레이어와 충돌할 여지가 없고, 패턴이 실수로 겹쳐도 안전하다. 예외 목록은 별도 설정 파일로 관리하고 있어서, 필터 코드 건드리지 않고 경로만 추가할 수 있다.

AJAX 요청은 Rate Limit 카운트에서 제외하는 옵션도 추가했다. 페이지 로드 시 AJAX 호출이 여러 개 연달아 나가는 구조에서 동일 기준을 그대로 적용하면 정상 사용자가 임계값에 걸린다. 다만 이건 트레이드오프가 있다. AJAX를 카운트에서 아예 빼면 해당 엔드포인트를 반복 호출하는 공격 패턴은 Rate Limit으로 못 잡는다. 지금은 패턴 감지 레이어에서 먼저 걸러내는 쪽으로 커버하고 있고, 필요하면 AJAX 전용 별도 임계값을 나중에 추가할 수 있는 구조로 뒀다. 이 판단이 맞는지는 운영 로그를 더 쌓아보면서 확인할 예정이다.

블랙리스트 자동 등록 구조

공격 트래픽이 들어올 때 수동으로 IP를 추가하는 방식은 속도 문제가 있다. 사람이 로그 보고 판단해서 등록할 때쯤이면 이미 수천 건이 지나간 뒤다. DB에 자동 등록하고 다음 요청부터 즉시 차단하는 구조를 만들면 실시간 대응이 가능하다.

자동 등록에서 신경 쓴 부분:

  • 오탐 방지: 로드 테스트나 배치 작업이 봇으로 오해받지 않도록 해당 IP를 사전에 화이트리스트에 넣어두고 진행. 내부 배치가 갑자기 차단되면 원인 추적이 까다로워진다.
  • TTL 설정: 영구 차단 대신 만료 시간을 두어 오탐이었을 때 자동 복구되게 했다. 심각한 공격 IP는 TTL을 길게, 단순 스캔 수준은 짧게 분류해서 관리한다.
  • 알림 연동: 자동 차단 발생 시 슬랙/디스코드로 알림을 보내 모니터링이 끊기지 않게 했다. 자동화됐다고 방치하면 오탐이 쌓여도 인지가 안 된다.

TTL 없이 영구 차단만 쌓으면 오탐 복구가 수동 작업이 된다. 자동화의 편리함이 운영 부담으로 돌아오는 패턴이다. 자동으로 잠그는 만큼 자동으로 풀리는 경로도 같이 설계해야 한다는 걸 이 작업에서 다시 확인했다.

작업 규모 자체는 크지 않았다. 임계값 조정, 패턴 목록 확장, 예외 경로 정리, 알림 연동 점검 정도. 코드 변경량으로 보면 별거 아닌데, 이런 수정들이 쌓여야 시스템이 실제로 단단해진다. 보안 필터는 한 번에 완성되는 게 아니고, 운영에서 나오는 패턴을 계속 반영해서 좁혀나가는 거다.

댓글 0

첫 댓글 달아줘.