# NAT Hairpinning (NAT Loopback) 문제 > 날짜: 2026-04-06 > 환경: 같은 LAN 내 PVE에서 공인 IP 도메인 접근 시 ## 증상 같은 LAN(192.168.0.x)에 있는 PVE에서 `http://head.pharmq.kr` 접속 시: - Caddy가 아닌 **공유기 웹 관리 페이지**가 응답 - `tailscale up --login-server=http://head.pharmq.kr` 무한 대기 ```bash # 같은 LAN에서 실행 curl -v http://head.pharmq.kr 2>&1 | head -10 # 결과: 공유기 login.cgi로 리다이렉트 # ``` ## 원인 `head.pharmq.kr` → DNS → `118.44.36.28` (공인 IP) → 공유기 같은 공유기 뒤에 있는 장비가 자기 공유기의 공인 IP로 접근하면: 1. 패킷이 공유기로 감 2. 공유기가 "이건 내 IP" 판단 → 내부 포트포워딩 대신 자기 웹UI 응답 3. Caddy(192.168.0.19)까지 도달 안 함 이것이 **NAT Hairpinning** (=NAT Loopback) 문제. ## 영향 범위 | 상황 | 문제 발생? | |------|-----------| | 같은 공유기 뒤 (같은 LAN) | **O** — 공유기가 가로챔 | | 같은 IP 대역이지만 다른 공유기 (외부 약국) | **X** — 인터넷 경유 정상 | | 완전 다른 네트워크 (외부) | **X** — 정상 | ## 해결 방법 ### 방법 1: 스크립트에서 자동 감지 (채택) ```bash # Headscale 8070 포트에 실제 응답하는지 확인 if curl -s --connect-timeout 3 -o /dev/null -w "%{http_code}" \ http://192.168.0.100:8070/ 2>/dev/null | grep -q "200\|404"; then HEADSCALE_SERVER="http://192.168.0.100:8070" # LAN 직접 else HEADSCALE_SERVER="http://head.pharmq.kr" # 외부 도메인 fi ``` ping으로 판단하면 안 됨 — 외부 약국에도 192.168.0.100 장비가 있을 수 있음. **Headscale 포트 응답**으로 판단해야 정확. ### 방법 2: 공유기 NAT Loopback 활성화 대부분의 가정용/ISP 공유기는 미지원: | 공유기 | NAT Loopback 지원 | |--------|-------------------| | ipTIME (한국 약국 대부분) | X 또는 숨김 설정 | | KT/SKB/LG U+ 기본 공유기 | X | | MikroTik, pfSense, UniFi | O | ### 방법 3: 내부 DNS 오버라이드 공유기 DNS에서 `head.pharmq.kr` → `192.168.0.19`(Caddy LAN IP)로 강제. 모든 공유기에 일일이 설정해야 해서 비현실적. ## 참고 - 통합 설치 스크립트(`pharmq-setup.sh`)에 자동 감지 로직 포함됨 - [caddy-headscale-proxy.md](caddy-headscale-proxy.md)와 함께 발생할 수 있음