gitscope
← awesome-scripts / master / dnsleak-guard/README.md
https://dev.kronoz.win/r/awesome-scripts.git
dnsleak-guard/README.md · markdown
Blame Raw

dnsleak-guard

Страж системного DNS для macOS. Автоматически возвращает DNS на 127.0.0.1, если сторонняя программа (например, Clash Verge Rev) его перезаписывает.

📖 Зачем это нужно

Clash Verge Rev при запуске в режиме TUN принудительно прописывает 114.114.114.114 (китайский публичный DNS) в системные настройки macOS. Это приводит к:

  • Утечке DNS — провайдер перехватывает запросы к 114.114.114.114 и подставляет свои резолверы.
  • Рассинхрону — часть DNS-запросов идёт через Clash TUN, часть — мимо.

dnsleak-guard решает проблему: LaunchDaemon раз в 10 секунд проверяет системный DNS и возвращает его на 127.0.0.1, где его перехватывает Clash TUN.

📂 Состав

Файл Назначение
ensure_dns.sh Основной скрипт-страж. Работает от root, бесконечный цикл
com.user.dnsleak-guard.plist LaunchDaemon для автозапуска при загрузке
install.sh Скрипт автоустановки

🔧 Требования

  • macOS 11+ (Big Sur и новее)
  • Clash Verge Rev или другой клиент в режиме TUN
  • dns.listen в конфиге Clash должен слушать порт 53 (например, 0.0.0.0:53)
  • Права root (для networksetup -setdnsservers)

📥 Установка

Автоматическая

WIP

Ручная

# 1. Скрипт
sudo cp ensure_dns.sh /usr/local/bin/ensure_dns.sh
sudo chmod +x /usr/local/bin/ensure_dns.sh
sudo chown root:wheel /usr/local/bin/ensure_dns.sh

# 2. LaunchDaemon
sudo cp com.user.dnsleak-guard.plist /Library/LaunchDaemons/
sudo chown root:wheel /Library/LaunchDaemons/com.user.dnsleak-guard.plist
sudo chmod 644 /Library/LaunchDaemons/com.user.dnsleak-guard.plist

# 3. Загрузить
sudo launchctl load /Library/LaunchDaemons/com.user.dnsleak-guard.plist

# 4. Проверить
sudo launchctl list | grep dnsleak-guard

🚀 Использование

После установки демон работает автоматически:

  • Запускается при загрузке системы (до логина пользователя).
  • Каждые 10 секунд проверяет DNS на всех активных сетевых сервисах.
  • Если DNS отличается от 127.0.0.1 — сбрасывает его и очищает DNS-кэш macOS.
  • Пишет события в /tmp/dnsleak-guard.log.

Проверка состояния

# Демон запущен?
sudo launchctl list | grep dnsleak-guard

# Текущий системный DNS
scutil --dns | grep nameserver
# Должно быть: nameserver[0] : 127.0.0.1

# Логи работы
tail -20 /tmp/dnsleak-guard.log

Ожидаемые логи

[2026-09-14 18:30:01] dnsleak-guard started
[2026-09-14 18:30:05] [Wi-Fi] DNS reset: '114.114.114.114' -> 127.0.0.1
[2026-09-14 18:30:05] DNS cache flushed

Если в логах только dnsleak-guard started — значит, Clash не перезаписывает DNS, и страж просто ждёт.

🛑 Управление

# Остановить
sudo launchctl unload /Library/LaunchDaemons/com.user.dnsleak-guard.plist

# Запустить
sudo launchctl load /Library/LaunchDaemons/com.user.dnsleak-guard.plist

# Перезапустить (после правки скрипта)
sudo launchctl unload /Library/LaunchDaemons/com.user.dnsleak-guard.plist
sudo launchctl load /Library/LaunchDaemons/com.user.dnsleak-guard.plist

Полное удаление

sudo launchctl unload /Library/LaunchDaemons/com.user.dnsleak-guard.plist
sudo rm /Library/LaunchDaemons/com.user.dnsleak-guard.plist
sudo rm /usr/local/bin/ensure_dns.sh
sudo rm -f /tmp/dnsleak-guard.log /tmp/dnsleak-guard.out /tmp/dnsleak-guard.err

