Files
infra-troubleshooting/nat-hairpinning.md
thug0bin c42d1b70ea Add troubleshooting docs: Caddy+Headscale proxy, NAT hairpinning, ODBC conflict
- caddy-headscale-proxy.md: HTTP redirect + HTTP/2 Upgrade header conflict fix
- nat-hairpinning.md: Same-LAN public IP access issue and auto-detection
- odbc-freetds-conflict.md: FreeTDS vs ODBC Driver 18 for MSSQL named instances
- README.md: Install script commands (individual + unified) and doc index

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:37:16 +00:00

2.4 KiB

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 무한 대기
# 같은 LAN에서 실행
curl -v http://head.pharmq.kr 2>&1 | head -10
# 결과: 공유기 login.cgi로 리다이렉트
# <meta http-equiv=refresh content="0; URL=login/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: 스크립트에서 자동 감지 (채택)

# 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.kr192.168.0.19(Caddy LAN IP)로 강제. 모든 공유기에 일일이 설정해야 해서 비현실적.

참고

  • 통합 설치 스크립트(pharmq-setup.sh)에 자동 감지 로직 포함됨
  • caddy-headscale-proxy.md와 함께 발생할 수 있음