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>
This commit is contained in:
133
caddy-headscale-proxy.md
Normal file
133
caddy-headscale-proxy.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# Caddy + Headscale 리버스 프록시 트러블슈팅
|
||||
|
||||
> 날짜: 2026-04-06
|
||||
> 환경: Caddy v2.11.2, Headscale 0.26.1 (Docker), Tailscale 1.96.4
|
||||
|
||||
## 증상
|
||||
|
||||
외부 노드에서 `tailscale up --login-server=http://head.pharmq.kr` 실행 시 무한 대기 또는 실패.
|
||||
|
||||
- PBS-LXC, 약국 PVE 등 외부 노드에서 Headscale 등록 불가
|
||||
- Headscale Docker 재시작 후 기존 노드 재연결 실패
|
||||
- Caddy 로그에 502 Bad Gateway 다수 발생
|
||||
|
||||
## 원인: 2가지 문제
|
||||
|
||||
### 문제 1: HTTP → HTTPS 강제 리다이렉트 (308)
|
||||
|
||||
**Caddy 동작**: TLS 설정이 있는 도메인은 자동으로 HTTP(80) → HTTPS(443) 308 리다이렉트 생성
|
||||
|
||||
```
|
||||
# Tailscale 클라이언트 요청
|
||||
POST http://head.pharmq.kr/ts2021
|
||||
|
||||
# Caddy 응답
|
||||
HTTP/1.1 308 Permanent Redirect
|
||||
Location: https://head.pharmq.kr/
|
||||
Server: Caddy
|
||||
```
|
||||
|
||||
**왜 문제인가**: Tailscale 클라이언트는 `--login-server=http://...`로 설정되면 HTTP를 기대함. HTTPS 리다이렉트를 자동으로 따라가지 못함.
|
||||
|
||||
**해결**: `http://` 전용 블록을 별도로 추가
|
||||
|
||||
```caddy
|
||||
http://head.pharmq.kr {
|
||||
reverse_proxy 192.168.0.100:8070
|
||||
}
|
||||
```
|
||||
|
||||
### 문제 2: HTTP/2에서 Upgrade 헤더 호환 불가 (502)
|
||||
|
||||
**Caddy 동작**: HTTPS 연결에서 백엔드로 프록시할 때 HTTP/2를 사용
|
||||
|
||||
```
|
||||
# Tailscale TS2021 프로토콜 요청
|
||||
POST /ts2021 HTTP/1.1
|
||||
Connection: upgrade
|
||||
Upgrade: tailscale-control-protocol
|
||||
|
||||
# Caddy가 h2로 변환하여 백엔드에 전달 → 에러
|
||||
http2: invalid Upgrade request header: ["tailscale-control-protocol"]
|
||||
→ 502 Bad Gateway
|
||||
```
|
||||
|
||||
**왜 문제인가**: HTTP/2 스펙(RFC 7540)에서 `Connection`과 `Upgrade` 헤더는 hop-by-hop이라 금지됨. Tailscale TS2021은 HTTP/1.1 Upgrade 메커니즘에 의존.
|
||||
|
||||
**Caddy 로그 (실제)**:
|
||||
```json
|
||||
{
|
||||
"level": "error",
|
||||
"msg": "http2: invalid Upgrade request header: [\"tailscale-control-protocol\"]",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"uri": "/ts2021",
|
||||
"headers": {
|
||||
"Connection": ["upgrade"],
|
||||
"Upgrade": ["tailscale-control-protocol"]
|
||||
}
|
||||
},
|
||||
"status": 502
|
||||
}
|
||||
```
|
||||
|
||||
**해결**: 백엔드 연결을 HTTP/1.1로 강제 + 스트리밍 즉시 전달
|
||||
|
||||
```caddy
|
||||
head.pharmq.kr {
|
||||
reverse_proxy 192.168.0.100:8070 {
|
||||
flush_interval -1
|
||||
transport http {
|
||||
versions 1.1
|
||||
}
|
||||
}
|
||||
tls {
|
||||
dns cloudflare {env.CF_API_TOKEN}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 최종 Caddyfile 설정
|
||||
|
||||
```caddy
|
||||
# Headscale — HTTP (리다이렉트 없이 직접 프록시)
|
||||
http://head.pharmq.kr {
|
||||
reverse_proxy 192.168.0.100:8070
|
||||
}
|
||||
|
||||
# Headscale — HTTPS (HTTP/1.1 강제, TS2021 Upgrade 호환)
|
||||
head.pharmq.kr {
|
||||
reverse_proxy 192.168.0.100:8070 {
|
||||
flush_interval -1
|
||||
transport http {
|
||||
versions 1.1
|
||||
}
|
||||
}
|
||||
|
||||
tls {
|
||||
dns cloudflare {env.CF_API_TOKEN}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 검증 방법
|
||||
|
||||
```bash
|
||||
# HTTP 프록시 확인 (리다이렉트 없어야 함)
|
||||
curl -v http://head.pharmq.kr 2>&1 | grep -E "HTTP|Location|Server"
|
||||
# 기대: HTTP/1.1 404 Not Found, Server 없거나 Via: 1.1 Caddy
|
||||
|
||||
# HTTPS 프록시 확인
|
||||
curl -sk https://head.pharmq.kr/ts2021 2>&1 | head -5
|
||||
# 502가 아니어야 함
|
||||
|
||||
# Tailscale 등록 테스트
|
||||
tailscale up --login-server=http://head.pharmq.kr \
|
||||
--authkey=<KEY> --accept-routes --accept-dns=false
|
||||
```
|
||||
|
||||
## 참고
|
||||
|
||||
- Docker 포트 매핑: 호스트 8070 → 컨테이너 8080
|
||||
- Headscale config: `listen_addr: 0.0.0.0:8080`
|
||||
- 같은 LAN에서는 NAT Hairpinning 문제로 `http://192.168.0.100:8070` 직접 사용 필요 ([nat-hairpinning.md](nat-hairpinning.md) 참조)
|
||||
Reference in New Issue
Block a user