조회수: 15

444 Connection Closed 오류 (nginx)

444 Connection Closed는 nginx가 응답 없이 끊은 것. 도달성·TLS/SNI·WAF 규칙을 점검한다. 무료 즉시 진단으로 바로 확인.

내 도메인에 이 문제가 있는지 지금 확인

무료, 가입 불필요. 이 가이드가 다루는 항목을 바로 검사하고 조치 방법을 알려드립니다.

Problem

서버로 보낸 요청이 아무것도 없이 돌아옵니다. 연결은 열리고, 요청은 나가고, 그다음 소켓이 응답 한 바이트 없이 닫힙니다. curlcurl: (52) Empty reply from server를 보고하고, Postman은 444 Connection Closed Without Response로 표시하며, 브라우저 도구는 상태 코드 없는 실패 요청을 보여 줍니다. 이 교환 어디에서도 서버가 444를 보내지 않았습니다 — 그 코드는 이 침묵을 만든 nginx 동작을 이름 붙인 것일 뿐입니다.

Symptoms

  • curl이 코드 52와 Empty reply from server 메시지로 종료됩니다.
  • Postman, Insomnia, API 클라이언트가 헤더도 본문도 없는 444를 보여 줍니다.
  • 요청이 서버에 도달은 하는데(TCP 연결은 수락됨) HTTP 응답이 돌아오지 않습니다.
  • 어떤 요청은 되고 어떤 요청은 버려집니다 — 흔히 경로·User-Agent·Host 헤더·소스 IP로 갈립니다.
  • nginx access.log의 상태 필드에 버려진 요청에 대해 444가 찍히거나, 아무것도 찍히지 않습니다.

What 444 Actually Means

444는 HTTP의 일부가 아닙니다. nginx 전용 지시어입니다: location이나 server 블록이 return 444;에 닿으면 nginx는 즉시 연결을 닫고 아무것도 보내지 않습니다 — 상태 줄도, 헤더도, 본문도. RFC 9110에 그런 코드는 없고, “444”를 담은 바이트가 네트워크를 건너는 일도 없습니다. 이건 의도된 것입니다. 444의 목적은 이미 거절하기로 정한 요청에 최대한 덜 쓰는 것입니다: 오류 페이지도, 설명도, 무언가 듣고 있다는 확인조차 없습니다.

이 점이 실패를 읽는 방식을 바꿉니다. 보통의 거절 — 403, 429, 502 — 은 대화입니다: 서버가 요청을 봤고 거절하기로 했다고 말해 줍니다. 444는 전화를 끊는 것입니다. 클라이언트 입장에서 의도적 return 444와 응답 도중 죽은 서버는 똑같아 보입니다 — 둘 다 조용해진 열린 소켓만 남기니까요. 그래서 첫 질문은 결코 “내 요청의 뭐가 잘못됐나”가 아니라 “무언가 이걸 일부러 버렸나, 아니면 무언가 깨졌나”입니다.

대개는 일부러였습니다. 운영자는 몇 군데 익숙한 자리에 return 444를 배선합니다: 유효한 Host 헤더 없는 맨 IP 요청, HTTPS 리스너에 잘못된(또는 없는) SNI를 단 트래픽, 차단 목록의 User-Agent, 취약점 스캐너만 찾는 경로, 429로 답하는 대신 버리도록 설정된 limit_req 레이트 리밋. nginx 앞단의 Cloudflare 같은 프록시도 연결을 거부할 때 같은 빈-응답 증상을 냅니다. 결정적 단서는 이겁니다: 그 버림은 선별적입니다. Host 헤더나 SNI, 소스를 바꾸면 같은 URL이 갑자기 답합니다.

