포트 포워딩 없이 어디서든 홈 서버에 안전하게 접속한다. WireGuard 기반 Tailscale의 메시 네트워크 원리부터 다중 서브넷 Subnet Router, Exit Node 활용 시나리오, MagicDNS 커스텀 도메인, HuJSON 태그 기반 ACL, Tailscale SSH, 그리고 연결 끊김·DNS 오류·라우트 전파 실패 등 실전 트러블슈팅까지 심층적으로 다룬다.

Tailscale의 Zero-Trust 아키텍처 원리

기존의 VPN은 중앙 서버(VPN 게이트웨이)를 통해 모든 트래픽이 라우팅되어 병목과 단일 장애점(SPOF)이 발생한다. Tailscale은 WireGuard 프로토콜 위에 구축된 메시 네트워크 방식으로, 각 기기가 Coordination Server(controlplane.tailscale.com)를 통해 공개키를 교환한 후 직접 피어 투 피어(P2P)로 통신한다. STUN/TURN 방식의 NAT 홀 펀칭(홀 뚫기)을 사용해 대부분의 NAT 환경에서 직접 연결이 가능하며, 직접 연결이 불가한 경우에만 DERP(Designated Encrypted Relay Proxy) 서버를 경유한다.

제로 트러스트 모델의 핵심은 "네트워크 내부도 신뢰하지 않는다"는 원칙이다. Tailscale은 모든 연결 요청을 ID 기반으로 인증하며, 기기와 사용자의 신원이 확인된 경우에만 ACL이 허용한 리소스에만 접근을 허용한다. 각 기기의 Tailscale IP(100.x.x.x)는 재할당되지 않으므로 방화벽 규칙을 IP 기반으로 고정할 수 있다.

설치 및 기본 설정 — 5분 완성

단 한 줄의 명령으로 설치가 완료되며, 포트 포워딩이나 방화벽 설정 없이 즉시 원격 접속이 가능해진다. Ubuntu/Debian 계열 외에도 공식 패키지 레포지토리를 통해 다양한 배포판을 지원한다.

bash
# ── Tailscale 설치 (Ubuntu/Debian) ──────────────────────────────────────────
curl -fsSL https://tailscale.com/install.sh | sh

# 또는 공식 레포지토리 수동 추가
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.gpg | \
  sudo gpg --dearmor -o /usr/share/keyrings/tailscale-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] \
  https://pkgs.tailscale.com/stable/ubuntu noble main" | \
  sudo tee /etc/apt/sources.list.d/tailscale.list

sudo apt update && sudo apt install -y tailscale

# ── Tailnet에 기기 등록 ──────────────────────────────────────────────────────
# 출력된 URL을 브라우저에서 열어 Google/GitHub/Microsoft 계정으로 로그인
sudo tailscale up

# Tailscale SSH도 함께 활성화 (비밀번호 없이 SSH 접속 가능)
sudo tailscale up --ssh

# 기기 IP 및 상태 확인
tailscale ip -4     # 100.x.x.x 형태 (고정 할당)
tailscale ip -6     # fd7a::... 형태 IPv6
tailscale status    # 연결된 모든 기기 목록 및 상태
Tailscale 플랜 비교

무료 Personal 플랜은 기기 3대까지 지원하며 홈서버 단일 구성에는 충분하다. 기기를 더 추가하려면 Personal Pro($6/월, 기기 무제한)로 업그레이드하거나, Headscale(오픈소스 자체 호스팅 Control Plane)을 운영하는 방법도 있다. Headscale은 외부 서버 없이 완전 자체 운영이 가능하지만 DERP 서버를 별도 운영해야 한다.

Tailscale SSH — 키 관리 없는 안전한 접속

Tailscale SSH는 기존 OpenSSH와 병행 동작하며, Tailscale 네트워크 안에서는 키 관리 없이 인증된 기기끼리 SSH 접속이 가능하다. 접속 권한은 ACL 정책으로 제어되며, 세션 기록(Session Recording) 기능을 활성화하면 SSH 세션 전체를 감사 로그로 남길 수 있다.

bash
# ── [서버] Tailscale SSH 활성화 ─────────────────────────────────────────────
sudo tailscale up --ssh

# sshd를 완전히 끄지 않아도 됨 — 기존 OpenSSH와 병행 동작
# Tailscale SSH는 tailscaled가 처리, OpenSSH는 그대로 유지