# Вернуть автоматический DNS
sudo networksetup -setdnsservers Wi-Fi "Empty"
sudo networksetup -setdnsservers Ethernet "Empty" 2>/dev/null
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

⚙️ Конфигурация

Параметры задаются в начале ensure_dns.sh:

DNS_SERVER="127.0.0.1"              # Целевой DNS-сервер
LOG_FILE="/tmp/dnsleak-guard.log"   # Путь к логу
sleep 10                            # Интервал проверки (в конце скрипта)

Изменить интервал

Значение Эффект
sleep 5 Быстрее реагирует, больше нагрузки
sleep 10 Компромисс (по умолчанию)
sleep 30 Реже проверяет, тише логи
sleep 60 Минимальная нагрузка

🐛 Решение проблем

Демон не запускается

sudo launchctl list | grep dnsleak-guard
cat /tmp/dnsleak-guard.err

Если пусто — загрузите принудительно:

sudo launchctl load -w /Library/LaunchDaemons/com.user.dnsleak-guard.plist

Логи переполнены ошибками «X is not a recognized network service»

Это псевдо-сервисы (Thunderbolt Bridge и т.д.). Убедитесь, что в скрипте используется while IFS= read -r service, а не for service in $(...). Обновите скрипт:

git pull
sudo cp ensure_dns.sh /usr/local/bin/ensure_dns.sh
sudo launchctl unload /Library/LaunchDaemons/com.user.dnsleak-guard.plist
sudo launchctl load /Library/LaunchDaemons/com.user.dnsleak-guard.plist

DNS всё равно утекает

1. Проверьте, что Clash слушает порт 53:

sudo lsof -iTCP:53 -iUDP:53 | grep -iE "clash|mihomo"

Если пусто — в конфиге Clash замените dns.listen на 0.0.0.0:53.

2. Отключите DoH в браузерах:

  • Chrome: chrome://settings/security → «Использовать безопасный DNS» → ВЫКЛ
  • Firefox: about:preferences#privacy → «Enable DNS over HTTPS» → ВЫКЛ

3. Сбросьте DNS-кэш:

sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

4. Проверьте через dnsleaktest.com → Extended Test. Должен быть только IP вашего VPS.

Интернет пропадает после установки

Скорее всего, Clash не слушает порт 53, а системный DNS указывает на 127.0.0.1, где никто не отвечает.

Быстрое восстановление:

sudo networksetup -setdnsservers Wi-Fi "Empty"
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

Затем исправьте dns.listen в Clash.

📊 Как это работает

┌─────────────────────────────────────────────────────────┐
│                    macOS                                │
│  ┌───────────────────────────────────────────────────┐  │
│  │  Системный DNS = 127.0.0.1                        │  │
│  └──────────────────┬────────────────────────────────┘  │
│                     │                                   │
│                     ▼                                   │
│  ┌───────────────────────────────────────────────────┐  │
│  │  Clash TUN (utun) слушает 53                      │  │
│  │  dns-hijack: any:53                               │  │
│  └──────────────────┬────────────────────────────────┘  │
│                     │                                   │
│                     ▼                                   │
│  ┌───────────────────────────────────────────────────┐  │
│  │  DNS → VLESS-туннель → VPS → CoreDNS              │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  LaunchDaemon com.user.dnsleak-guard                    │
│  ├── Каждые 10 сек: проверяет DNS на всех сервисах      │
│  ├── Если DNS ≠ 127.0.0.1:                              │
│  │   ├── networksetup -setdnsservers                    │
│  │   └── dscacheutil -flushcache + killall mDNSResponder│
│  └── Логи в /tmp/dnsleak-guard.log                      │
└─────────────────────────────────────────────────────────┘

🔐 Безопасность

  • Работает от root — необходимо для networksetup -setdnsservers.
  • Не принимает внешних команд, только меняет DNS на заранее заданный 127.0.0.1.
  • Не передаёт данные наружу — вся работа локальная.
  • Логи содержат только имена сервисов и их DNS — никакой чувствительной информации.

📝 Лицензия

MIT.

🤝 Вклад

Pull request'ы приветствуются. Особенно интересны:

  • Уведомления через Telegram / macOS Notification Center при сбросе DNS.
  • Ротация логов.
  • Совместимость с другими клиентами (ClashX Pro, sing-box, Stash).