Skip to content
foosber-bytePublic

Latest commit

 

History

41 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

English version

DnsToolWinForms

WinForms-приложение для работы с DNS-сервером Windows - то, чего нет в dnsmgmt.msc: записи внутри Zone Scope в виде дерева, клиентские подсети, Query Resolution Policies, удалённое управление другим сервером со своей аутентификацией, автообновление с GitHub.

Работает через встроенный PowerShell-модуль DnsServer. Автор: foosber, 2026. v2.9.2.

Требования

  • .NET Framework 4.8 - обычно уже стоит на Windows Server 2016+.
  • Роль DNS Server там, куда направлены операции (локально или через "Целевой DNS-сервер"). RSAT: DNS Server Tools, если приложение работает только удалённо.
  • Права администратора нужны только для локального режима (см. ниже) - при отказе приложение само предложит перезапуск с UAC.
  • Visual Studio 2019/2022 - только для сборки из исходников.

Права администратора - по требованию, а не всегда

Манифест - asInvoker: приложение стартует без UAC-запроса. Права нужны только когда операция идёт локально (DNS-служба на этой же машине) - при удалённом управлении (-ComputerName/CimSession) права проверяются на стороне целевого сервера через Kerberos/NTLM, локальная элевация тут вообще не при чём.

Если локальная операция реально упёрлась в нехватку прав - приложение показывает окно "Требуются права администратора" с предложением перезапуститься через UAC (Verb="runas"). Показывается один раз за сессию, не спамит при повторных отказах.

Интерфейс

  • Значки вместо текстовых кнопок на всех 3 вкладках - свои, через GDI+ (IconFactory.cs). Действия с вводом данных (создать зону/scope/запись/подсеть/политику) открывают диалог по клику на "+". Фильтр остаётся обычным полем - живой поиск важнее компактности.
  • Подсказки "?" - круглый пастельный значок с текстом во всплывающей подсказке (HelpIcon.cs) вместо постоянного серого текста.
  • Баннер - справа в самой верхней панели окна, на всю её высоту (не отдельным блоком сверху и не втиснут в общую высоту элементов слева), клик открывает "О программе" (как и значок в футере).
  • Двойной клик по записи - редактирование; правая кнопка мыши - меню проверить/изменить/удалить (на дереве записей - ещё и "создать папку").
  • Сворачивание блока вывода без потери накопленного текста.