# ── [클라이언트] 접속 테스트 ────────────────────────────────────────────────
# MagicDNS 기기 이름으로 접속 (IP 불필요)
ssh user@homeserver

# 또는 Tailscale IP로 접속
ssh user@100.x.x.x

# Tailscale이 인증을 처리하므로 ~/.ssh/authorized_keys 불필요
# (Tailscale 계정으로 인증된 기기만 접속 가능)

# ── SSH 체크 모드 — 접속 가능 여부 확인 ────────────────────────────────────
tailscale ssh --check homeserver

# ── [서버] Tailscale SSH 상태 확인 ──────────────────────────────────────────
tailscale status | grep -i ssh
sudo systemctl status tailscaled

Subnet Router — 다중 서브넷 광고와 IP 포워딩

Subnet Router를 활성화하면 Tailscale이 설치되지 않은 NAS, 프린터, IP 카메라, IoT 기기, 관리용 IPMI 인터페이스 등 홈 내부 네트워크 전체에 원격으로 접근할 수 있다. 여러 서브넷을 동시에 광고하거나, 사무실과 집 네트워크를 모두 노출하는 다중 Subnet Router 구성도 가능하다.

bash
# ── IP 포워딩 영구 활성화 (Subnet Router 필수 전제 조건) ────────────────────
sudo tee /etc/sysctl.d/99-tailscale.conf > /dev/null << 'EOF'
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
EOF

sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

# 적용 확인
sysctl net.ipv4.ip_forward   # 결과: net.ipv4.ip_forward = 1

# ── 단일 서브넷 광고 ─────────────────────────────────────────────────────────
sudo tailscale up \
  --advertise-routes=192.168.1.0/24 \
  --ssh

# ── 다중 서브넷 동시 광고 ───────────────────────────────────────────────────
# 예: 홈 LAN + IoT 전용 VLAN + 관리 네트워크
sudo tailscale up \
  --advertise-routes=192.168.1.0/24,192.168.10.0/24,10.0.0.0/24 \
  --ssh

# ── Admin 콘솔에서 경로 승인 (필수 단계) ────────────────────────────────────
# https://login.tailscale.com/admin/machines
# → 기기 클릭 → "..." 메뉴 → "Edit route settings"
# → 광고된 서브넷 옆 토글 활성화

# ── 클라이언트에서 Subnet Router 경로 수락 ──────────────────────────────────
# Admin 콘솔 승인 후 클라이언트에서도 수락 필요
tailscale up --accept-routes

# 라우팅 테이블 확인 (클라이언트)
ip route show | grep tailscale
tailscale ip
bash
# ── Subnet Router 라우트 전파 안됨 — 트러블슈팅 ────────────────────────────

# 1. IP 포워딩 상태 재확인
cat /proc/sys/net/ipv4/ip_forward   # 1이어야 함

# 2. tailscale 광고 상태 확인
tailscale status --peers | grep -A3 homeserver
# "ExitNodeOption: false" 와 "Relay: ..." 라인 확인

# 3. 라우트가 광고되고 있는지 확인
sudo tailscale debug netmap | grep -A5 "PrimaryRoutes"

# 4. 방화벽이 포워딩을 차단하는지 확인
sudo iptables -L FORWARD -n -v | head -20
# Docker를 함께 사용하는 경우 DOCKER-USER 체인도 확인

# 5. 라우트 직접 확인
ip route show table all | grep 192.168.

# 6. Claude Code로 진단
tailscale status | claude "Subnet Router 라우트가 클라이언트에 전파되지 않는 이유 분석해줘"

Exit Node — 공공 Wi-Fi 보안 강화와 지역 우회

Exit Node 설정을 통해 모든 인터넷 트래픽을 홈서버를 통해 라우팅하면, 공공 Wi-Fi 사용 시에도 가정용 IP로 안전하게 인터넷을 사용할 수 있다. 추가로, 해외에서 국내 IP가 필요한 스트리밍 서비스나 금융 거래 시에도 활용된다. Exit Node는 해당 기기를 통해 모든 트래픽이 나가므로 업로드 대역폭과 ISP 약관을 반드시 확인해야 한다.

bash
# ── [서버] Exit Node로 광고 ─────────────────────────────────────────────────
# IP 포워딩이 활성화되어 있어야 함 (위 Subnet Router 섹션 참조)
sudo tailscale up \
  --advertise-exit-node \
  --advertise-routes=192.168.1.0/24 \
  --ssh

