[GH-ISSUE #2513] [macOS] Kill Switch «DNS exceptions» (allowedDnsServers) игнорируется для WireGuard / AmneziaWG #1132

Open
opened 2026-10-13 20:35:00 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @hdream10 on GitHub (Apr 22, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2513

Describe the bug

На macOS при подключении с включённым Kill Switch список «DNS exceptions» из Settings → Kill Switch не применяется к системному firewall. Настройка сохраняется корректно — её видно в ~/Library/Preferences/org.amneziavpn.AmneziaVPN.plist под ключом Conf/allowedDnsServers — но ни один из этих IP не попадает в pf-таблицу <dnsaddr>, на основе которой amn/310.blockDNS решает, какие DNS-адреса пропускать. В результате все DNS-запросы к серверам из whitelist'а молча режутся Kill Switch'ем.

Таблица <dnsaddr> после подключения содержит только primaryDnsServer и secondaryDnsServer из конфига туннеля. Значения из UI-поля «DNS exceptions» до firewall'а не доходят.

To Reproduce

  1. Настроить и активировать профиль сервера AmneziaWG (или WireGuard).
  2. Открыть Settings → Kill Switch → DNS exceptions и добавить IP DNS-сервера, например 10.0.0.1.
  3. Включить Kill Switch и подключиться.
  4. В терминале выполнить:
    sudo pfctl -a 'amn/310.blockDNS' -t dnsaddr -T show
    
  5. IP, добавленный на шаге 2, отсутствует в выводе.

Независимая проверка того, что pf-слой работает корректно — ручное добавление IP в таблицу:

sudo pfctl -a 'amn/310.blockDNS' -t dnsaddr -T add 10.0.0.1

DNS-трафик к 10.0.0.1 сразу начинает проходить. При следующем переподключении Amnezia таблица пересобирается, и записи снова нет. Это подтверждает, что настройка просто не доезжает до firewall-слоя при установке соединения.

Expected behavior

Каждый IP, сконфигурированный в Settings → Kill Switch → DNS exceptions, должен присутствовать в pf-таблице <dnsaddr> после подключения, чтобы DNS-трафик к этим серверам проходил через Kill Switch.

Log files

N/A.

Screenshots

N/A. Проблема полностью воспроизводится из терминала через вывод pfctl -T show.

Desktop:

  • OS: macOS 26.2 (build 25C56), Apple Silicon
  • Version: AmneziaVPN 4.8.14.5 (stable). То же поведение наблюдалось и на 4.8.11.4 до обновления.

Smartphone:

N/A.

Server:

Amnezia Premium (AmneziaWG-туннель). Проблема на стороне клиента, от сервера не зависит.

Additional context

Исходя из беглого просмотра кода, наиболее вероятное место, где теряется список — WireGuard-специфичный daemon-код для macOS: client/platforms/macos/daemon/wireguardutilsmacos.cpp, ветка, которая собирает FirewallParams при killSwitchEnabled == true и затем вызывает MacOSFirewall::setAnchorTable("310.blockDNS", ..., "dnsaddr", params.dnsServers). Это предположение на основе поверхностного чтения кода.

Также предполагаю, что Linux-путь WireGuard daemon'а (client/platforms/linux/daemon/wireguardutilslinux.cpp) может иметь ту же проблему, поскольку структура обработки Kill Switch / DNS вокруг params.dnsServers выглядит аналогично macOS-варианту. На Linux сам не воспроизводил — гипотеза.

Originally created by @hdream10 on GitHub (Apr 22, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2513 **Describe the bug** На macOS при подключении с включённым Kill Switch список «DNS exceptions» из Settings → Kill Switch не применяется к системному firewall. Настройка сохраняется корректно — её видно в `~/Library/Preferences/org.amneziavpn.AmneziaVPN.plist` под ключом `Conf/allowedDnsServers` — но ни один из этих IP не попадает в pf-таблицу `<dnsaddr>`, на основе которой `amn/310.blockDNS` решает, какие DNS-адреса пропускать. В результате все DNS-запросы к серверам из whitelist'а молча режутся Kill Switch'ем. Таблица `<dnsaddr>` после подключения содержит только `primaryDnsServer` и `secondaryDnsServer` из конфига туннеля. Значения из UI-поля «DNS exceptions» до firewall'а не доходят. **To Reproduce** 1. Настроить и активировать профиль сервера AmneziaWG (или WireGuard). 2. Открыть Settings → Kill Switch → DNS exceptions и добавить IP DNS-сервера, например `10.0.0.1`. 3. Включить Kill Switch и подключиться. 4. В терминале выполнить: ``` sudo pfctl -a 'amn/310.blockDNS' -t dnsaddr -T show ``` 5. IP, добавленный на шаге 2, отсутствует в выводе. Независимая проверка того, что pf-слой работает корректно — ручное добавление IP в таблицу: ``` sudo pfctl -a 'amn/310.blockDNS' -t dnsaddr -T add 10.0.0.1 ``` DNS-трафик к `10.0.0.1` сразу начинает проходить. При следующем переподключении Amnezia таблица пересобирается, и записи снова нет. Это подтверждает, что настройка просто не доезжает до firewall-слоя при установке соединения. **Expected behavior** Каждый IP, сконфигурированный в Settings → Kill Switch → DNS exceptions, должен присутствовать в pf-таблице `<dnsaddr>` после подключения, чтобы DNS-трафик к этим серверам проходил через Kill Switch. **Log files** N/A. **Screenshots** N/A. Проблема полностью воспроизводится из терминала через вывод `pfctl -T show`. **Desktop:** - OS: macOS 26.2 (build 25C56), Apple Silicon - Version: AmneziaVPN 4.8.14.5 (stable). То же поведение наблюдалось и на 4.8.11.4 до обновления. **Smartphone:** N/A. **Server:** Amnezia Premium (AmneziaWG-туннель). Проблема на стороне клиента, от сервера не зависит. **Additional context** Исходя из беглого просмотра кода, наиболее вероятное место, где теряется список — WireGuard-специфичный daemon-код для macOS: `client/platforms/macos/daemon/wireguardutilsmacos.cpp`, ветка, которая собирает `FirewallParams` при `killSwitchEnabled == true` и затем вызывает `MacOSFirewall::setAnchorTable("310.blockDNS", ..., "dnsaddr", params.dnsServers)`. Это предположение на основе поверхностного чтения кода. Также предполагаю, что Linux-путь WireGuard daemon'а (`client/platforms/linux/daemon/wireguardutilslinux.cpp`) может иметь ту же проблему, поскольку структура обработки Kill Switch / DNS вокруг `params.dnsServers` выглядит аналогично macOS-варианту. На Linux сам не воспроизводил — гипотеза.
Author
Owner

@pbelinovich commented on GitHub (Aug 29, 2026):

Подтверждаю на AmneziaVPN 5.0.1, macOS 26.6.2 (build 25G83), Apple Silicon, AmneziaWG. Поведение то же, что описано для 4.8.14.5 — за четыре месяца и мажорную версию не изменилось.

Проверка вашим способом, при поднятом туннеле. В настройках клиента primaryDns = 192.168.1.1, secondaryDns = 1.1.1.1, список DNS exceptions пуст:

$ sudo pfctl -a 'amn/310.blockDNS' -t dnsaddr -T show
   1.1.1.1
   192.168.1.1

Ровно primary + secondary, ничего больше. Ручное добавление сразу открывает трафик:

$ sudo pfctl -a 'amn/310.blockDNS' -t dnsaddr -T add 77.88.8.8
1/1 addresses added.
$ dig +short @77.88.8.8 ya.ru
77.88.44.242

Отдельно подтверждаю и обратное: при заполненном Conf.allowedDnsServers адрес в таблицу не попадает. Записал 192.168.1.1 в DNS exceptions, сохранил, переподключился — значение в plist осталось, в <dnsaddr> его не было, DNS-трафик к нему резался. Метка времени записи конфига и старта процесса amneziawg-go совпадали до секунды, так что настройка точно была на месте в момент установки соединения.


Хочу добавить к issue то, чего в нём пока нет: насколько велики последствия. Сейчас он читается как «настройка не доезжает до firewall», и из такой формулировки не видно, что при настройках по умолчанию ломается всё.

Дело в связке с раздельным туннелированием. Померил разницу режимов на одной и той же конфигурации клиента:

Раздельное туннелирование включено — клиент свой DNS в систему не устанавливает:

resolver #1
  nameserver[0] : 192.168.1.1      # роутер, выданный по DHCP

Раздельное туннелирование выключено (полный туннель) — устанавливает:

resolver #1
  search domain[0] : lan
  nameserver[0] : 192.168.1.1
  nameserver[1] : 1.1.1.1          # из настроек клиента; DHCP этот адрес не раздаёт,
                                   # ручного DNS на интерфейсе нет

Отсюда и следует поломка. В раздельном режиме macOS спрашивает резолвер локальной сети — а KillSwitch пропускает только primary/secondary, где по умолчанию стоят 1.1.1.1 / 1.0.0.1. Получается, что разрешён адрес, который система не спрашивает, и заблокирован тот, который спрашивает. При дефолтных настройках DNS в этом режиме не работает вообще.

Само по себе то, что в раздельном режиме резолвер остаётся локальным, выглядит правильно — в этом режиме имена и должны разрешаться в локальной сети. Проблема в том, что KillSwitch этого не учитывает, а штатное средство примирить одно с другим — DNS exceptions — не работает.

Почему это тяжело диагностировать пользователю:

  • Отказ молчаливый и полный. ICMP проходит, порт 443 открыт, сайты открываются по прямому IP — не работают только имена. Выглядит как «сломался интернет» или «провайдер блокирует DNS», а не как проблема VPN.
  • Проявляется отложенно. Пока системный резолвер по какой-то причине совпадает с primary DNS, всё работает; ломается при первой же смене резолвера — переподключение, обновление аренды DHCP, переход в другую сеть. Со стороны это «вчера работало, сегодня нет» на машине, где ничего не меняли.
  • Конфигурация полностью дефолтная: DNS по умолчанию, KillSwitch включён, раздельное туннелирование включено. Ничего экзотического не требуется.

Замер по всем резолверам при включённом туннеле, до исправления (primaryDns = 1.1.1.1). Колонки ICMP и TCP/443 показывают, что сами адреса доступны — отказ ровно на порту 53:

резолвер UDP/53 TCP/53 ICMP TCP/443
1.1.1.1 (primary) да да да да
1.0.0.1 (secondary) да да да да
8.8.8.8 нет нет да да
9.9.9.9 нет нет да да
77.88.8.8 нет нет да да
208.67.222.222 нет нет да да
94.140.14.14 нет нет да да
192.168.1.1 (резолвер, который спрашивает macOS) нет нет да —

Обходной путь для тех, кто сюда придёт: вписать адрес своего роутера в DNS servers → Primary, оставив публичный резолвер запасным. Тогда роутер попадает в <dnsaddr> и всё работает. Ограничение — адрес привязан к конкретной сети, в другой понадобится другой.

Что помогло бы, по убыванию пользы:

  1. Починить DNS exceptions — функция существует ровно для этого случая.
  2. В раздельном режиме по умолчанию разрешать текущие системные резолверы: в этом режиме клиент намеренно оставляет разрешение имён локальным, и блокировать локальный резолвер противоречит замыслу самого режима.
  3. Как минимум предупреждать при подключении, если сконфигурированный primary/secondary DNS не совпадает с тем, что реально будет спрашивать система. Одна такая проверка превращает молчаливый полный отказ в понятное сообщение.
<!-- gh-comment-id:5462481459 --> @pbelinovich commented on GitHub (Aug 29, 2026): Подтверждаю на **AmneziaVPN 5.0.1**, macOS 26.6.2 (build 25G83), Apple Silicon, AmneziaWG. Поведение то же, что описано для 4.8.14.5 — за четыре месяца и мажорную версию не изменилось. Проверка вашим способом, при поднятом туннеле. В настройках клиента `primaryDns = 192.168.1.1`, `secondaryDns = 1.1.1.1`, список DNS exceptions пуст: ``` $ sudo pfctl -a 'amn/310.blockDNS' -t dnsaddr -T show 1.1.1.1 192.168.1.1 ``` Ровно primary + secondary, ничего больше. Ручное добавление сразу открывает трафик: ``` $ sudo pfctl -a 'amn/310.blockDNS' -t dnsaddr -T add 77.88.8.8 1/1 addresses added. $ dig +short @77.88.8.8 ya.ru 77.88.44.242 ``` Отдельно подтверждаю и обратное: при заполненном `Conf.allowedDnsServers` адрес в таблицу не попадает. Записал `192.168.1.1` в DNS exceptions, сохранил, переподключился — значение в plist осталось, в `<dnsaddr>` его не было, DNS-трафик к нему резался. Метка времени записи конфига и старта процесса `amneziawg-go` совпадали до секунды, так что настройка точно была на месте в момент установки соединения. --- Хочу добавить к issue то, чего в нём пока нет: **насколько велики последствия**. Сейчас он читается как «настройка не доезжает до firewall», и из такой формулировки не видно, что при настройках по умолчанию ломается всё. Дело в связке с раздельным туннелированием. Померил разницу режимов на одной и той же конфигурации клиента: **Раздельное туннелирование включено** — клиент свой DNS в систему не устанавливает: ``` resolver #1 nameserver[0] : 192.168.1.1 # роутер, выданный по DHCP ``` **Раздельное туннелирование выключено (полный туннель)** — устанавливает: ``` resolver #1 search domain[0] : lan nameserver[0] : 192.168.1.1 nameserver[1] : 1.1.1.1 # из настроек клиента; DHCP этот адрес не раздаёт, # ручного DNS на интерфейсе нет ``` Отсюда и следует поломка. В раздельном режиме macOS спрашивает резолвер локальной сети — а KillSwitch пропускает только primary/secondary, где по умолчанию стоят `1.1.1.1` / `1.0.0.1`. Получается, что **разрешён адрес, который система не спрашивает, и заблокирован тот, который спрашивает**. При дефолтных настройках DNS в этом режиме не работает вообще. Само по себе то, что в раздельном режиме резолвер остаётся локальным, выглядит правильно — в этом режиме имена и должны разрешаться в локальной сети. Проблема в том, что KillSwitch этого не учитывает, а штатное средство примирить одно с другим — DNS exceptions — не работает. Почему это тяжело диагностировать пользователю: - Отказ молчаливый и полный. ICMP проходит, порт 443 открыт, сайты открываются по прямому IP — не работают только имена. Выглядит как «сломался интернет» или «провайдер блокирует DNS», а не как проблема VPN. - Проявляется отложенно. Пока системный резолвер по какой-то причине совпадает с primary DNS, всё работает; ломается при первой же смене резолвера — переподключение, обновление аренды DHCP, переход в другую сеть. Со стороны это «вчера работало, сегодня нет» на машине, где ничего не меняли. - Конфигурация полностью дефолтная: DNS по умолчанию, KillSwitch включён, раздельное туннелирование включено. Ничего экзотического не требуется. Замер по всем резолверам при включённом туннеле, до исправления (`primaryDns` = `1.1.1.1`). Колонки ICMP и TCP/443 показывают, что сами адреса доступны — отказ ровно на порту 53: | резолвер | UDP/53 | TCP/53 | ICMP | TCP/443 | |---|---|---|---|---| | 1.1.1.1 (primary) | да | да | да | да | | 1.0.0.1 (secondary) | да | да | да | да | | 8.8.8.8 | **нет** | **нет** | да | да | | 9.9.9.9 | **нет** | **нет** | да | да | | 77.88.8.8 | **нет** | **нет** | да | да | | 208.67.222.222 | **нет** | **нет** | да | да | | 94.140.14.14 | **нет** | **нет** | да | да | | 192.168.1.1 (резолвер, который спрашивает macOS) | **нет** | **нет** | да | — | Обходной путь для тех, кто сюда придёт: вписать адрес своего роутера в **DNS servers → Primary**, оставив публичный резолвер запасным. Тогда роутер попадает в `<dnsaddr>` и всё работает. Ограничение — адрес привязан к конкретной сети, в другой понадобится другой. Что помогло бы, по убыванию пользы: 1. Починить DNS exceptions — функция существует ровно для этого случая. 2. В раздельном режиме по умолчанию разрешать текущие системные резолверы: в этом режиме клиент намеренно оставляет разрешение имён локальным, и блокировать локальный резолвер противоречит замыслу самого режима. 3. Как минимум предупреждать при подключении, если сконфигурированный primary/secondary DNS не совпадает с тем, что реально будет спрашивать система. Одна такая проверка превращает молчаливый полный отказ в понятное сообщение.
Author
Owner

@mfattakhov commented on GitHub (Oct 6, 2026):

Воспроизводится на AmneziaVPN 5.0.3 (macOS 26, Apple Silicon).

Ещё один сценарий, который ломается: параллельно с Amnezia поднят корпоративный OpenVPN (Pritunl, отдельный utun), внутренние домены резолвятся только его DNS (ниже 10.0.0.53). С включённым KillSwitch трафик в его туннель проходит (200.allowVPN разрешает все utun*), но DNS к 10.0.0.53 режется в 310.blockDNS. Добавил 10.0.0.53 в DNS exceptions, переподключился: в Conf.allowedDnsServers он есть, в <dnsaddr> нет.

$ sudo pfctl -a amn/310.blockDNS -t dnsaddr -T show
   1.0.0.1
   1.1.1.1
$ sudo pfctl -a amn/310.blockDNS -t dnsaddr -T add 10.0.0.53
1/1 addresses added.

После ручного добавления всё работает, до следующего переподключения. Обход «вписать адрес в Primary DNS» здесь не подходит: тогда все запросы пойдут в корпоративный DNS. Нужны именно рабочие DNS exceptions.

<!-- gh-comment-id:6011197749 --> @mfattakhov commented on GitHub (Oct 6, 2026): Воспроизводится на **AmneziaVPN 5.0.3** (macOS 26, Apple Silicon). Ещё один сценарий, который ломается: параллельно с Amnezia поднят корпоративный OpenVPN (Pritunl, отдельный `utun`), внутренние домены резолвятся только его DNS (ниже `10.0.0.53`). С включённым KillSwitch трафик в его туннель проходит (`200.allowVPN` разрешает все `utun*`), но DNS к `10.0.0.53` режется в `310.blockDNS`. Добавил `10.0.0.53` в DNS exceptions, переподключился: в `Conf.allowedDnsServers` он есть, в `<dnsaddr>` нет. ``` $ sudo pfctl -a amn/310.blockDNS -t dnsaddr -T show 1.0.0.1 1.1.1.1 $ sudo pfctl -a amn/310.blockDNS -t dnsaddr -T add 10.0.0.53 1/1 addresses added. ``` После ручного добавления всё работает, до следующего переподключения. Обход «вписать адрес в Primary DNS» здесь не подходит: тогда все запросы пойдут в корпоративный DNS. Нужны именно рабочие DNS exceptions.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#1132
No description provided.