온프렘 Pi에서 낭만 노트를 재기동한 직후 backend가 RDS 주소를 해석하지 못해(ENOTFOUND) 재시작을 반복했고, frontend는 API 프록시에 실패했습니다. 석촌 OPNsense Unbound의 DNS rebind 보호가 사설 IP로 해석되는 RDS 응답을 삭제한 것이 원인이었습니다. Route 53 Resolver inbound endpoint를 만들고 OPNsense에서 RDS 도메인 조회를 VPN 경유로 전달하도록 구성해 DNS를 복구했습니다. 이후 드러난 IAM 인증 첫 연결 지연에 대비해 DB 연결 timeout도 상향했습니다.
기간
2026-10-08 08:23 KST
2026-10-08 09:06 KST
영향 서비스
낭만 노트(온프렘 Pi Docker Compose) backend API 및 frontend 전체 기능
담당자
리포터: 이성원 / 작업자: 이성원
기술 임팩트
backend(NestJS)가 기동 시 DB 연결에 실패해 약 43분 동안 crash loop 상태였고, 그동안 frontend의 모든 API 요청이 ECONNREFUSED로 실패했습니다. RDS, 보안그룹, NACL, Site-to-Site VPN, TLS 경로는 모두 정상이었습니다. 문제는 석촌 DNS가 RDS의 사설 IP 응답을 지운 것이었습니다. 장애 이전 백업에도 같은 DNS 설정이 있었으므로, 원래 있던 문제가 재기동하면서 새로 DNS를 조회하는 순간 드러난 것입니다.
RDS private endpoint는 공용 DNS에서 VPC 사설 IP로 해석됩니다. 석촌 OPNsense Unbound에는 DNS rebind 보호가 켜져 있었습니다. 이 기능은 10.0.0.0/8 같은 사설 대역이 담긴 응답을 삭제하는데, 예외 도메인(Private Domains)이 비어 있었습니다. 그 결과 Pi는 answer가 빈 NOERROR 응답을 받았고, Node.js는 이를 ENOTFOUND로 처리해 TypeORM 연결 재시도 끝에 프로세스가 종료되었습니다.
기여 요인
- 온프렘에서 AWS private 리소스 이름을 VPC 내부 DNS가 아닌 공용 재귀 조회로 해석하고 있었음
- backend가 기동 시 한 번만 DNS를 조회하고 연결 풀을 유지해, 컨테이너가 오래 떠 있는 동안에는 DNS 문제가 드러나지 않았음
- DNS를 복구한 직후 RDS IAM 인증 첫 연결이 약 24초 걸렸고, 앱 연결 timeout 기본값 5초를 넘겨 추가 재시작이 발생함
- 온프렘 DNS 경유 RDS 이름 해석 여부와 backend 재시작 횟수를 감시하는 모니터링이 없었음
- OPNsense가 policy 기반 IPsec이라서, 방화벽이 직접 보내는 DNS 질의는 출발지를 LAN 주소로 지정해야 VPN을 통과함
근거 자료
- backend 로그에서 getaddrinfo ENOTFOUND <rds-endpoint> 및 exited with code 1 (restarting) 반복 확인
- frontend 로그에서 Failed to proxy http://localhost:9999 ... ECONNREFUSED 반복 확인
- 석촌 DNS 질의는 NOERROR지만 answer가 없었고, 공용 DNS(1.1.1.1, 8.8.8.8)는 같은 이름을 VPC 사설 IP로 정상 응답
- 사설 IP를 반환하는 다른 테스트 도메인도 석촌 DNS에서 동일하게 빈 응답이 나와 rebind 보호가 원인임을 확인
- OPNsense Unbound 설정에서 Private Address에 10.0.0.0/8 등 16개 대역이 등록되어 있고 Private Domains가 비어 있음을 확인
- 장애 이전 OPNsense 설정 백업에도 같은 rebind 설정이 있어 방화벽 설정 변경이 원인이 아님을 확인
- AWS에서 RDS available, 보안그룹 5432는 온프렘 LAN과 ECS SG에만 허용, 기본 NACL 전체 허용, VPN 두 터널 UP 확인
- Pi에서 RDS 5432로 PostgreSQL SSLRequest를 보내 'S' 응답(11~21ms)을 받고 STARTTLS TLS 핸드셰이크 성공을 확인
- DNS 복구 후 실제 IAM 토큰 연결이 처음에는 24,215ms 걸리고 이후 441~637ms로 정상화된 것을 측정
- RDS PostgreSQL 로그에서 온프렘 클라이언트의 'could not receive data from client: Connection reset by peer' 기록 확인
타임라인
- 2026-10-08 08:23 | 온프렘 Pi에서 낭만 노트 docker compose down/up 후 backend crash loop 시작