# Admin 콘솔에서 Exit Node 승인
# https://login.tailscale.com/admin/machines
# → 기기 → "Edit route settings" → "Use as exit node" 활성화

# ── [클라이언트] Exit Node 사용 설정 ────────────────────────────────────────
# 서버 Tailscale IP 또는 기기 이름 지정
tailscale up --exit-node=100.x.x.x
# 또는 기기 이름으로
tailscale up --exit-node=homeserver

# 로컬 네트워크는 Exit Node 우회 (프린터·NAS 접근 유지)
tailscale up --exit-node=homeserver --exit-node-allow-lan-access=true

# Exit Node 비활성화 (직접 인터넷 복귀)
tailscale up --exit-node=

# ── Exit Node 동작 확인 ──────────────────────────────────────────────────────
# 클라이언트에서 외부 IP가 홈서버 IP인지 확인
curl -s https://ipinfo.io/json | python3 -m json.tool

# 라우팅 경로 확인
traceroute 8.8.8.8 | head -5
"Tailscale은 홈 네트워크를 클라우드처럼 만든다 — 어디서든, 포트 포워딩 없이, 키 관리 없이."

ACL HuJSON — 태그 기반 세밀한 접근 제어

Tailscale의 ACL(Access Control List)은 HuJSON 형식(주석이 허용되는 JSON)으로 작성하며, Admin 콘솔의 "Access Controls" 탭에서 직접 편집한다. 태그(tag) 기반 정책을 사용하면 기기 IP가 바뀌더라도 정책이 유지되며, 기기 역할에 따른 계층적 권한 관리가 가능하다. tagOwners는 해당 태그를 기기에 부여할 수 있는 사용자를 정의한다.

json
{
  // ── 태그 소유자 정의 ────────────────────────────────────────────────────
  // 각 태그를 기기에 부여할 수 있는 사용자(또는 그룹) 목록
  "tagOwners": {
    "tag:server":    ["autogroup:admin"],       // 홈서버·NAS 등 서비스 기기
    "tag:laptop":    ["autogroup:admin"],       // 개인 노트북·데스크톱
    "tag:mobile":    ["autogroup:admin"],       // 스마트폰·태블릿
    "tag:iot":       ["autogroup:admin"],       // IoT·스마트홈 기기
    "tag:readonly":  ["autogroup:admin"]        // 읽기 전용 접근 기기
  },

  // ── 사용자 그룹 정의 ─────────────────────────────────────────────────────
  "groups": {
    "group:admins":  ["user@example.com"],
    "group:family":  ["user@example.com", "spouse@example.com"]
  },

  // ── ACL 규칙 (위에서 아래로 순서대로 평가, 첫 번째 매칭 규칙 적용) ────
  "acls": [
    // 1. 랩톱·관리자: 서버에 모든 포트 전체 접근 허용
    {
      "action": "accept",
      "src":    ["tag:laptop", "group:admins"],
      "dst":    ["tag:server:*"]
    },

    // 2. 모바일: Jellyfin(8096), Portainer(9000)만 허용 — SSH 차단
    {
      "action": "accept",
      "src":    ["tag:mobile"],
      "dst":    ["tag:server:8096", "tag:server:9000"]
    },

    // 3. 가족: 미디어 서버만 접근 허용
    {
      "action": "accept",
      "src":    ["group:family"],
      "dst":    ["tag:server:8096", "tag:server:8920"]
    },

    // 4. IoT 기기: 인터넷만 허용, Tailnet 내부 통신 차단
    {
      "action": "accept",
      "src":    ["tag:iot"],
      "dst":    ["autogroup:internet:*"]
    },

    // 5. 읽기 전용: Samba 읽기 포트만 허용
    {
      "action": "accept",
      "src":    ["tag:readonly"],
      "dst":    ["tag:server:445"]
    }
    // 기본 정책: 위 규칙에 매칭되지 않은 모든 트래픽 차단 (묵시적 deny)
  ],

  // ── SSH 접근 제어 ─────────────────────────────────────────────────────────
  "ssh": [
    // 관리자 랩톱: 모든 서버에 자신 계정으로 SSH 허용
    {
      "action": "accept",
      "src":    ["tag:laptop"],
      "dst":    ["tag:server"],
      "users":  ["autogroup:nonroot"]
    },
    // 긴급 접근: admin 계정으로 모든 기기에서 서버 접속 허용
    {
      "action": "accept",
      "src":    ["group:admins"],
      "dst":    ["tag:server"],
      "users":  ["root", "ubuntu", "admin"]
    }
  ],

  // ── 테스트 규칙 ───────────────────────────────────────────────────────────
  // Admin 콘솔에서 "Test policy" 버튼으로 특정 src→dst 조합 사전 검증 가능
  "tests": [
    {
      "src":    "tag:mobile",
      "dst":    "tag:server:8096",
      "expect": "accept"
    },
    {
      "src":    "tag:mobile",
      "dst":    "tag:server:22",
      "expect": "deny"
    }
  ]
}