Вкладка "Scopes и записи" (зоны, scope'ы и записи - всё в одном дереве)

Отдельной вкладки "Зоны" больше нет - управление зонами переехало сюда же, а сам список зон стал одним из уровней общего дерева. Два явно разграниченных блока с рамкой, стоящие рядом по горизонтали (не друг под другом - экономит вертикальное место для дерева и списка записей ниже), шириной точно по содержимому - "Управление зонами" (создать/удалить/перезагрузить/экспортировать/обновить список) и "Управление scope/записями" (создать/удалить scope, обновить записи текущего scope) - чтобы не путать, какая кнопка к чему относится, раз теперь всё на одной вкладке.

Дерево: верхний уровень - серверы ("Локальный" + любой, к которому успешно подключались через панель "Целевой DNS-сервер"); внутри каждого сервера - "Зоны прямого просмотра", "Зоны обратного просмотра" и (если есть) "Прочие зоны (условная пересылка, stub)". Категория берётся из самого объекта зоны: ZoneType Forwarder/Stub → "прочие"; IsReverseLookupZone → "обратного просмотра" (с откатом на суффикс .in-addr.arpa/.ip6.arpa); остальное → "прямого просмотра". Служебные авто-зоны (TrustAnchors, корневые подсказки ., 0/127/255.in-addr.arpa) не показываются - как обычный, не "расширенный", вид dnsmgmt.msc. Зоны условной пересылки и stub - листья (Zone Scopes они не поддерживают, WIN32 9603), по клику показывают только источник. Внутри каждой категории - сами зоны; внутри зоны - её scope'ы; внутри scope - записи, сгруппированные по составным именам в папки (как в dnsmgmt.msc): admin.pro32connect → папка pro32connect, элемент admin. Каждый уровень подгружается лениво (при первом выборе/раскрытии узла) - ничего не тянется с сервера впустую. Группировка записей в папки - визуальная, из уже загруженных данных; папка - только узел со своими дочерними узлами, одноуровневые записи не превращаются в лишние ветки. Справа - содержимое текущей папки (папки сверху, как в проводнике). Позиция границы запоминается (RecordsTreeSplitter). Узел-сервер в дереве подсвечен (синий фон, белый жирный текст) - сразу видно верхний уровень, не путая его с зонами/scope на вкладке.

Управление зонами: создание (Add-DnsServerPrimaryZone, типы AD-домен/AD-лес/файловая), удаление (Remove-DnsServerZone), перезагрузка с диска (значок с буквой "R" внутри - dnscmd /ZoneReload, всегда локально, не учитывает целевой сервер) - все три действия применяются к зоне, выбранной сейчас в дереве. Экспорт - имена зон текущего (развёрнутого) сервера в .txt файл. Строка под блоками показывает источник выбранной зоны с составным форматированием (не просто серый текст): слова "Источник" и "мастер-серверы" подчёркнуты, тип зоны (Primary/Secondary/Stub) и сами адреса мастер-серверов/путь к файлу - жирным.

Несколько серверов одновременно: подключение к серверу (см. "Управление другим сервером удалённо" ниже) сохраняется на весь срок работы приложения, и это верно сразу для нескольких серверов параллельно - переключение между ними в дереве не разрывает подключение к остальным. Клик по узлу сервера в дереве сам переключает панель "Целевой DNS-сервер" сверху на него.

Добавление записи учитывает текущую папку - запись test внутри pro32connect станет test.pro32connect. @ внутри папки = сама папка. Поля Priority/Weight/Port видны только для SRV/MX.

Создание "папки": правая кнопка на scope/папке → диалог с выбором режима. По умолчанию - wildcard-запись * внутри нового поддомена (*.sales → IP): и настоящая запись, и способ сделать поддомен видимым как папку (папка появляется, только если у узла есть свои дочерние узлы - сама по себе запись sales без вложенности останется обычной строкой, не папкой). Второй вариант - буквально как "Новый домен" в dnsmgmt.msc (запись с именем ровно как папка, без *) - с явным предупреждением: так папка не появится в дереве, пока внутри неё нет ещё одной вложенной записи.

Файловый режим (значок с блокнотом) - обходной путь для Secondary-зон, где обычное добавление падает с WIN32 9611: правка .dns-файла scope напрямую, всегда локально, с бэкапом и dnscmd /ZoneReload. Explicit предупреждение при каждом использовании.

Экспорт записей в .txt - имя сервера, с которого сделана выгрузка (DnsHelper.ComputerName, если задан целевой сервер, иначе имя локальной машины), попадает и в имя файла, и первой строкой внутрь самого файла вместе с датой - чтобы файл был понятен и без контекста, откуда он взялся.

Импорт записей из такого файла (значок со стрелкой вверх): строки-папки ([FLDR] имя N запис.) распознаются и не импортируются как записи - вместо этого предлагается создать соответствующий субдомен через wildcard (с IP на каждый, по желанию). Есть чекбокс "Исключить @-записи". Импорт идёт в текущую выбранную папку/scope (как и обычное добавление). Значения SRV/MX разбираются обратно из составного текста в экспорте (target:port (priority=..., weight=...) / exchange (preference=...)); если запись из файла уже существует в scope (по имени+типу) - диалог конфликта показывает и существующее, и новое значение рядом (сразу видно, это точный дубль или реально отличается IP/имя), и спрашивает перезаписать или пропустить, с массовым вариантом ("всё") - после него дальнейшие конфликты решаются автоматически без повторных вопросов. Список "что уже есть в scope" обновляется по ходу самого импорта (не только один раз в начале) - если в файле есть повторяющаяся запись, второй дубль тоже распознаётся как конфликт с тем, что уже добавлено в этом же прогоне, а не улетает в DNS Server напрямую с ошибкой "запись уже существует".

Командлеты: A/AAAA/CNAME/PTR/MX - типизированные (Add-DnsServerResourceRecordA и т.д.). NS/TXT/SRV - только универсальный Add-DnsServerResourceRecord -NS/-Txt/-Srv (выделенных командлетов нет). @ в имени - запись в корне зоны.

Редактирование - пересоздание (сначала новая, потом старая, чтобы не терять данные при сбое), кроме CNAME: DNS не даёт CNAME сосуществовать с другой записью под тем же именем ни на секунду, поэтому порядок обратный (сначала удалить, потом добавить, с откатом при неудаче). Удаление - через -InputObject с полным объектом записи; можно выделить сразу несколько записей (обычное множественное выделение списком, правый клик внутри уже выделенной группы не сбрасывает её) - одно подтверждение на всю группу, папки среди выделенного игнорируются молча.

Прогресс операций: каждое успешное добавление/удаление/импорт записи - отдельная строка в блоке вывода вида OK: запись "имя" (тип) значение добавлена в зону "...", scope "..." (для удаления - аналогично), а не просто финальная сводка в конце.

Проверка записи - nslookup (Resolve-DnsName, вывод причёсан) и Ping (с -t, источником -S, кодировкой CP866).

Вкладка "Подсети"

Get/Add/Remove-DnsServerClientSubnet. Имя + CIDR.

Вкладка "Политики"

Get/Add/Remove-DnsServerQueryResolutionPolicy. У результата Get-... подсеть лежит в Criteria, scope - в Content (не ClientSubnet/ZoneScope, это имена параметров у Add-..., не свойств у Get-...). Несколько подсетей через запятую (логическое ИЛИ).

Подсети в описании политики показаны только именами, без CIDR в скобках - раньше рядом с именем подставлялся реальный диапазон (net_100 (10.0.1.0/24)), но это "(...)" не часть имени подсети, и при копипасте такой строки в поле "Подсети" нового диалога создания политики получалась ошибка ("такой подсети не существует"). CIDR по-прежнему виден - на вкладке "Подсети".

Важно, легко забыть: политики (как и клиентские подсети) не реплицируются на резервные контроллеры домена - привязаны локально к этому серверу/зоне. Поэтому одно и то же имя политики у разных зон - не конфликт (диалог создания политики напоминает об этом явным текстом).

Удалённое управление другим сервером

Поле "Целевой DNS-сервер" сверху - все операции идут через -ComputerName, без переноса приложения. Если проверка подключения текущей учёткой не проходит - открывается окно аутентификации (логин/пароль), через New-CimSession -Credential (у командлетов DnsServer своего параметра -Credential нет). Сессия кэшируется на весь срок работы приложения, и это отдельно для каждого сервера - переключение между несколькими подключёнными серверами (в том числе через дерево на вкладке "Scopes и записи") не разрывает подключение к остальным; закрывается всё только при закрытии самого приложения.

Транспорт - обычный WinRM: Kerberos (домен) или NTLM через TrustedHosts на клиенте (не домен) - то же самое, что Enter-PSSession. Пароль не хешируется перед отправкой (Kerberos/ NTLM сам challenge-response, хеширование сломало бы аутентификацию), строится в памяти сразу как SecureString. Подробный разбор - SECURITY.md.

Если клиент не в домене:

Set-Item WSMan:\localhost\Client\TrustedHosts -Value "<сервер>" -Concatenate -Force

История последних 10 серверов - в settings.ini.

Подтверждение удаления

Запись - обычное да/нет. Зона/scope/подсеть/политика - усиленное окно с 5-секундной задержкой кнопки "Удалить".

Прочее

  • Автоподгрузка списков зон/scope при первом заходе на вкладку.
  • changes.log рядом с exe - только реальные изменения и попытки аутентификации, без пароля.
  • Диагностика ошибок: полное разворачивание CIM/PowerShell исключений; понятные сообщения вместо сырых дампов для типичных случаев - "не DNS-сервер" (WIN32 1722), "нужны права администратора" (см. выше), "WinRM не достучался" (TrustedHosts/файрвол/ сетевой профиль), "зона не поддерживает Zone Scopes" (WIN32 9603 - зоны условной пересылки и похожие типы структурно не поддерживают scope'ы, это не временная проблема).
  • Обновления: кнопка в "О программе" тянет последний релиз с GitHub, сравнивает версию (AppVersion.cs), качает и ставит через .bat-скрипт (ждёт закрытия процесса через tasklist, копирует robocopy, перезапускает). settings.ini/changes.log/*.dns не трогает. Нужен исходящий HTTPS до github.com.

Как открыть и собрать

  1. Скачай папку на сервер, открой DnsToolWinForms.csproj в Visual Studio (2019/2022).
  2. NuGet восстановится сам. Переключи на Release, собери (Ctrl+Shift+B).
  3. Готовый .exe - в bin\Release\net48\. Копируется на сервер как есть, ничего дополнительно ставить не нужно (сборка PowerShell берётся из самой Windows).

Антивирус ругается на exe - ожидаемо для неподписанного exe, хостящего PowerShell: подписать (signtool.exe), добавить в исключения, либо отправить как false positive.

NuGet не находит Microsoft.PowerShell.5.1.ReferenceAssemblies - в .csproj есть закомментированный HintPath-блок на системную сборку, раскомментируй вместо PackageReference.

Структура

  • Program.cs - точка входа. MainForm.cs - вся форма (разметка кодом, без .resx).
  • DnsHelper.cs - обёртка над PowerShell: вызовы командлетов, разбор ошибок, CimSession для удалённой аутентификации, проверка элевации.
  • IconFactory.cs/HelpIcon.cs - значки и подсказки (GDI+).
  • *Dialog.cs - все диалоговые окна (создание зон/scope/записей/подсетей/политик, аутентификация, подтверждение удаления, проверка записи, "О программе").
  • UpdateChecker.cs - обновления через GitHub. FileLogger.cs - changes.log. AppVersion.cs - версия приложения.
  • SECURITY.md - разбор безопасности удалённого подключения со ссылками на код.

Что можно доделать под себя

  • Просмотр записей вне scope; более строгая валидация ввода (IP/CIDR).
  • Создание зоны условной пересылки (conditional forwarder) с теми же опциями, что в dnsmgmt.msc (Add-DnsServerConditionalForwarderZone) - сейчас в блоке "Управление зонами" можно создать только Primary (AD-интегрированную или файловую); зоны условной пересылки не поддерживают Zone Scopes вообще (см. диагностику WIN32 9603 выше), поэтому это отдельная, самостоятельная ветка функциональности, не пересекающаяся с остальной частью приложения.

Лицензия

MIT - используй, форкай, меняй как угодно, сохраняя авторство (LICENSE). Без гарантий: инструмент пишет напрямую в DNS-конфигурацию, тестируй на некритичном окружении.

Поддержать автора

  • USDT (TRC20/TRON): TQp9az9Nbnojg65qwvRjhwRkEnwEfFHK77
  • ETH (ERC20): 0x40d1775df43a9ff67aabe21ccb000421c0d6f092

⚠️ Проверь сеть перед отправкой. Необязательно - инструмент бесплатный в любом случае ^_^

Releases

Contributors

Languages