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

73 lines
2.4 KiB
Markdown

# 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로 리다이렉트
# <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: 스크립트에서 자동 감지 (채택)
```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)와 함께 발생할 수 있음