MagicDNS — 커스텀 도메인과 사내 DNS 통합

Admin 콘솔 → DNS → MagicDNS를 활성화하면 100.x.x.x 대신 homeserver.tail12345.ts.net과 같은 사람이 읽을 수 있는 FQDN으로 접속이 가능해진다. 추가로 커스텀 도메인(home.example.com)을 Tailscale 네임서버로 위임하거나, Pi-hole 같은 자체 DNS 서버를 Tailscale 전체 네임서버로 설정하는 것도 지원된다.

bash
# ── MagicDNS 활성화 후 기본 접속 테스트 ────────────────────────────────────
# Admin 콘솔에서 MagicDNS 활성화 후:
ping homeserver                      # 기기 이름으로 ICMP 핑
ssh user@homeserver                  # SSH 접속
curl http://homeserver:8096          # Jellyfin HTTP
curl https://homeserver:8920         # Jellyfin HTTPS
curl http://homeserver:9000          # Portainer

# Tailscale 전체 도메인 형식
# 기기이름.tailnet이름.ts.net
ping homeserver.tail12345.ts.net

# ── Tailscale DNS 상태 진단 ──────────────────────────────────────────────────
tailscale dns status
tailscale dns --help

# DNS 해석 테스트
dig @100.100.100.100 homeserver.tail12345.ts.net  # Tailscale DNS 서버 직접 쿼리
nslookup homeserver.tail12345.ts.net 100.100.100.100
bash
# ── 커스텀 DNS 서버(Pi-hole) 연동 ──────────────────────────────────────────
# Admin 콘솔 → DNS → "Custom nameservers" 에 Pi-hole IP 추가
# 예: 100.x.x.x (Pi-hole 서버의 Tailscale IP)

# "Override local DNS" 활성화 시: 모든 Tailnet 기기가 Pi-hole 사용
# 비활성화 시: 기기별 DNS 서버를 우선 사용

# ── Split DNS — 특정 도메인만 자체 DNS로 해석 ──────────────────────────────
# Admin 콘솔 → DNS → "Nameservers" → "Add nameserver" →
# "Restrict to domain" 에 ".home.arpa" 또는 "home.example.com" 입력
# 해당 도메인 쿼리만 지정 DNS로, 나머지는 기본 DNS로 처리

# ── DNS 트러블슈팅 ──────────────────────────────────────────────────────────
# DNS 해석 실패 시 단계별 진단
tailscale netcheck                          # 네트워크 연결성 전반 확인
resolvectl status                           # systemd-resolved 상태
resolvectl query homeserver.tail12345.ts.net # 실제 DNS 쿼리 테스트
cat /etc/resolv.conf                        # 현재 적용된 DNS 서버 확인

# Tailscale이 DNS를 변경했는지 확인
resolvectl status | grep -A5 "tailscale"

# DNS 강제 재시작
sudo systemctl restart systemd-resolved
sudo tailscale down && sudo tailscale up --ssh --accept-routes

연결 끊김·오류 — 실전 트러블슈팅

Tailscale 연결 문제는 대부분 NAT 타입, 방화벽, DNS 설정, 기기 키 만료 중 하나에서 발생한다. 단계별 진단 명령으로 원인을 빠르게 좁혀 나갈 수 있다.

bash
# ── 연결 상태 전반 진단 ─────────────────────────────────────────────────────
tailscale status                    # 전체 기기 목록과 연결 상태
tailscale status --active           # 현재 활성 연결만 표시
tailscale status --peers            # 피어별 세부 정보 (마지막 핸드셰이크 시간 포함)

# ── 특정 기기에 핑 테스트 ────────────────────────────────────────────────────
tailscale ping homeserver           # 첫 번째 핑 (키 교환 시간 포함)
tailscale ping homeserver --until-direct  # 직접 P2P 연결 확립될 때까지 반복

