
tailsnitch v1.7
Ein Sicherheitsprüfer für Tailscale-Konfigurationen. Durchsucht Ihr Tailnet nach Fehlkonfigurationen, zu permissiven Zugriffskontrollen und Verstößen gegen Sicherheitsbest Practices.
Tailsnitch
Ein Sicherheitsauditor für Tailscale-Konfigurationen. Tailsnitch scannt dein Tailnet auf 57 Fehlkonfigurationen, übermäßig permissive Zugriffskontrollen und Verstöße gegen Sicherheits-Best Practices.
Schnellstart
# 1. Setze deine Tailscale-API-Anmeldedaten
export TS_API_KEY="tskey-api-..."
# 2. Audit ausführen
tailsnitch
# 3. Nur Ergebnisse mit hoher Schwere anzeigen
tailsnitch --severity high
# 4. Einige Probleme beheben ~interaktiv~ yolo-Modus
tailsnitch --fix
Installation
Vorkompiliertes Binary herunterladen
Lade die neueste Version von GitHub Releases herunter.
macOS-Benutzer: Entferne nach dem Download das Quarantäne-Attribut:
sudo xattr -rd com.apple.quarantine tailsnitch
Installation über Go
go install github.com/Adversis/tailsnitch@latest
Aus dem Quellcode erstellen
git clone https://github.com/Adversis/tailsnitch.git
cd tailsnitch
go build -o tailsnitch .
Authentifizierung
Tailsnitch unterstützt zwei Authentifizierungsmethoden. OAuth wird bevorzugt, wenn beide konfiguriert sind.
Option 1: OAuth-Client (Empfohlen)
OAuth-Clients bieten abgegrenzten, auditierbaren Zugriff, der nicht abläuft, wenn Mitarbeiter das Unternehmen verlassen.
export TS_OAUTH_CLIENT_ID="..."
export TS_OAUTH_CLIENT_SECRET="tskey-client-..."
Erstelle einen OAuth-Client unter: https://login.tailscale.com/admin/settings/oauth
Erforderliche Bereiche für schreibgeschütztes Audit:
all:read deckt alles ab. Einzelne Bereiche vergeben:
| Bereich | Verwendet für |
|---|---|
policy_file:read | Tailnet-Policy-Datei — ACL-, NET-, SSH-* |
devices:core:read | Geräteliste — DEV-, NET-, ACL-011 |
dns:read | DNS-Konfiguration — DNS-001, DEV-007 |
auth_keys:read | Maschinen-Auth-Keys — AUTH-*, ACL-011 |
feature_settings:read | Tailnet-Einstellungen — DEV-008, DEV-009, DEV-014 |
logs:network:read | Netzwerk-Flow-Logging-Einstellung — LOG-001 |
networking_settings:read | HTTPS-Zertifikatseinstellung — NET-004 |
log_streaming:read | Log-Stream-Ziele — LOG-002 |
webhooks:read | Webhook-Endpunkte — LOG-005, LOG-012 |
oauth_keys:read | OAuth-Clients — LOG-006 |
users:read | Benutzerrollen und -status — USER-001, LOG-006 |
account_settings:read | Sicherheitskontakt — LOG-011 |
devices:posture_attributes:read | Posture-Integrationen — DEV-014 |
Jeder Bereich, den du weglässt, betrifft nur die Prüfungen, die ihn benötigen: Diese Prüfungen melden, dass sie die Einstellung nicht lesen konnten, anstatt sie zu bestehen.
AUTH-005 und AUTH-006 lesen die föderierten Identitäten des Tailnets, die die Admin-
Konsole als Vertrauensnachweise bezeichnet. Sie stammen aus derselben Key-Liste wie
Auth-Keys, daher wird erwartet, dass auth_keys:read sie abdeckt. Das wurde nicht
gegen ein Live-Tailnet bestätigt. Wenn die Key-Liste nicht gelesen werden kann, melden
beide Prüfungen „nicht ausgewertet", anstatt zu bestehen. Ob ein fehlender Bereich einen
Fehler zurückgibt oder stattdessen die Liste mit herausgefilterten Identitäten zurückgibt,
ist unbestätigt; wenn er stillschweigend filtert, würde AUTH-005 melden, dass keine
Vertrauensnachweise existieren, und AUTH-006 hätte nichts zu prüfen.
Zusätzliche Bereiche für den Fix-Modus:
devices:core- Geräte löschen, Tags ändern (erfordert Tag-Auswahl)auth_keys- Auth-Keys löschen
Tailnet Lock
DEV-010 und DEV-012 berichten über Tailnet Lock, das die Tailscale-API nicht
als Tailnet-Einstellung bereitstellt. Geräte, die dadurch gesperrt sind, sind über die
API sichtbar, aber die Feststellung, ob Lock aktiviert ist, erfordert die lokale tailscale-CLI,
die den Daemon auf dem Rechner liest, auf dem tailsnitch läuft. Wenn du ein anderes
Tailnet mit --tailnet auditierst, behandle diesen Teil des Ergebnisses entsprechend. Verwende
--tailscale-path, wenn sich das Binary an einem nicht standardmäßigen Ort befindet.
Option 2: API-Key
API-Keys agieren als der Benutzer, der sie erstellt hat, und erben dessen Berechtigungen.
export TS_API_KEY="tskey-api-..."
Erstelle einen API-Key unter: https://login.tailscale.com/admin/settings/keys
Verwendungsbeispiele
Basis-Audit
# Vollständiges Audit ausführen
tailsnitch
# Auch bestandene Prüfungen anzeigen (ausführlich)
tailsnitch --verbose
# Ausgabe als JSON zur Verarbeitung
tailsnitch --json
# Bestimmtes Tailnet auditieren (wenn der OAuth-Client Zugriff auf mehrere hat)
tailsnitch --tailnet mycompany.com
Ergebnisse filtern
# Nur kritische und hohe Schweregrade anzeigen
tailsnitch --severity high
# Nach Kategorie filtern
tailsnitch --category access # ACL-Probleme
tailsnitch --category auth # Authentifizierung & Keys
tailsnitch --category device # Gerätesicherheit
tailsnitch --category network # Netzwerkexposition
tailsnitch --category ssh # SSH-Regeln
tailsnitch --category log # Logging & Admin
# Nur bestimmte Prüfungen ausführen
tailsnitch --checks ACL-001,AUTH-001,DEV-010
tailsnitch --checks stale-devices,tailnet-lock-not-enabled
# Alle verfügbaren Prüfungen auflisten
tailsnitch --list-checks
Interaktiver Fix-Modus
Der Fix-Modus ermöglicht es dir, Probleme direkt über die Tailscale-API zu beheben:
# Interaktiver Fix-Modus
tailsnitch --fix
# Vorschau, was behoben würde (Probelauf)
tailsnitch --fix --dry-run
# Sichere Fixes automatisch auswählen (erfordert weiterhin Bestätigung)
tailsnitch --fix --auto
# Audit-Logging von Fix-Aktionen deaktivieren
tailsnitch --fix --no-audit-log
Per API behebbare Elemente:
| Prüfung | Aktion |
|---|---|
| AUTH-001, AUTH-002, AUTH-003 | Auth-Keys löschen |
| DEV-002 | Tags von Benutzergeräten entfernen |
| DEV-004 | Veraltete Geräte löschen |
| DEV-005 | Ausstehende Geräte autorisieren |
Der Fix-Modus bietet außerdem direkte Links zur Admin-Konsole für Probleme, die manuelles Eingreifen erfordern.
SOC-2-Nachweisexport
Erzeuge Nachweisberichte für SOC-2-Audits mit Common-Criteria-Controls-Zuordnungen (CC):
# Als JSON exportieren
tailsnitch --soc2 json > soc2-evidence.json
# Als CSV exportieren (für Tabellenkalkulationen)
tailsnitch --soc2 csv > soc2-evidence.csv
Der SOC-2-Bericht enthält:
- Testergebnisse pro Ressource (jedes Gerät, jeder Key, jede ACL-Regel einzeln getestet)
- CC-Code-Zuordnungen (CC6.1, CC6.2, CC6.3, CC6.6, CC7.1, CC7.2, usw.)
- Bestanden/Fehlgeschlagen/N/A-Status für jeden Control-Test
- Zeitstempel für den Audit-Trail
Beispiel-CSV-Ausgabe:
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
Bekannte Risiken ignorieren
Erstelle eine .tailsnitch-ignore-Datei, um Befunde für bekannte, akzeptierte Risiken zu unterdrücken:
# .tailsnitch-ignore
# Informationelle Prüfungen ignorieren
ACL-008 # Wir verwenden absichtlich keine Gruppen
ACL-009 # Legacy-ACLs sind für unseren Anwendungsfall in Ordnung
# Bestimmte mittlere Prüfungen mit Begründung ignorieren
DEV-006 # Externe Geräte sind genehmigte Auftragnehmer
LOG-001 # Flow-Logs erfordern den Enterprise-Plan
# Ein Element innerhalb einer Prüfung ignorieren, statt die gesamte Prüfung stummzuschalten
ACL-011:tag:monitoring # bewusst breit ausgelegt; jedes andere Tag wird weiterhin geprüft
AUTH-001:tskey-auth-xxxx # rotiert automatisch über CI, verfolgt in TICKET-123
Eine Zeile benennt entweder eine gesamte Prüfung (ACL-011) oder ein einzelnes Element darin
(CHECK-ID:item, geteilt am ersten Doppelpunkt – das Element selbst kann Doppelpunkte
enthalten). Eine Regel pro Element unterdrückt nur dieses Element: Die Prüfung läuft weiterhin und
meldet weiterhin alles andere, was sie findet. Das Unterdrücken jedes markierten Elements verwandelt
eine fehlgeschlagene Prüfung nie in eine bestandene – der Befund bleibt bestehen, herabgestuft auf
Informationell, sodass ein unterdrückter Befund nie wie ein erfüllter Control wirkt.
Speicherorte der Ignore-Datei (in dieser Reihenfolge geprüft):
.tailsnitch-ignoreim aktuellen Verzeichnis~/.tailsnitch-ignoreim Home-Verzeichnis
Da der erste Speicherort das Arbeitsverzeichnis ist, kann eine Ignore-Datei aus einem
Repository stammen und nicht von dir. Jeder Lauf meldet, welche Datei verwendet wurde
und wie viele Befunde und Elemente unterdrückt wurden, und --json zeichnet dies in den
Feldern ignore_file und ignored auf (CHECK-ID für eine gesamte Prüfung,
CHECK-ID:item für ein unterdrücktes Element). Verwende --no-ignore, um die Datei zu überspringen.
# Eine bestimmte Ignore-Datei verwenden
tailsnitch --ignore-file /pfad/zur/ignore
# Die Verarbeitung der Ignore-Datei vollständig deaktivieren
tailsnitch --no-ignore
JSON-Export und -Verarbeitung
# Vollständigen Bericht exportieren
tailsnitch --json > audit.json
# Fehlgeschlagene Prüfungen als TSV extrahieren
tailsnitch --json | jq -r '
.suggestions
| map(select(.pass == false))
| .[]
| [.id, .title, .severity, .remediation]
| @tsv
' > findings.tsv
# Zusammenfassung nach Schweregrad
tailsnitch --json | jq '
.suggestions
| map(select(.pass == false))
| group_by(.severity)
| map({severity: .[0].severity, count: length})
'
# Kritische/hohe Probleme mit Admin-Links auflisten
tailsnitch --json | jq -r '
.suggestions
| map(select(.pass == false and (.severity == "CRITICAL" or .severity == "HIGH")))
| .[]
| "\(.id): \(.title)\n Fix: \(.fix.admin_url // "manual")\n"
'
Befehlsreferenz
| Flag | Beschreibung |
|---|---|
--json | Ausgabe als JSON |
--severity | Nach Mindestschweregrad filtern: critical, high, medium, low, info |
--category | Nach Kategorie filtern: access, auth, network, ssh, log, device, dns |
--checks | Bestimmte Prüfungen ausführen (kommagetrennte IDs oder Slugs) |
--list-checks | Alle verfügbaren Prüfungen auflisten und beenden |
--tailnet | Zu auditierendes Tailnet angeben (Standard: aus API-Key) |
--verbose | Auch bestandene Prüfungen anzeigen |
--fix | Interaktiven Fix-Modus aktivieren |
--auto | Sichere Fixes automatisch auswählen (erfordert --fix) |
--dry-run | Fix-Aktionen ohne Ausführung in der Vorschau anzeigen (erfordert --fix) |
--no-audit-log | Audit-Logging von Fix-Aktionen deaktivieren |
--soc2 | SOC-2-Nachweise exportieren: json oder csv |
--tailscale-path | Pfad zur tailscale-CLI (für Tailnet-Lock-Prüfungen) |
--timeout | Gesamtes Zeitbudget für das Audit (Standard 2m) |
--ignore-file | Pfad zur Ignore-Datei |
--no-ignore | Verarbeitung der Ignore-Datei deaktivieren |
--version | Versionsinformationen anzeigen |
Sicherheitsprüfungen
Tailsnitch führt 57 Sicherheitsprüfungen in 7 Kategorien durch. Siehe docs/CHECKS.md für die detaillierte Dokumentation jeder Prüfung.
Kritischer Schweregrad
| ID | Prüfung | Risiko |
|---|---|---|
| ACL-001 | Standardrichtlinie „Alle zulassen" | Alle Geräte haben uneingeschränkten Zugriff |
| ACL-002 | SSH-autogroup:nonroot-Fehlkonfiguration | SSH als beliebiger Nicht-Root-Benutzer |
| ACL-006 | tagOwners zu breit gefasst | Privilegieneskalation über Tags |
| ACL-007 | autogroup:danger-all-Verwendung | Zugriff für externe Benutzer gewährt |
Hoher Schweregrad
| ID | Prüfung | Risiko |
|---|---|---|
| ACL-011 | Tag-Reichweite überschreitet eine Vertrauensgrenze | Ein gestohlener wiederverwendbarer Key prägt ein Tag, das alles erreicht |
| AUTH-001 | Wiederverwendbare Auth-Keys | Unbegrenzte Gerätehinzufügungen bei Diebstahl |
| AUTH-002 | Auth-Keys mit langer Gültigkeit | Erweitertes Expositionsfenster |
| AUTH-003 | Vorautorisierte Keys | Umgehung der Gerätefreigabe |
| AUTH-006 | Föderiertes Identitätssubjekt zu breit gefasst | Jedes vom Aussteller verbürgte Principal kann das Tag prägen |
| DEV-001 | Getaggte Geräte ohne Key-Ablauf | Unbegrenzter Zugriff |
| DEV-002 | Benutzergeräte getaggt | Bleiben nach Entfernung des Benutzers bestehen |
| DEV-010 | Tailnet Lock deaktiviert | Kein Schutz vor gestohlenen Keys |
| DEV-012 | Ausstehende Tailnet-Lock-Signaturen | Unsigierte Knoten benötigen Überprüfung |
| NET-001 | Funnel-Exposition | Öffentlicher Internetzugriff |
| NET-003 | Subnetz-Router-Vertrauensgrenze | Unverschlüsselter Datenverkehr im lokalen Netzwerk |
| SSH-002 | Root-SSH ohne Check-Modus | Keine erneute Authentifizierung erforderlich |
Mittlerer Schweregrad
| ID | Prüfung | Risiko |
|---|---|---|
| ACL-004 | autogroup:member-Verwendung | Externe Benutzer eingeschlossen |
| ACL-005 | AutoApprovers konfiguriert | Umgehung der Routenfreigabe |
| AUTH-004 | Nicht-ephemere CI/CD-Keys | Veraltete Geräte sammeln sich an |
| AUTH-005 | Workload-Identitätsföderation nicht verwendet | Langlebige Keys bleiben stehlbar |
| DEV-003 | Veraltete Clients | Potenzielle Schwachstellen |
| DEV-004 | Veraltete Geräte | Ungenutzte Angriffsfläche |
| DEV-005 | Nicht autorisierte Geräte | Warteschlange ausstehender Freigaben |
| DEV-007 | Sensible Maschinennamen | CT-Log-Exposition |
| DEV-009 | Gerätefreigabe-Konfiguration | Möglicherweise nicht aktiviert |
| NET-004 | HTTPS-CT-Log-Exposition | Maschinennamen öffentlich |
| NET-005 | Sichtbarkeit des Exit-Node-Datenverkehrs | Betreiber sieht gesamten Datenverkehr |
| NET-006 | Serve-Exposition | Lokale Dienste im Tailnet |
| SSH-003 | Recorder-UI-Exposition | Sitzungen im Netzwerk sichtbar |
Informationell
Prüfungen für Logging-Konfiguration, DNS-Einstellungen, Benutzerrollen und manuelle Verifizierungselemente.
Schweregrad, der vom Befund abhängt
Mehrere Prüfungen bewerten, was sie finden, anstatt einen festen Schweregrad zu tragen. Drei sind hier besonders erwähnenswert:
- ACL-011 meldet die Reichweite jedes Tags als Informationell. Sie schlägt nur fehl, wenn ein Tag, das ein Auth-Key zuweisen kann, ein Wildcard-Ziel, ein geroutetes Subnetz oder Exit-Node-Egress erreicht: Hoch, wenn ein wiederverwendbarer Key dieses Tag zuweist, Mittel, wenn nur ein Einmal-Key dies tut. Eine Geräteanzahl setzt nie den Schweregrad.
- AUTH-005 meldet Mittel, wenn das Tailnet überhaupt keine Vertrauensnachweise hat, und Niedrig, wenn Vertrauensnachweise existieren, aber ein wiederverwendbarer Key weiterhin Tags prägt, die keiner von ihnen abdeckt.
- AUTH-006 meldet Hoch für ein Subjekt, das nichts als ein Wildcard ist, und Niedrig für ein engeres Wildcard oder eine fehlende Audience.
Ausgabebeispiel
+=====================================================================+
| TAILSNITCH SECURITY AUDIT |
| Tailnet: example.com |
| Version: 1.0.0 (build: abc123) |
+=====================================================================+
Verwende Ignore-Datei: .tailsnitch-ignore (3 Regeln)
=== ZUGRIFFSKONTROLLEN ===================================================
[KRITISCH] ACL-001: Standardrichtlinie „Alle zulassen" aktiv
Deine ACL-Policy lässt das Feld 'acls' aus. Tailscale wendet eine
Standardrichtlinie „Alle zulassen" an, die allen Geräten vollen Zugriff gewährt.
Abhilfe:
Definiere explizite ACL-Regeln nach dem Prinzip der geringsten Privilegien.
Quelle: https://tailscale.com/docs/reference/examples/acls
----------------------------------------------------------------------
=== AUTHENTIFIZIERUNG & KEYS =============================================
[HOCH] AUTH-001: Wiederverwendbare Auth-Keys vorhanden
2 wiederverwendbare Auth-Key(s) gefunden. Diese können bei Kompromittierung
wiederverwendet werden, um mehrere Geräte hinzuzufügen.
Details:
- Key tskey-auth-xxx (läuft in 45 Tagen ab)
- Key tskey-auth-yyy (läuft in 89 Tagen ab)
Abhilfe:
Speichere wiederverwendbare Keys in einem Secrets-Manager. Bevorzuge Einmal-Keys.
Quelle: https://tailscale.com/docs/features/access-control/auth-keys
----------------------------------------------------------------------
ZUSAMMENFASSUNG
======================================================================
Kritisch: 1 Hoch: 3 Mittel: 5 Niedrig: 2 Info: 8
Gesamte Befunde: 19 | Bestanden: 33
Tailnet-Lock-Prüfungen
Tailnet-Lock-Prüfungen (DEV-010, DEV-012) erfordern die lokale tailscale-CLI und laufen gegen den Daemon des lokalen Rechners. Wenn du ein entferntes Tailnet über --tailnet auditierst, spiegeln diese Prüfungen den lokalen Status wider, nicht das auditierte Tailnet.
# Bei Bedarf benutzerdefinierten tailscale-Binary-Pfad angeben
tailsnitch --tailscale-path /opt/tailscale/bin/tailscale
CI/CD-Integration
Führe Tailsnitch in CI/CD-Pipelines aus, um Sicherheitsregressionen zu erkennen:
# GitHub-Actions-Beispiel
- name: Tailscale-Sicherheit auditieren
env:
TS_OAUTH_CLIENT_ID: ${{ secrets.TS_OAUTH_CLIENT_ID }}
TS_OAUTH_CLIENT_SECRET: ${{ secrets.TS_OAUTH_CLIENT_SECRET }}
run: |
tailsnitch --json > audit.json
# Fehlschlagen, wenn kritische oder hohe Probleme existieren
if tailsnitch --severity high --json | jq -e '.summary.critical + .summary.high > 0' > /dev/null; then
echo "Kritische oder hohe Probleme gefunden!"
tailsnitch --severity high
exit 1
fi
Referenzen
Lizenz
MIT
Mitwirken
Siehe CONTRIBUTING.md für Richtlinien.