신비한 개발사전

Nginx로 스팸 요청 걸러내기 본문

Infrastructure

Nginx로 스팸 요청 걸러내기

jbilee 2025. 9. 11. 03:13

우여곡절 끝에 팀 프로젝트에 적용한 CloudWatch 지표와 로그 모니터링이 잘 돌아가고 있음을 확인하고, 더이상 인프라를 건드릴 일은 없을 거라며 뿌듯해하고 있을 때쯤이었다.

 

어느날 CloudWatch에서 운영환경 서버에 찍힌 로그들을 살펴보니 이상한 요청들이 기록돼있는 것을 알게 됐다.

 

당연히 우리가 구현한 API 중에 "/schar-papushak"이란 것은 없다. 팀원이나 일반 사용자 중 그 누구도 저런 엔드포인트에 접근하려고 하지 않았을 텐데, 접근 기록이 남아있다.

 

뿐만 아니라 "/assets" 나 "/v3" 등, 실제로 구현하진 않았지만 충분히 있을 법한 URL에도 접근하려 한 흔적이 있었는데, 요청한 URI와 호출 timestamp를 보고 누군가 자동화 프로그램으로 보낸 스팸 요청이라는 것을 깨닫게 되었다.

 

호기심에 다른 사람들의 경험담을 찾아보니, 매일 전세계 서버 오너들에게 일어나는 굉장히 일상적인 일이라고 한다.

 

문제는 이런 무의미한 요청들을 어떻게 걸러내는가였다. 안그래도 한정된 컴퓨팅 자원으로 서비스를 배포하고 있는데, 우리 서버의 리소스를 1 바이트도 내어주고 싶지 않았다.

 

Nginx에 허용할 엔드포인트 설정

이미 Nginx를 설치해 rate limiting과 리버스 프록시를 활용하고 있어서, 스팸 요청이 스프링 애플리케이션까지 전달될 필요 없이 Nginx단에서 미리 트래픽을 걸러낼 방법을 알아보았다.

 

Nginx 설정 중 location은 정규식을 허용한다. 우리 서비스는 서버 API 엔드포인트가 많지 않고, 또 구현한 엔드포인트 외에는 트래픽을 받아 처리할 이유가 없기 때문에 정규식으로 특정 엔드포인트만 유효한 요청으로 간주하도록 했다.

 

Nginx의 정규식 매칭은 location ~로 시작한다. ~ 이후에 매칭할 URI 패턴을 정규식으로 입력해주면 된다.

server {
    # 허용할 URI 패턴을 정규식으로 구분
    location ~ ^/(recommendations|subway-stations) {
        proxy_pass http://10.0.20.202:80;
        # ...기타 프록시 설정 생략...
    }

    # 정규식에서 매칭되지 않은 엔드포인트는 전부 444를 리턴하도록 함
    location / {
        return 444;
    }
}

 

동일한 server 블록 안에 location이 여러개 있으면 우선순위에 따라 URI를 체크한다. 정규식(~)보다 /가 우선순위가 가장 낮기 때문에, Nginx는 요청 URI를 정규식 location에 먼저 대조하게 된다.

 

따라서 "/recommendations"나 "/subway-stations"로 시작하는 URI가 아니면 다음 우선순위인 "location /"를 확인하게 되고, 그 결과 444를 응답하게 된다.

 

444 No Response는 Nginx 전용 응답코드로, 클라이언트에게 아무런 응답도 하지 않고 연결을 즉시 끊는다. 444로 응답하는 Nginx의 입장에서도 리소스 비용을 대폭 줄일 수 있다.

 

Backdoor 포트가 없는지 확인하기

위 설정은 엔드포인트만 확인한다는 점을 기억해야 한다. 만약 요청에 포트 번호까지 포함돼있으면, 해당 포트의 보안 설정도 함께 점검해줘야 한다.

 

나 같은 경우 운영환경과 개발환경 둘 다 Nginx 리버스 프록시를 적용해 두었는데, 애플리케이션을 private 서브넷에 둔 운영환경과는 달리 개발환경은 애플리케이션과 Nginx 둘 다 같은 public EC2에서 가동시키고 있는 상황이었다.

 

개발환경에도 정규식 location을 설정했음에도 불구하고 스팸 요청이 애플리케이션까지 전달되길래 원인을 알아본 결과, 개발용 EC2의 보안 그룹은 외부(0.0.0.0/0)로부터 8080 포트 접근까지 허용하고 있어서 클라이언트가 직접적으로 8080 포트에 접근하는 경우 Nginx가 거를 수 없었던 것이다. 사소한 허점으로 일종의 backdoor를 허용한 셈이다.

 

* 가장 쉽고 안전한 방법은 보안 그룹을 더 타이트하게 설정하는 것인데, 조직에서 정책을 두고 관리하는 보안 그룹이어서 다른 방법을 알아봐야 했다.

 

8080 포트는 이미 애플리케이션이 사용 중이었기 때문에 Nginx가 점유할 수 없어서, 8080 포트는 localhost로부터의 요청만 허용하도록 iptables 설정을 통해 외부 접근을 막는 방법으로 해결했다.

 

 

Nginx로 트래픽 인입을 제한한 결과, 로그에 스팸 요청으로 인한 노이즈가 없어지고 더불어 서버의 자원 낭비도 줄이는 이점을 얻었다. 물론 이외에도 스팸 요청을 차단하는 방법은 다양하게 있을테니, 우리 인프라에 적합한 방법을 찾아 적용해보면 좋을 것 같다.