# 결과 예시:
# pong from homeserver (100.x.x.x) via DERP(Seoul) in 30ms   ← 릴레이 경유
# pong from homeserver (100.x.x.x) via 192.168.1.x:41641 in 2ms  ← 직접 연결

# ── 직접 연결이 안 되고 DERP 릴레이만 쓰는 경우 ─────────────────────────────
# 원인 1: UDP 41641 포트가 차단됨
sudo ufw allow 41641/udp comment 'Tailscale WireGuard'

# 원인 2: NAT 타입 문제 (Symmetric NAT)
tailscale netcheck
# "DERP latency" 섹션에서 사용 중인 릴레이 서버 확인
# "MappingVariesByDestIP: true" → Symmetric NAT, 직접 연결 어려움

# ── tailscaled 데몬 로그 확인 ────────────────────────────────────────────────
sudo journalctl -u tailscaled -n 100 --no-pager
sudo journalctl -u tailscaled -f                    # 실시간 로그 스트리밍

# 특정 오류 필터링
sudo journalctl -u tailscaled | grep -iE "error|warn|failed|expired"

# ── 연결 완전 재시작 ─────────────────────────────────────────────────────────
sudo systemctl restart tailscaled
sudo tailscale down && sudo tailscale up --ssh --accept-routes

# Claude Code로 로그 분석
sudo journalctl -u tailscaled -n 200 | claude "tailscale 연결 실패 원인 분석해줘"
bash
# ── 기기 키 만료 처리 ───────────────────────────────────────────────────────
# Tailscale 기기 키는 기본 180일 후 만료됨
# 만료 시 Admin 콘솔에서 "..." → "Disable key expiry" 로 영구 비활성화 가능
# 또는 자동 키 갱신 활성화

