nginx 497 오류: HTTP를 HTTPS 포트로
nginx가 TLS 포트에서 평문 HTTP를 받으면 497. 스킴·프록시·리다이렉트 3단계로 원인을 짚습니다. 무료 즉시 진단으로 바로 확인.
내 도메인에 이 문제가 있는지 지금 확인
무료, 가입 불필요. 이 가이드가 다루는 항목을 바로 검사하고 조치 방법을 알려드립니다.
Problem
사이트 요청이 497 HTTP Request Sent to HTTPS Port로 실패하거나, 응답 본문에 400 Bad Request — The plain HTTP request was sent to HTTPS port가 뜹니다. 497이라는 숫자가 nginx access.log, proxy_pass 오류, 혹은 헬스체크 대시보드에 나타납니다.
Symptoms
- nginx가
497상태를 로그하거나, 본문이 그대로 “The plain HTTP request was sent to HTTPS port”인 400을 반환. https://로 치면 되는데, 같은 포트에http://를 쓰는 순간 깨짐.- nginx 앞의 리버스 프록시·로드밸런서·인그레스가 TLS 변경 후 502/400을 반환하기 시작.
- 443(또는 8443 같은 커스텀 포트)의 모니터링 프로브·헬스체크는 실패인데 브라우저는 멀쩡.
What This Error Actually Means
497은 인증서 문제의 정확히 반대를 알려줍니다. TLS는 설정돼 있습니다. 리스너에 ssl 키워드가 있고, 인증서가 로드됐고, 핸드셰이크도 될 겁니다 — 그런데 도착한 바이트가 TLS 핸드셰이크가 전혀 아니었습니다. 평문 HTTP 요청이었죠: GET / HTTP/1.1\r\nHost: .... nginx는 첫 바이트를 읽고, TLS ClientHello를 기대한 자리에서 ASCII 요청 라인을 보고는 거부합니다. 오해를 부르는 TLS 오류 대신 자기 코드 497을 올리고 400으로 답합니다.
이건 SSL_ERROR_RX_RECORD_TOO_LONG의 반대입니다. 그 오류는 클라이언트가 TLS로 말하는데 포트가 평문으로 답한 경우, 497은 클라이언트가 평문으로 말하는데 포트가 TLS를 기대한 경우. 둘 다 누군가 스킴을 틀렸고, 497은 그걸 TLS 쪽에서 nginx가 알아챈 것뿐입니다.
핵심 결론: 결함은 거의 nginx의 TLS 설정에 있지 않습니다. ssl 리스너의 앞단 — http://를 https:// 백엔드로 넘기는 프록시, 스킴을 잘못 잡은 헬스체크, http://host:443을 친 사람 — 에 있습니다.
Top 3 Causes
- 리버스 프록시/로드밸런서가 평문 HTTP를 TLS 포트로 넘김 — 프로덕션에서 가장 흔합니다. 앞단이 TLS를 종단한 뒤
ssl로 listen하는 nginx에proxy_pass http://backend:443;을 합니다. 평문을 TLS를 요구하는 포트로 보내는 거죠. 틀린 건proxy_pass의 스킴(또는 ALB 대상 그룹 프로토콜)이지 인증서가 아닙니다. - 헬스체크/모니터가 스킴을 틀림 — 업타임 프로브, 쿠버네티스 readiness 체크, ELB 헬스체크가 HTTPS만 말하는 포트에 HTTP로 설정됨. 서비스는 정상인데 평문으로 두드리는 프로브가 거짓말을 합니다.
- 사람/스크립트가 HTTPS 전용 포트에
http://를 침 — 오래된 북마크, 하드코딩된http://링크,https://없는 curl,http://host:8443을 가리킨 클라이언트. 하나씩은 무해하지만 로그에서 시끄럽고 스크립트가 조용히 실패하면 헷갈립니다.
Diagnose with DechoNet
- SSL 진단으로 포트가 실제로 유효한 인증서를 제시하고 TLS 핸드셰이크를 완료하는지 확인하세요. SSL 진단이 성공하면 TLS는 멀쩡하고, 497은 nginx 앞의 평문 요청에서 온 것 — 인증서가 아닙니다.
- Port 진단으로 포트가 열려 도달 가능한지 확인해 “틀린 스킴”과 “리스너 없음”을 분리하세요.
- HTTP 진단을
https://URL에 돌려 앱이 TLS 위에서 제대로 응답하는지 확인하고, 결함을 평문을 보내는 쪽으로 좁히세요.
Resolution Checklist
- 패턴 확인: 같은 포트에
https://는 되는데http://는 실패하나요? 그렇다면 TLS는 건강하고 평문 요청이 TLS 리스너에 닿는 게 문제입니다. - 이 nginx 앞의 모든
proxy_pass와 업스트림 정의를 확인. TLS 포트는proxy_pass https://...;로 지정해야 하며http://...;가 아닙니다. AWS ALB/NLB라면 대상 그룹 프로토콜을 HTTPS로. - 헬스체크/모니터 설정 확인: 443(또는 TLS 포트)의 프로브는 HTTPS 스킴을 써야 합니다. 아니면 서비스가 멀쩡해도 497이 영원히 뜹니다.
- HTTPS 전용 포트의 진짜 클라이언트 오타에는
server블록에error_page 497 =301 https://$host$request_uri;를 넣어 떠도는 평문 요청을 리다이렉트하세요. 단, 프록시 오설정을 배제한 뒤에만 — 앞단이 평문을 보내는 쪽이면 루프가 납니다. - SSL 진단으로 핸드셰이크 완료를 확인. 되면 인증서 보기를 멈추고 앞단의 스킴을 고치러 가세요.
When to Escalate
- SSL 진단은 오리진에 건강한 인증서를 보여주는데 497이 계속되면, 로드밸런서나 인그레스를 맡은 사람에게 넘기세요 — 평문 요청이 엣지와 nginx 사이에서 생성되고 있고,
proxy_pass스킴이나 대상 그룹 프로토콜이 지렛대입니다. - 인증서 설치나 마이그레이션 직후 497이 시작됐다면, 새 TLS 포트로 대화하도록 바뀌었지만 여전히
http://를 보내도록 설정된 앞단을 의심하세요.
관련 도구
관련 가이드
가이드 공유