
Инструмент аудита безопасности для конфигураций Tailscale. Сканирует ваш tailnet на наличие неправильных конфигураций, излишне разрешительных политик доступа и нарушений лучших практик безопасности.
Аудитор безопасности конфигураций Tailscale. Tailsnitch сканирует вашу tailnet-сеть на наличие 57 ошибок конфигурации, излишне разрешающих контролей доступа и нарушений лучших практик безопасности.
# 1. Укажите свои учётные данные API Tailscale
export TS_API_KEY="tskey-api-..."
# 2. Запустите аудит
tailsnitch
# 3. Покажите только находки высокой степени серьёзности
tailsnitch --severity high
# 4. Исправьте некоторые проблемы ~интерактивно~ режим yolo
tailsnitch --fix
Загрузите последний релиз из GitHub Releases.
Пользователям macOS: Снимите атрибут quarantine после загрузки:
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 | Файл политики tailnet — 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 | Настройки tailnet — 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 | Интеграции posture — DEV-014 |
Любая область, которую вы пропустите, влияет только на проверки, которым она нужна: такие проверки сообщают, что не смогли прочитать настройку, а не проходят успешно.
AUTH-005 и AUTH-006 читают федеративные удостоверения tailnet, которые консоль администратора называет доверенными учётными данными. Они поступают из того же списка ключей, что и ключи аутентификации, поэтому ожидается, что auth_keys:read их покрывает. Это не было подтверждено на живой tailnet-сети. Если список ключей не может быть прочитан, обе проверки сообщают «не оценено», а не «пройдено». Подтверждено ли, что отсутствующая область возвращает ошибку или вместо этого возвращает список с отфильтрованными удостоверениями, не установлено; если она фильтрует молча, AUTH-005 сообщит, что доверенных учётных данных не существует, а AUTH-006 не найдёт, что проверять.
Дополнительные области для режима исправления:
devices:core — Удаление устройств, изменение тегов (требуется выбор тега)auth_keys — Удаление ключей аутентификацииDEV-010 и DEV-012 сообщают о Tailnet Lock, который API Tailscale не раскрывает как настройку tailnet. Устройства, заблокированные им, видны через API, но определение того, включён ли lock, требует локального CLI tailscale, который читает демон на машине, где запущен tailsnitch. При аудите другой tailnet-сети с помощью --tailnet учитывайте эту часть результата соответствующим образом. Используйте --tailscale-path, если бинарный файл находится в нестандартном месте.
API-ключи действуют от имени пользователя, который их создал, и наследуют права этого пользователя.
export TS_API_KEY="tskey-api-..."
Создайте API-ключ по адресу: https://login.tailscale.com/admin/settings/keys
# Запуск полного аудита
tailsnitch
# Показ также проходящих проверок (подробный режим)
tailsnitch --verbose
# Вывод в формате JSON для обработки
tailsnitch --json
# Аудит конкретной tailnet-сети (когда 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
Режим исправления позволяет устранять проблемы напрямую через API Tailscale:
# Интерактивный режим исправления
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):
# Экспорт в 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
# Игнорирование одного элемента в проверке вместо отключения всей проверки
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
# Экспорт полного отчёта
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 | Указание tailnet-сети для аудита (по умолчанию: из API-ключа) |
--verbose | Показ также проходящих проверок |
--fix | Включение интерактивного режима исправления |
--auto | Автовыбор безопасных исправлений (требует --fix) |
--dry-run | Предпросмотр действий по исправлению без выполнения (требует --fix) |
--no-audit-log | Отключение журналирования аудита действий по исправлению |
--soc2 | Экспорт доказательств SOC 2: json или csv |
--tailscale-path | Путь к CLI tailscale (для проверок Tailnet Lock) |
--timeout | Общий бюджет времени на аудит (по умолчанию 2m) |
--ignore-file | Путь к файлу игнорирования |
--no-ignore | Отключение обработки файла игнорирования |
--version | Показ информации о версии |
Tailsnitch выполняет 57 проверок безопасности в 7 категориях. См. docs/CHECKS.md для подробной документации по каждой проверке.
| ID | Проверка | Риск |
|---|---|---|
| ACL-001 | Политика «разрешить всё» по умолчанию | Все устройства имеют неограниченный доступ |
| ACL-002 | Неправильная конфигурация SSH autogroup:nonroot | SSH от имени любого пользователя, не являющегося root |
| 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 | Раскрытие в CT-журналах HTTPS | Имена машин публичны |
| NET-005 | Видимость трафика узла выхода | Оператор видит весь трафик |
| NET-006 | Воздействие Serve | Локальные сервисы в tailnet |
| SSH-003 | Воздействие интерфейса Recorder | Сеансы видны сети |
Проверки конфигурации журналирования, настроек DNS, ролей пользователей и элементов ручной проверки.
Некоторые проверки оценивают то, что находят, а не несут одну фиксированную серьёзность. Три из них стоит выделить:
+=====================================================================+
| TAILSNITCH SECURITY AUDIT |
| Tailnet: example.com |
| Version: 1.0.0 (build: abc123) |
+=====================================================================+
Используется файл игнорирования: .tailsnitch-ignore (3 правила)
=== ACCESS CONTROLS ===================================================
[CRITICAL] ACL-001: Активна политика «разрешить всё» по умолчанию
В вашей политике ACL отсутствует поле 'acls'. Tailscale применяет
политику «разрешить всё» по умолчанию, предоставляя всем устройствам полный доступ.
Исправление:
Определите явные правила ACL, следуя принципу наименьших привилегий.
Источник: https://tailscale.com/docs/reference/examples/acls
----------------------------------------------------------------------
=== AUTHENTICATION & KEYS =============================================
[HIGH] AUTH-001: Существуют многоразовые ключи аутентификации
Найдено 2 многоразовых ключа аутентификации. При компрометации
их можно повторно использовать для добавления нескольких устройств.
Детали:
- Ключ tskey-auth-xxx (истекает через 45 дней)
- Ключ tskey-auth-yyy (истекает через 89 дней)
Исправление:
Храните многоразовые ключи в менеджере секретов. Предпочитайте одноразовые ключи.
Источник: https://tailscale.com/docs/features/access-control/auth-keys
----------------------------------------------------------------------
SUMMARY
======================================================================
Critical: 1 High: 3 Medium: 5 Low: 2 Info: 8
Всего находок: 19 | Пройдено: 33
Проверки Tailnet Lock (DEV-010, DEV-012) требуют локального CLI tailscale и выполняются против демона локальной машины. При аудите удалённой tailnet-сети через --tailnet эти проверки отражают локальный статус, а не аудируемую tailnet-сеть.
# Указание пользовательского пути к бинарному файлу tailscale при необходимости
tailsnitch --tailscale-path /opt/tailscale/bin/tailscale
Запускайте Tailsnitch в конвейерах CI/CD для обнаружения регрессий безопасности:
# Пример для 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
# Завершить с ошибкой, если существуют проблемы критической или высокой серьёзности
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 для получения рекомендаций.