Top 3 Causes

  1. 의도적 return 444 규칙이 당신 요청에 매치됐다. 설정 블록이 맨 IP 요청, 잘못된 Host나 SNI, 차단 네트워크, 스캐너 형태의 경로를 버립니다. 지문: 한 가지 형태의 요청에는 일관되게 버려지고, Host 헤더를 고치거나 SNI에 진짜 호스트명을 쓰거나 다른 IP에서 오면 사라집니다. 서버에서 grep -r "444" /etc/nginx로 규칙을 빨리 찾습니다.
  2. 리스너에 잘못된 프로토콜이나 SNI가 닿는다. HTTPS 전용 포트에 보낸 평문 HTTP, 또는 SNI를 요구하는 서버에 SNI가 없거나 틀린 TLS 핸드셰이크는 HTTP 응답 전에 끊깁니다. 지문: 실패가 무엇을 요청하느냐가 아니라 어떻게 연결하느냐(스킴·포트·호스트명)를 따라가고, http://https://로 바꾸거나 호스트명을 고치면 결과가 달라집니다.
  3. 업스트림이 응답 도중 죽었다 — 444 규칙과 무관. 애플리케이션 워커가 크래시했거나 OOM으로 kill됐거나, nginx가 응답을 중계하기 전에 업스트림이 소켓을 닫아서 클라이언트가 444와 똑같아 보이는 빈 응답을 받습니다. 지문: 간헐적이고 부하·배포·메모리 압박과 상관관계가 있으며, nginx error.log에 액세스 로그의 깔끔한 444가 아니라 upstream prematurely closed connection이 찍힙니다.

Diagnose with DechoNet

  • HTTP Check는 호스트가 진짜 HTTP 응답을 내는지, 최종적으로 어떤 코드에 안착하는지 알려 줍니다 — “서버는 답하는데 나한테만 안 함”과 “서버가 이 요청 형태를 버림”을 가장 빨리 가르는 방법입니다.
  • Port Check는 대상 포트가 실제로 열려 연결을 받는지 확인해, 빈 응답이 닫히거나 필터링된 포트가 아니라 의도적으로 끊은 것임을 알려 줍니다.
  • SSL Check는 TLS 핸드셰이크와 인증서를 검사해, HTTPS 리스너가 응답 없이 당신을 버리게 만드는 SNI/호스트명 불일치와 HTTP-대-HTTPS-포트 오류를 드러냅니다.

Resolution Checklist

  • curl -v로 재현해 (52) Empty reply from server가 나는지 확인하세요 — verbose 출력은 연결이 수락됐는지, 어디서(TLS 전인지 후인지) 조용해졌는지 보여 줍니다.
  • 맨 IP가 아니라 올바른 Host 헤더와 호스트명 기반 SNI로 요청을 보내세요 — 많은 444 규칙이 바로 맨 IP·잘못된 Host 트래픽을 버리려고 존재합니다.
  • 서버에서 grep -rn "444" /etc/nginx/return 444;를 찾고, 그것을 지키는 조건(Host, $http_user_agent, map, limit_req, geo/IP 허용목록)을 읽으세요.
  • error.log에서 upstream prematurely closed connection이나 워커 OOM/segfault를 확인하세요 — 이게 보이면 규칙이 아니라 크래시이고, 해결은 nginx가 아니라 앱에 있습니다.
  • 스킴과 포트가 맞는지 확인하세요: ssl 전용 리스너에 평문 HTTP를 보내면 같은 빈 응답이 납니다; https://와 올바른 포트를 쓰세요.
  • 레이트 리밋 버림이라면, 조용히 끊는 게 원하는 동작인지 판단하거나, 존을 바꿔 Retry-After와 함께 429로 답하게 해 정상 클라이언트가 물러설 수 있게 하세요.

When to Escalate

  • 444가 nginx 앞단의 CDN이나 프록시(Cloudflare, 로드 밸런서, 인그레스 컨트롤러)에서 비롯된다면, 버림 규칙이 nginx 설정이 아니라 거기에 있을 수 있습니다 — 오리진을 건드리기 전에 엣지의 방화벽·봇·레이트 리밋 규칙을 확인하세요.
  • error.log에 깔끔한 444가 아니라 업스트림 크래시가 찍힌다면, 애플리케이션 안정성 문제로 다루세요: 배포·트래픽 대비 타이밍을 잡고, nginx 규칙이 아니라 메모리 한도·워커 타임아웃·업스트림 자체 로그를 조사하세요.

관련 도구

관련 가이드

가이드 공유

[Ad] Guide Detail Inline
← 전체 가이드 보기