
tailsnitch v1.7
Tailscale 구성에 대한 보안 감사 도구입니다. 테일넷(tailnet)에서 잘못된 구성, 과도하게 허용적인 접근 제어, 보안 모범 사례 위반을 스캔합니다.
Tailsnitch
Tailscale 구성에 대한 보안 감사 도구입니다. Tailsnitch는 테일넷에서 57가지의 잘못된 구성, 과도하게 허용적인 접근 제어, 보안 모범 사례 위반을 스캔합니다.
빠른 시작
# 1. Tailscale API 자격 증명 설정
export TS_API_KEY="tskey-api-..."
# 2. 감사 실행
tailsnitch
# 3. 높은 심각도 결과만 보기
tailsnitch --severity high
# 4. 일부 문제 수정 ~대화형~ yolo 모드
tailsnitch --fix
설치
사전 빌드된 바이너리 다운로드
GitHub Releases에서 최신 릴리스를 다운로드하세요.
macOS 사용자: 다운로드 후 격리 속성을 제거하세요:
sudo xattr -rd com.apple.quarantine tailsnitch
Go로 설치
go install github.com/Adversis/tailsnitch@latest
소스에서 빌드
git clone https://github.com/Adversis/tailsnitch.git
cd tailsnitch
go build -o tailsnitch .
인증
Tailsnitch는 두 가지 인증 방법을 지원합니다. 둘 다 구성된 경우 OAuth가 선호됩니다.
옵션 1: 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-, NET-, SSH-* |
devices:core:read | 장치 목록 — DEV-, NET-, ACL-011 |
dns:read | DNS 구성 — DNS-001, DEV-007 |
auth_keys:read | 머신 인증 키 — AUTH-*, ACL-011 |
feature_settings:read | 테일넷 설정 — DEV-008, DEV-009, DEV-014 |
logs:network:read | 네트워크 흐름 로깅 설정 — LOG-001 |
networking_settings:read | HTTPS 인증서 설정 — NET-004 |
log_streaming:read | 로그 스트림 대상 — LOG-002 |
webhooks:read | 웹훅 엔드포인트 — LOG-005, LOG-012 |
oauth_keys:read | OAuth 클라이언트 — LOG-006 |
users:read | 사용자 역할 및 상태 — USER-001, LOG-006 |
account_settings:read | 보안 연락처 — LOG-011 |
devices:posture_attributes:read | 포스처 통합 — DEV-014 |
생략한 범위는 해당 범위가 필요한 검사에만 영향을 미칩니다. 해당 검사는 통과로 보고하는 대신 설정을 읽을 수 없다고 보고합니다.
AUTH-005 및 AUTH-006은 관리 콘솔에서 신뢰 자격 증명이라고 부르는 테일넷의 페더레이션 ID를 읽습니다. 이들은 인증 키와 동일한 키 목록에서 가져오므로 auth_keys:read가 이를 포함할 것으로 예상됩니다. 이는 실제 테일넷에서 확인되지 않았습니다. 키 목록을 읽을 수 없으면 두 검사 모두 통과 대신 평가되지 않음으로 보고합니다. 누락된 범위가 오류를 반환하는지 아니면 ID가 필터링된 목록을 반환하는지는 확인되지 않았습니다. 조용히 필터링하는 경우 AUTH-005는 신뢰 자격 증명이 없다고 보고하고 AUTH-006은 확인할 항목을 찾지 못합니다.
수정 모드에 필요한 추가 범위:
devices:core- 장치 삭제, 태그 수정 (태그 선택 필요)auth_keys- 인증 키 삭제
테일넷 잠금
DEV-010 및 DEV-012는 Tailscale API가 테일넷 설정으로 노출하지 않는 테일넷 잠금에 대해 보고합니다. 잠금으로 잠긴 장치는 API를 통해 볼 수 있지만, 잠금이 활성화되었는지 확인하려면 tailsnitch를 실행하는 머신의 데몬을 읽는 로컬 tailscale CLI가 필요합니다. --tailnet으로 다른 테일넷을 감사할 때는 결과의 해당 부분을 그에 따라 처리하세요. 바이너리가 비표준 위치에 있는 경우 --tailscale-path를 사용하세요.
옵션 2: API 키
API 키는 생성한 사용자로 작동하며 해당 사용자의 권한을 상속합니다.
export TS_API_KEY="tskey-api-..."
API 키 생성: https://login.tailscale.com/admin/settings/keys
사용 예시
기본 감사
# 전체 감사 실행
tailsnitch
# 통과 검사도 표시 (자세히)
tailsnitch --verbose
# 처리를 위해 JSON으로 출력
tailsnitch --json
# 특정 테일넷 감사 (OAuth 클라이언트가 여러 테일넷에 액세스할 수 있는 경우)
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 | 인증 키 삭제 |
| DEV-002 | 사용자 장치에서 태그 제거 |
| DEV-004 | 오래된 장치 삭제 |
| DEV-005 | 대기 중인 장치 승인 |
수정 모드는 수동 개입이 필요한 문제에 대해 관리 콘솔로의 직접 링크도 제공합니다.
SOC 2 증거 내보내기
공통 기준(CC) 제어 매핑과 함께 SOC 2 감사용 증거 보고서 생성:
# JSON으로 내보내기
tailsnitch --soc2 json > soc2-evidence.json
# CSV로 내보내기 (스프레드시트용)
tailsnitch --soc2 csv > soc2-evidence.csv
SOC 2 보고서에는 다음이 포함됩니다:
- 리소스별 테스트 결과 (각 장치, 키, ACL 규칙이 개별적으로 테스트됨)
- CC 코드 매핑 (CC6.1, CC6.2, CC6.3, CC6.6, CC7.1, CC7.2 등)
- 각 제어 테스트의 통과/실패/N/A 상태
- 감사 추적용 타임스탬프
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 플랜 필요
# 전체 검사를 음소거하는 대신 검사 내 하나의 항목만 무시
ACL-011:tag:monitoring # 설계상 광범위함; 다른 모든 태그는 여전히 검사됨
AUTH-001:tskey-auth-xxxx # CI를 통해 자동으로 순환됨, TICKET-123에서 추적됨
한 줄은 전체 검사(ACL-011) 또는 그 안의 한 항목(CHECK-ID:item, 첫 번째 콜론에서 분할 - 항목 자체에 콜론이 포함될 수 있음)을 지정합니다. 항목별 규칙은 해당 항목만 억제합니다. 검사는 계속 실행되고 찾은 다른 모든 것을 계속 보고합니다. 플래그된 모든 항목을 억제해도 실패한 검사가 통과로 바뀌지 않습니다. 결과는 유지되며 정보 제공 수준으로 강등되므로 억제된 결과가 충족된 제어로 읽히지 않습니다.
무시 파일 위치 (순서대로 확인):
- 현재 디렉토리의
.tailsnitch-ignore - 홈 디렉토리의
~/.tailsnitch-ignore
첫 번째 위치가 작업 디렉토리이므로 무시 파일은 사용자가 아닌 저장소에서 올 수 있습니다. 모든 실행은 어떤 파일을 사용했는지와 억제된 결과 및 항목 수를 보고하며, --json은 이를 ignore_file 및 ignored 필드에 기록합니다 (CHECK-ID는 전체 검사, CHECK-ID:item은 억제된 항목 하나). 파일을 건너뛰려면 --no-ignore를 사용하세요.
# 특정 무시 파일 사용
tailsnitch --ignore-file /path/to/ignore
# 무시 파일 처리를 완전히 비활성화
tailsnitch --no-ignore
JSON 내보내기 및 처리
# 전체 보고서 내보내기
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"
'
명령 참조
| 플래그 | 설명 |
|---|---|
--json | JSON으로 출력 |
--severity | 최소 심각도로 필터링: critical, high, medium, low, info |
--category | 카테고리로 필터링: access, auth, network, ssh, log, device, dns |
--checks | 특정 검사 실행 (쉼표로 구분된 ID 또는 슬러그) |
--list-checks | 사용 가능한 모든 검사 나열 후 종료 |
--tailnet | 감사할 테일넷 지정 (기본값: API 키에서) |
--verbose | 통과 검사도 표시 |
--fix | 대화형 수정 모드 활성화 |
--auto | 안전한 수정 자동 선택 (--fix 필요) |
--dry-run | 실행 없이 수정 작업 미리보기 (--fix 필요) |
--no-audit-log | 수정 작업의 감사 로깅 비활성화 |
--soc2 | SOC 2 증거 내보내기: json 또는 csv |
--tailscale-path | tailscale CLI 경로 (테일넷 잠금 검사용) |
--timeout | 감사 전체 시간 예산 (기본값 2m) |
--ignore-file | 무시 파일 경로 |
--no-ignore | 무시 파일 처리 비활성화 |
--version | 버전 정보 표시 |
보안 검사
Tailsnitch는 7개 카테고리에 걸쳐 57개의 보안 검사를 수행합니다. 각 검사에 대한 자세한 문서는 docs/CHECKS.md를 참조하세요.
중요 심각도
| ID | 검사 | 위험 |
|---|---|---|
| ACL-001 | 기본 '모두 허용' 정책 | 모든 장치에 무제한 액세스 |
| ACL-002 | SSH autogroup:nonroot 잘못된 구성 | 모든 비루트 사용자로 SSH |
| ACL-006 | tagOwners가 너무 광범위함 | 태그를 통한 권한 상승 |
| ACL-007 | autogroup:danger-all 사용 | 외부 사용자에게 액세스 부여 |
높은 심각도
| ID | 검사 | 위험 |
|---|---|---|
| ACL-011 | 태그 도달이 신뢰 경계를 넘음 | 도난된 재사용 키가 모든 것에 도달하는 태그를 생성 |
| AUTH-001 | 재사용 가능한 인증 키 | 도난 시 무제한 장치 추가 |
| AUTH-002 | 긴 만료 인증 키 | 확장된 노출 기간 |
| AUTH-003 | 사전 승인된 키 | 장치 승인 우회 |
| AUTH-006 | 페더레이션 ID 주체가 너무 광범위함 | 발급자가 보증하는 모든 주체가 태그를 생성할 수 있음 |
| DEV-001 | 키 만료 없는 태그된 장치 | 무기한 액세스 |
| DEV-002 | 태그된 사용자 장치 | 사용자 제거 후에도 유지 |
| DEV-010 | 테일넷 잠금 비활성화 | 도난 키에 대한 보호 없음 |
| DEV-012 | 대기 중인 테일넷 잠금 서명 | 서명되지 않은 노드는 검토 필요 |
| NET-001 | Funnel 노출 | 공개 인터넷 액세스 |
| NET-003 | 서브넷 라우터 신뢰 경계 | 로컬 네트워크의 암호화되지 않은 트래픽 |
| SSH-002 | 확인 모드 없는 루트 SSH | 재인증 불필요 |
중간 심각도
| ID | 검사 | 위험 |
|---|---|---|
| ACL-004 | autogroup:member 사용 | 외부 사용자 포함 |
| ACL-005 | AutoApprovers 구성 | 경로 승인 우회 |
| AUTH-004 | 비일시적 CI/CD 키 | 오래된 장치 축적 |
| AUTH-005 | 워크로드 ID 페더레이션 미사용 | 장기 키가 계속 도난 가능 |
| DEV-003 | 오래된 클라이언트 | 잠재적 취약점 |
| DEV-004 | 오래된 장치 | 사용되지 않는 공격 표면 |
| DEV-005 | 승인되지 않은 장치 | 대기 승인 큐 |
| DEV-007 | 민감한 머신 이름 | CT 로그 노출 |
| DEV-009 | 장치 승인 구성 | 활성화되지 않을 수 있음 |
| NET-004 | HTTPS CT 로그 노출 | 머신 이름 공개 |
| NET-005 | 종료 노드 트래픽 가시성 | 운영자가 모든 트래픽을 볼 수 있음 |
| NET-006 | Serve 노출 | 테일넷의 로컬 서비스 |
| SSH-003 | 레코더 UI 노출 | 세션이 네트워크에 표시됨 |
정보 제공
로깅 구성, DNS 설정, 사용자 역할 및 수동 확인 항목에 대한 검사.
결과에 따라 달라지는 심각도
여러 검사는 고정된 심각도를 가지지 않고 찾은 내용을 평가합니다. 여기서 세 가지를 언급할 가치가 있습니다:
- ACL-011은 모든 태그의 도달 범위를 정보 제공 수준으로 보고합니다. 인증 키가 할당할 수 있는 태그가 와일드카드 대상, 라우팅된 서브넷 또는 종료 노드 이그레스에 도달할 때만 실패합니다: 재사용 키가 해당 태그를 할당하면 높음, 일회용 키만 할당하면 중간. 장치 수는 심각도를 설정하지 않습니다.
- AUTH-005은 테일넷에 신뢰 자격 증명이 전혀 없으면 중간으로 보고하고, 신뢰 자격 증명이 존재하지만 재사용 키가 여전히 그 중 어느 것도 포함하지 않는 태그를 생성하면 낮음으로 보고합니다.
- AUTH-006은 와일드카드뿐인 주체에 대해 높음으로 보고하고, 더 좁은 와일드카드 또는 누락된 대상(audience)에 대해 낮음으로 보고합니다.
출력 예시
+=====================================================================+
| 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/docs/reference/examples/acls
----------------------------------------------------------------------
=== 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/docs/features/access-control/auth-keys
----------------------------------------------------------------------
SUMMARY
======================================================================
Critical: 1 High: 3 Medium: 5 Low: 2 Info: 8
Total findings: 19 | Passed: 33
테일넷 잠금 검사
테일넷 잠금 검사(DEV-010, DEV-012)는 로컬 tailscale CLI가 필요하며 로컬 머신의 데몬에 대해 실행됩니다. --tailnet으로 원격 테일넷을 감사할 때 이러한 검사는 감사 대상 테일넷이 아닌 로컬 상태를 반영합니다.
# 필요한 경우 사용자 지정 tailscale 바이너리 경로 지정
tailsnitch --tailscale-path /opt/tailscale/bin/tailscale
CI/CD 통합
CI/CD 파이프라인에서 Tailsnitch를 실행하여 보안 회귀를 감지하세요:
# GitHub Actions 예시
- name: Audit Tailscale Security
env:
TS_OAUTH_CLIENT_ID: ${{ secrets.TS_OAUTH_CLIENT_ID }}
TS_OAUTH_CLIENT_SECRET: ${{ secrets.TS_OAUTH_CLIENT_SECRET }}
run: |
tailsnitch --json > audit.json
# Fail if critical or high severity issues exist
if tailsnitch --severity high --json | jq -e '.summary.critical + .summary.high > 0' > /dev/null; then
echo "Critical or high severity issues found!"
tailsnitch --severity high
exit 1
fi
참고 자료
라이선스
MIT
기여
지침은 CONTRIBUTING.md를 참조하세요.