# 키 만료일 확인 (Admin 콘솔 또는 CLI)
tailscale status --json | python3 -c "
import json, sys, datetime
data = json.load(sys.stdin)
for peer in data.get('Peer', {}).values():
    exp = peer.get('KeyExpiry', '')
    if exp:
        dt = datetime.datetime.fromisoformat(exp.replace('Z', '+00:00'))
        print(f\"{peer['HostName']}: 만료일 {dt.strftime('%Y-%m-%d')}\")
"

# 키 갱신 (현재 기기)
sudo tailscale up   # 재인증으로 키 갱신

# Admin 콘솔에서 특정 기기 키 갱신:
# https://login.tailscale.com/admin/machines → 기기 → "..." → "Expire"
# 다음 tailscale up 시 재인증 강제

데이터·로그 관리 및 오래된 기기 정리

Tailscale 네트워크가 커질수록 더 이상 사용하지 않는 기기가 ACL 규칙을 복잡하게 만들고, MagicDNS 이름 충돌을 야기할 수 있다. 정기적인 기기 정리와 로그 모니터링이 필요하다.

bash
# ── tailscaled 로그 모니터링 ────────────────────────────────────────────────
# 최근 100줄 (페이저 없이 출력)
sudo journalctl -u tailscaled -n 100 --no-pager

# 특정 날짜 이후 로그
sudo journalctl -u tailscaled --since "2026-05-01 00:00:00"

# 로그 크기 확인 (journald 전체)
sudo journalctl --disk-usage

# tailscaled 로그만 지정 기간 보존 (30일)
sudo journalctl --vacuum-time=30d

# ── 연결 통계 수집 (주기적 모니터링 스크립트) ──────────────────────────────
tee ~/tailscale-status-check.sh > /dev/null << 'EOF'
#!/bin/bash
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
STATUS=$(tailscale status --peers 2>&1)
OFFLINE=$(echo "$STATUS" | grep -c "offline")
ONLINE=$(echo "$STATUS" | grep -c -v "offline")

echo "[$TIMESTAMP] 온라인: ${ONLINE} 기기, 오프라인: ${OFFLINE} 기기"
if [ "$OFFLINE" -gt 0 ]; then
    echo "오프라인 기기 목록:"
    echo "$STATUS" | grep "offline"
fi
EOF
chmod +x ~/tailscale-status-check.sh

# 크론에 등록 (매시간 상태 로그)
echo "0 * * * * $USER ~/tailscale-status-check.sh >> /var/log/tailscale-monitor.log 2>&1" | \
  sudo tee -a /etc/crontab

# ── 오래된 기기 제거 방법 ───────────────────────────────────────────────────
# 방법 1: Admin 콘솔 (GUI)
# https://login.tailscale.com/admin/machines
# → 제거할 기기 → "..." → "Remove"

# 방법 2: Tailscale API (자동화 스크립트에서 활용)
# API 키는 Admin 콘솔 → Settings → Keys 에서 발급
TAILSCALE_API_KEY="tskey-api-xxxx"
TAILNET="example.com"   # 또는 your-tailnet-name.gmail.com

# 전체 기기 목록 조회
curl -s -H "Authorization: Bearer $TAILSCALE_API_KEY" \
  "https://api.tailscale.com/api/v2/tailnet/$TAILNET/devices" | \
  python3 -m json.tool | grep -E '"name"|"lastSeen"'

# 특정 기기 제거 (기기 ID 필요)
DEVICE_ID="n1234567890"
curl -s -X DELETE \
  -H "Authorization: Bearer $TAILSCALE_API_KEY" \
  "https://api.tailscale.com/api/v2/device/$DEVICE_ID"

키 만료 자동 갱신 — 무중단 운영 설정

서버용 기기는 키 만료 시 원격 접속이 끊길 수 있어, Admin 콘솔에서 키 만료를 비활성화하거나 자동 갱신 스크립트를 설정하는 것이 중요하다.

bash
# ── 방법 1: Admin 콘솔에서 서버 기기 키 만료 비활성화 (권장) ───────────────
# https://login.tailscale.com/admin/machines
# → 서버 기기 선택 → "..." 메뉴 → "Disable key expiry"
# 이후 해당 기기는 키 만료 없이 영구 연결 유지

# ── 방법 2: systemd 서비스로 주기적 키 갱신 자동화 ──────────────────────────
sudo tee /etc/systemd/system/tailscale-renew.service > /dev/null << 'EOF'
[Unit]
Description=Tailscale key renewal
After=network-online.target tailscaled.service

[Service]
Type=oneshot
# --auth-key 옵션으로 재인증 (Admin 콘솔에서 재사용 가능한 auth key 발급 필요)
ExecStart=/usr/bin/tailscale up --auth-key=tskey-auth-xxxx --reset
RemainAfterExit=yes
EOF

sudo tee /etc/systemd/system/tailscale-renew.timer > /dev/null << 'EOF'
[Unit]
Description=Tailscale key renewal timer

[Timer]
# 매월 1일 오전 3시 갱신
OnCalendar=*-*-01 03:00:00
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now tailscale-renew.timer

# 타이머 상태 확인
sudo systemctl list-timers tailscale-renew.timer

Claude Code로 네트워크 설정 분석

복잡한 ACL 정책이나 네트워크 문제가 발생했을 때, Claude Code CLI를 터미널에서 직접 사용하면 tailscale status, journalctl, ip route 출력을 AI가 즉시 분석해 해결 방향을 제시한다.

bash
# ── 시나리오 1: 연결 끊김 분석 ─────────────────────────────────────────────
tailscale status | claude "tailscale 연결 상태 분석해줘. 문제가 있는 기기가 있으면 알려줘"

# ── 시나리오 2: DNS 해석 실패 분석 ──────────────────────────────────────────
{
  echo "=== tailscale dns status ==="
  tailscale dns status
  echo "=== resolvectl status ==="
  resolvectl status 2>/dev/null || cat /etc/resolv.conf
  echo "=== dig test ==="
  dig homeserver.tail12345.ts.net 2>&1
} | claude "MagicDNS DNS 해석이 실패하는 이유 분석해줘"

# ── 시나리오 3: Subnet Router 라우팅 문제 ───────────────────────────────────
{
  echo "=== ip route ==="
  ip route show
  echo "=== tailscale status ==="
  tailscale status --peers
  echo "=== sysctl forwarding ==="
  sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding
} | claude "Subnet Router 192.168.1.0/24 라우팅이 클라이언트에서 동작하지 않는 이유 분석해줘"

# ── 시나리오 4: ACL 정책 검증 ───────────────────────────────────────────────
cat /path/to/tailscale-acl.hujson | claude "이 ACL 정책에서 tag:mobile이 port 22에 접근 가능한지 확인해줘"

# ── 시나리오 5: tailscaled 데몬 오류 ────────────────────────────────────────
sudo journalctl -u tailscaled --since "1 hour ago" | \
  claude "tailscaled 오류 로그 분석해줘. 핵심 원인과 해결 방법 알려줘"

# Claude Code CLI가 없는 경우 설치
curl -fsSL https://claude.ai/install.sh | sh