글 / Nginx 운영

미등록 도메인 Catch-All 차단

등록하지 않은 도메인으로 수신된 요청을 기본 서버 블록에서 차단하며, 80은 444, 443은 핸드셰이크 거부로 처리한다.

작성일 · 수정일 · 읽는 시간 2분 · Nginx 1.28 기준

문제 정의

nginx는 Host가 어느 server_name과도 일치하지 않으면 그 포트의 기본 서버로 요청을 전달한다. 기본 서버를 별도로 지정하지 않았다면 설정 파일에서 가장 먼저 나오는 블록이 기본 서버가 된다. 이 때문에 서버 주소를 가리키는 타인의 도메인으로 접속하면 해당 서버의 사이트가 그대로 표시된다.

미등록 도메인 요청이 기본 서버 블록에서 차단되는 흐름

80 포트의 444 처리

444는 nginx에서만 사용하는 값으로, 응답을 전송하지 않고 연결을 종료한다.

nginx/etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    # 인증서 갱신 경로는 살려 둔다
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # 그 밖의 요청은 응답 없이 연결을 닫는다
    location / {
        return 444;
    }
}

443 포트의 핸드셰이크 거부

HTTPS는 응답을 전송하기 전에 인증서부터 제시해야 한다. 일치하지 않는 이름에는 인증서를 제시하지 않고 연결을 거부하는 방식이 더 적절하다.

80 포트와 443 포트의 미등록 도메인 처리 차이

nginx/etc/nginx/sites-available/default
server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;

    # 이름이 맞지 않는 요청은 TLS 연결 단계에서 거부한다
    ssl_reject_handshake on;
}
참고

ssl_reject_handshake는 nginx 1.19.4부터 사용할 수 있다.

확인 방법

서버 내부에서 존재하지 않는 도메인 이름으로 요청을 전송한다.

bash서버 안에서
curl -s -o /dev/null -w '%{http_code}\n' \
  --resolve unknown.example:80:127.0.0.1 http://unknown.example/
# 000  ← 응답 없이 끊겼다는 뜻
요청 처리 curl 결과
등록한 도메인 해당 사이트로 전달 200 등
미등록 도메인, 80 응답 없이 연결 종료 000
미등록 도메인, 443 핸드셰이크 거부 000

정리

  • 기본 서버 블록을 명시적으로 두면 첫 블록이 기본 서버가 되는 동작을 방지할 수 있다.
  • 80은 return 444, 443은 ssl_reject_handshake on으로 처리한다.
  • 인증서 갱신 경로는 예외로 유지한다.