
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は2つの認証方法をサポートしています。両方が設定されている場合は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 | Webhookエンドポイント — 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は、テールネットのフェデレーテッドアイデンティティを読み取ります。これは管理コンソールではトラストクレデンシャルと呼ばれます。これらは認証キーと同じキーリストから取得されるため、auth_keys:readがそれらをカバーすることが期待されます。これはライブテールネットに対して確認されていません。キーリストを読み取れない場合、両方のチェックは合格ではなく「未評価」と報告します。スコープが不足している場合にエラーが返されるのか、それともアイデンティティがフィルタリングされたリストが返されるのかは未確認です。サイレントにフィルタリングされる場合、AUTH-005はトラストクレデンシャルが存在しないと報告し、AUTH-006はチェックするものが見つからないと報告します。
修正モード用の追加スコープ:
devices:core- デバイスの削除、タグの変更(タグ選択が必要)auth_keys- 認証キーの削除
Tailnet Lock
DEV-010とDEV-012はTailnet Lockについて報告します。これは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エビデンスエクスポート
Common Criteria(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など)
- 各コントロールテストの合格/不合格/該当なしステータス
- 監査証跡用のタイムスタンプ
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プランが必要
# チェック全体をミュートする代わりに、チェック内の1つの項目を無視
ACL-011:tag:monitoring # 設計上広範。他のすべてのタグは引き続きチェックされる
AUTH-001:tskey-auth-xxxx # CIで自動ローテーション、TICKET-123で追跡
行はチェック全体(ACL-011)またはその中の1つの項目(CHECK-ID:item、最初のコロンで分割 - 項目自体にコロンが含まれる場合があります)を指定します。項目ごとのルールはその項目のみを抑制します。チェックは引き続き実行され、見つけた他のすべてを報告します。フラグされたすべての項目を抑制しても、失敗したチェックが合格になることはありません - 検出結果は残り、情報提供に格下げされるため、抑制された検出結果が満たされたコントロールとして読まれることはありません。
無視ファイルの場所(順にチェックされます):
- カレントディレクトリの
.tailsnitch-ignore - ホームディレクトリの
~/.tailsnitch-ignore
最初の場所は作業ディレクトリであるため、無視ファイルはあなたではなくリポジトリから取得される可能性があります。実行ごとに使用したファイルと抑制した検出結果と項目の数が報告され、--jsonはこれをignore_fileおよびignoredフィールドに記録します(チェック全体の場合はCHECK-ID、抑制された1つの項目の場合は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へのパス(Tailnet Lockチェック用) |
--timeout | 監査の全体の時間予算(デフォルト 2m) |
--ignore-file | 無視ファイルへのパス |
--no-ignore | 無視ファイル処理を無効化 |
--version | バージョン情報を表示 |
セキュリティチェック
Tailsnitchは7つのカテゴリにわたって57のセキュリティチェックを実行します。各チェックの詳細なドキュメントについてはdocs/CHECKS.mdを参照してください。
重大な重大度
| ID | チェック | リスク |
|---|---|---|
| ACL-001 | デフォルトの「すべて許可」ポリシー | すべてのデバイスが無制限にアクセス可能 |
| ACL-002 | SSH autogroup:nonrootの設定ミス | 任意の非rootユーザーとしてSSH |
| ACL-006 | tagOwnersが広すぎる | タグによる権限昇格 |
| ACL-007 | autogroup:danger-allの使用 | 外部ユーザーへのアクセス付与 |
高重大度
| ID | チェック | リスク |
|---|---|---|
| ACL-011 | タグの到達範囲が信頼境界を越える | 盗まれた再利用可能キーがすべてに到達するタグを作成 |
| AUTH-001 | 再利用可能な認証キー | 盗まれた場合の無制限のデバイス追加 |
| AUTH-002 | 有効期限が長い認証キー | 露出ウィンドウの延長 |
| AUTH-003 | 事前承認されたキー | デバイス承認のバイパス |
| AUTH-006 | フェデレーテッドアイデンティティのサブジェクトが広すぎる | 発行者が保証する任意のプリンシパルがタグを作成可能 |
| DEV-001 | キー有効期限なしのタグ付きデバイス | 無期限のアクセス |
| DEV-002 | タグ付きユーザーデバイス | ユーザー削除後も永続 |
| DEV-010 | Tailnet Lock無効 | 盗まれたキーに対する保護なし |
| DEV-012 | 保留中のTailnet Lock署名 | 未署名ノードはレビューが必要 |
| NET-001 | Funnel露出 | パブリックインターネットアクセス |
| NET-003 | サブネットルーターの信頼境界 | ローカルネットワーク上の暗号化されていないトラフィック |
| SSH-002 | チェックモードなしのroot SSH | 再認証が不要 |
中程度の重大度
| ID | チェック | リスク |
|---|---|---|
| ACL-004 | autogroup:memberの使用 | 外部ユーザーが含まれる |
| ACL-005 | AutoApprovers設定 | ルート承認のバイパス |
| AUTH-004 | 非一時的なCI/CDキー | 古いデバイスが蓄積 |
| AUTH-005 | ワークロードアイデンティティフェデレーションが未使用 | 長期キーが盗難可能なまま |
| DEV-003 | 古いクライアント | 潜在的な脆弱性 |
| DEV-004 | 古いデバイス | 未使用の攻撃面 |
| DEV-005 | 未承認デバイス | 保留中の承認キュー |
| DEV-007 | 機密性の高いマシン名 | CTログ露出 |
| DEV-009 | デバイス承認設定 | 有効になっていない可能性がある |
| NET-004 | HTTPS CTログ露出 | マシン名が公開 |
| NET-005 | 終了ノードのトラフィック可視性 | オペレーターがすべてのトラフィックを閲覧可能 |
| NET-006 | Serve露出 | テールネット上のローカルサービス |
| SSH-003 | レコーダーUI露出 | セッションがネットワークに表示 |
情報提供
ロギング設定、DNS設定、ユーザーロール、手動検証項目のチェック。
検出結果に依存する重大度
いくつかのチェックは固定の重大度を持たず、見つけたものに基づいて評価します。ここで3つを挙げます:
- ACL-011は各タグの到達範囲を情報提供として報告します。認証キーが割り当てられるタグがワイルドカード宛先、ルーティングされたサブネット、または終了ノードの出力に到達した場合のみ失敗します: 再利用可能なキーがそのタグを割り当てる場合は高、ワンタイムキーのみの場合は中。デバイス数が重大度を設定することはありません。
- AUTH-005は、テールネットにトラストクレデンシャルがまったくない場合は中程度、トラストクレデンシャルが存在するが再利用可能なキーがそれらのいずれもカバーしないタグを作成する場合は低と報告します。
- AUTH-006は、ワイルドカードのみのサブジェクトに対して高、より狭いワイルドカードまたは欠落したオーディエンスに対して低と報告します。
出力例
+=====================================================================+
| 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
Tailnet Lockチェック
Tailnet Lockチェック(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を参照してください。