
Tailscale 구성에 대한 보안 감사 도구입니다. 테일넷(tailnet)에서 잘못된 구성, 과도하게 허용적인 접근 제어, 보안 모범 사례 위반을 스캔합니다.
Tailscale 구성을 위한 보안 감사 도구. Tailsnitch는 50개 이상의 잘못된 구성, 과도하게 허용적인 접근 제어, 보안 모범 사례 위반을 스캔합니다.
# 1. Set your Tailscale API credentials
export TS_API_KEY="tskey-api-..."
# 2. Run audit
tailsnitch
# 3. See only high-severity findings
tailsnitch --severity high
# 4. Fix some issues ~interactively~ yolo mode
tailsnitch --fix
최신 릴리스를 GitHub Releases에서 다운로드하세요.
macOS 사용자: 다운로드 후 격리 속성 제거:
sudo xattr -rd com.apple.quarantine tailsnitch
go install github.com/Adversis/tailsnitch@latest
git clone https://github.com/Adversis/tailsnitch.git
cd tailsnitch
go build -o tailsnitch .
Tailsnitch는 두 가지 인증 방법을 지원합니다. 둘 다 구성된 경우 OAuth가 선호됩니다.
OAuth 클라이언트는 직원이 퇴사해도 만료되지 않는 범위 지정 및 감사 가능한 액세스를 제공합니다.
export TS_OAUTH_CLIENT_ID="..."
export TS_OAUTH_CLIENT_SECRET="tskey-client-..."
OAuth 클라이언트 생성: https://login.tailscale.com/admin/settings/oauth
읽기 전용 감사에 필요한 범위:
all:read (가장 간단), 또는 개별적으로:policy_file:read - ACL 정책devices:core:read - 장치 목록dns:read - DNS 구성auth_keys:read - 인증 키 (AUTH 검사용)수정 모드를 위한 추가 범위:
devices:core - 장치 삭제, 태그 수정 (태그 선택 필요)auth_keys - 인증 키 삭제API 키는 생성한 사용자로 작동하며 해당 사용자의 권한을 상속합니다.
export TS_API_KEY="tskey-api-..."
API 키 생성: https://login.tailscale.com/admin/settings/keys
# 전체 감사 실행
tailsnitch
# 통과 검사도 표시 (자세히)
tailsnitch --verbose
# 처리를 위해 JSON으로 출력
tailsnitch --json
# 특정 tailnet 감사 (OAuth 클라이언트가 여러 tailnet에 액세스할 수 있는 경우)
tailsnitch --tailnet mycompany.com
# 치명 및 높음 심각도 문제만 표시
tailsnitch --severity high
# 카테고리별 필터
tailsnitch --category access # ACL 문제
tailsnitch --category auth # 인증 및 키
tailsnitch --category device # 장치 보안
tailsnitch --category network # 네트워크 노출
tailsnitch --category ssh # SSH 규칙
tailsnitch --category log # 로깅 및 관리
# 특정 검사만 실행
tailsnitch --checks ACL-001,AUTH-001,DEV-010
tailsnitch --checks stale-devices,tailnet-lock-not-enabled
# 사용 가능한 모든 검사 목록
tailsnitch --list-checks
수정 모드를 사용하면 Tailscale API를 통해 직접 문제를 해결할 수 있습니다:
# 대화형 수정 모드
tailsnitch --fix
# 수정될 내용 미리 보기 (모의 실행)
tailsnitch --fix --dry-run
# 안전한 수정 사항 자동 선택 (여전히 확인 필요)
tailsnitch --fix --auto
# 수정 작업의 감사 로깅 비활성화
tailsnitch --fix --no-audit-log
API로 수정 가능한 항목:
| 검사 | 작업 |
|---|---|
| AUTH-001, AUTH-002, AUTH-003 | 인증 키 삭제 |
| AUTH-004 | 임시 키로 교체 |
| DEV-002 | 사용자 장치에서 태그 제거 |
| DEV-004 | 오래된 장치 삭제 |
수정 모드는 수동 개입이 필요한 문제에 대해 관리 콘솔로의 직접 링크도 제공합니다.
공통 기준(CC) 제어 매핑을 사용하여 SOC 2 감사를 위한 증거 보고서 생성:
# JSON으로 내보내기
tailsnitch --soc2 json > soc2-evidence.json
# CSV로 내보내기 (스프레드시트용)
tailsnitch --soc2 csv > soc2-evidence.csv
SOC 2 보고서에는 다음이 포함됩니다:
예시 CSV 출력:
resource_type,resource_id,resource_name,check_id,check_title,cc_codes,status,details,tested_at
device,node123,prod-server,DEV-001,Tagged devices with key expiry disabled,CC6.1;CC6.3,PASS,Tags: [tag:server] key expiry enabled,2025-01-05T10:30:00Z
key,tskey-auth-xxx,tskey-auth-xxx,AUTH-001,Reusable auth keys exist,CC6.1;CC6.2;CC6.3,FAIL,Reusable key expires in 45 days,2025-01-05T10:30:00Z
.tailsnitch-ignore 파일을 생성하여 알려진 수락된 위험에 대한 결과를 억제하세요:
# .tailsnitch-ignore
# 정보성 검사 무시
ACL-008 # 의도적으로 그룹을 사용하지 않음
ACL-009 # 기존 ACL이 우리 사용 사례에 적합함
# 특정 중간 검사를 정당성과 함께 무시
DEV-006 # 외부 장치는 승인된 계약자임
LOG-001 # 흐름 로그는 Enterprise 플랜 필요
무시 파일 위치 (순서대로 확인):
.tailsnitch-ignore~/.tailsnitch-ignore# 특정 무시 파일 사용
tailsnitch --ignore-file /path/to/ignore
# 무시 파일 처리 완전 비활성화
tailsnitch --no-ignore
# 전체 보고서 내보내기
tailsnitch --json > audit.json
# 실패한 검사를 TSV로 추출
tailsnitch --json | jq -r '
.suggestions
| map(select(.pass == false))
| .[]
| [.id, .title, .severity, .remediation]
| @tsv
' > findings.tsv
# 심각도별 요약
tailsnitch --json | jq '
.suggestions
| map(select(.pass == false))
| group_by(.severity)
| map({severity: .[0].severity, count: length})
'
# 관리 링크가 있는 치명/높음 문제 목록
tailsnitch --json | jq -r '
.suggestions
| map(select(.pass == false and (.severity == "CRITICAL" or .severity == "HIGH")))
| .[]
| "\(.id): \(.title)\n Fix: \(.fix.admin_url // "manual")\n"
'
Tailsnitch는 7개 카테고리에 걸쳐 52개의 보안 검사를 수행합니다. 각 검사에 대한 자세한 문서는 docs/CHECKS.md를 참조하세요.
로깅 구성, DNS 설정, 사용자 역할, 수동 확인 항목에 대한 검사입니다.
+=====================================================================+
| TAILSNITCH SECURITY AUDIT |
| Tailnet: example.com |
| Version: 1.0.0 (build: abc123) |
+=====================================================================+
Using ignore file: .tailsnitch-ignore (3 rules)
=== ACCESS CONTROLS ===================================================
[CRITICAL] ACL-001: Default 'allow all' policy active
Your ACL policy omits the 'acls' field. Tailscale applies a
default 'allow all' policy, granting all devices full access.
Remediation:
Define explicit ACL rules following least privilege principle.
Source: https://tailscale.com/kb/1192/acl-samples
----------------------------------------------------------------------
=== AUTHENTICATION & KEYS =============================================
[HIGH] AUTH-001: Reusable auth keys exist
Found 2 reusable auth key(s). These can be reused to add
multiple devices if compromised.
Details:
- Key tskey-auth-xxx (expires in 45 days)
- Key tskey-auth-yyy (expires in 89 days)
Remediation:
Store reusable keys in a secrets manager. Prefer one-off keys.
Source: https://tailscale.com/kb/1085/auth-keys
----------------------------------------------------------------------
SUMMARY
======================================================================
Critical: 1 High: 3 Medium: 5 Low: 2 Info: 8
Total findings: 19 | Passed: 33
Tailnet Lock 검사(DEV-010, DEV-012)는 로컬 tailscale CLI가 필요하며 로컬 머신의 데몬에 대해 실행됩니다. --tailnet을 사용하여 원격 tailnet을 감사할 때 이러한 검사는 감사 대상 tailnet이 아닌 로컬 상태를 반영합니다.
# 필요한 경우 사용자 정의 tailscale 바이너리 경로 지정
tailsnitch --tailscale-path /opt/tailscale/bin/tailscale
CI/CD 파이프라인에서 Tailsnitch를 실행하여 보안 회귀를 잡아내세요:
# GitHub Actions 예시
- name: Tailscale 보안 감사
env:
TS_OAUTH_CLIENT_ID: ${{ secrets.TS_OAUTH_CLIENT_ID }}
TS_OAUTH_CLIENT_SECRET: ${{ secrets.TS_OAUTH_CLIENT_SECRET }}
run: |
tailsnitch --json > audit.json
# 치명 또는 높음 심각도 문제가 있으면 실패
if tailsnitch --severity high --json | jq -e '.summary.critical + .summary.high > 0' > /dev/null; then
echo "치명 또는 높음 심각도 문제가 발견되었습니다!"
tailsnitch --severity high
exit 1
fi
MIT
지침은 CONTRIBUTING.md를 참조하세요.
| DEV-005 | 보류 중인 장치 승인 |
| 플래그 | 설명 |
|---|
--json | JSON으로 출력 |
--severity | 최소 심각도로 필터: critical, high, medium, low, info |
--category | 카테고리로 필터: access, auth, network, ssh, log, device, dns |
--checks | 특정 검사 실행 (쉼표로 구분된 ID 또는 슬러그) |
--list-checks | 사용 가능한 모든 검사 목록 표시 후 종료 |
--tailnet | 감사할 tailnet 지정 (기본값: API 키 기준) |
--verbose | 통과 검사도 표시 |
--fix | 대화형 수정 모드 활성화 |
--auto | 안전한 수정 사항 자동 선택 (--fix 필요) |
--dry-run | 실행하지 않고 수정 작업 미리 보기 (--fix 필요) |
--no-audit-log | 수정 작업의 감사 로깅 비활성화 |
--soc2 | SOC 2 증거 내보내기: json 또는 csv |
--tailscale-path | tailscale CLI 경로 (Tailnet Lock 검사용) |
--ignore-file | 무시 파일 경로 |
--no-ignore | 무시 파일 처리 비활성화 |
--version | 버전 정보 표시 |
| ID | 검사 | 위험 |
|---|
| ACL-001 | 기본 '모두 허용' 정책 | 모든 장치에 제한 없는 액세스 |
| ACL-002 | SSH autogroup:nonroot 오구성 | 모든 비루트 사용자로 SSH 가능 |
| ACL-006 | tagOwners 범위가 너무 넓음 | 태그를 통한 권한 상승 |
| ACL-007 | autogroup:danger-all 사용 | 외부 사용자에게 액세스 권한 부여 |
| ID | 검사 | 위험 |
|---|
| AUTH-001 | 재사용 가능한 인증 키 | 도난 시 무제한 장치 추가 가능 |
| AUTH-002 | 긴 만료 인증 키 | 확장된 노출 기간 |
| AUTH-003 | 사전 승인된 키 | 장치 승인 우회 |
| DEV-001 | 키 만료가 없는 태그 장치 | 무기한 액세스 |
| DEV-002 | 사용자 장치에 태그 지정 | 사용자 제거 후에도 지속 |
| DEV-010 | Tailnet Lock 비활성화 | 도난 키에 대한 보호 없음 |
| DEV-012 | 보류 중인 Tailnet Lock 서명 | 서명되지 않은 노드 검토 필요 |
| NET-001 | Funnel 노출 | 공개 인터넷 액세스 |
| NET-003 | 서브넷 라우터 신뢰 경계 | 로컬 네트워크에서 암호화되지 않은 트래픽 |
| SSH-002 | 확인 모드 없는 루트 SSH | 재인증 불필요 |
| ID | 검사 | 위험 |
|---|
| ACL-004 | autogroup:member 사용 | 외부 사용자 포함 |
| ACL-005 | AutoApprovers 구성 | 경로 승인 우회 |
| AUTH-004 | 임시가 아닌 CI/CD 키 | 오래된 장치 누적 |
| DEV-003 | 오래된 클라이언트 | 잠재적 취약점 |
| DEV-004 | 오래된 장치 | 사용되지 않는 공격 표면 |
| DEV-005 | 승인되지 않은 장치 | 보류 중인 승인 큐 |
| DEV-007 | 민감한 머신 이름 | CT 로그 노출 |
| DEV-009 | 장치 승인 구성 | 활성화되지 않을 수 있음 |
| NET-004 | HTTPS CT 로그 노출 | 머신 이름 공개 |
| NET-005 | 종료 노드 트래픽 가시성 | 운영자가 모든 트래픽을 봄 |
| NET-006 | Serve 노출 | tailnet의 로컬 서비스 |
| SSH-003 | Recorder UI 노출 | 세션이 네트워크에 표시됨 |