Этот документ - для тех, кто проверяет код перед тем, как разрешить установку
(служба ИБ, аудит, самопроверка). Версия: v2.2.1. Ссылки на строки даются в формате
файл:строка и относятся к состоянию кода на момент этой версии - при последующих правках
номера строк могут сместиться, ориентируйтесь по названиям методов/переменных, если файл
успел измениться.
- Приложение не реализует собственный сетевой протокол. Вся связь с удалённым DNS-сервером
идёт через штатный WinRM (Windows Remote Management) - тот же самый транспорт, что
использует
Enter-PSSession,Invoke-Commandи удалённое управление черезdnsmgmt.msc. Ничего поверх стандартных возможностей Windows не добавляется. - Аутентификация - Kerberos (если клиент и сервер в одном домене) либо NTLM через
TrustedHosts(если клиент вне домена). Оба механизма - встроенные в Windows, приложение их не реализует само, а просто вызывает штатный командлетNew-CimSession. - HTTPS-транспорт и пропуск проверки TLS-сертификата, которые были в v2.1.0, полностью убраны в v2.2.1 (см. раздел 5) - сейчас в кодовой базе нет пути, который бы принимал недоверенный сертификат сервера.
- Пароль никогда не пишется на диск - ни в файл лога, ни в файл настроек, ни во временные
файлы. Хранится в памяти только как
SecureString.
По умолчанию поле DnsHelper.ComputerName пустое, и все командлеты выполняются локально,
на том же компьютере, где запущено приложение (DnsHelper.cs:22).
Если пользователь указывает целевой сервер (поле "Целевой DNS-сервер" в главном окне), это
значение просто передаётся как параметр -ComputerName каждому вызову командлета
(DnsHelper.cs:211) - стандартный параметр модуля DnsServer, ничего специфичного для этого
приложения. Аутентификация в этом случае - текущая Windows-сессия пользователя
(Kerberos с делегированием текущего токена), без ввода пароля.
Если требуется подключиться под другой учёткой, чем текущая Windows-сессия - открывается
ServerAuthDialog (ServerAuthDialog.cs). Логика:
- Пароль, введённый в текстовое поле, сразу же посимвольно копируется в
SecureString(ServerAuthDialog.cs:127), сразу помечается неизменяемым (.MakeReadOnly(),ServerAuthDialog.cs:129), и текстовое поле пароля немедленно очищается (ServerAuthDialog.cs:130) - обычнаяstring-копия пароля нигде не хранится дольше, чем нужно для этого одного присваивания. SecureStringпередаётся вDnsHelper.TryAuthenticate(DnsHelper.cs:53), который строит из негоPSCredential(DnsHelper.cs:62) и вызывает штатный командлетNew-CimSession -ComputerName <сервер> -Credential <PSCredential>.New-CimSession- это командлет из модуляCimCmdlets, входящего в поставку Windows (не сторонняя библиотека). Он сам решает, как аутентифицироваться - Kerberos или NTLM - по тем же правилам, что и любой другой инструмент Windows, использующий WinRM/WSMan. Приложение не влияет на выбор протокола и не реализует его само.- Созданная
CimSessionкешируется по серверу (DnsHelper.cs:62, словарь_cimSessions, не единственное значение на всё приложение) и используется для всех дальнейших запросов именно к этому серверу (ps.AddParameter("CimSession", ...),DnsHelper.cs:220) - то есть повторно логиниться не нужно, пока не закроется приложение. Несколько разных серверов, авторизованных с явными кредами, могут оставаться подключёнными одновременно - переключение между ними в интерфейсе не разрывает подключение к остальным (DnsHelper.cs:120).
Если клиентская машина не входит в домен, Kerberos физически не может работать (нет
доверия к KDC), и WinRM требует одно из двух: HTTPS-транспорт, либо явное добавление
целевого сервера в список TrustedHosts на клиенте. Это ограничение самого WinRM,
задокументированное Microsoft - не то, что придумано в этом приложении. Соответствующая
команда (Set-Item WSMan:\localhost\Client\TrustedHosts ...) выполняется пользователем
вручную, в системном PowerShell, вне этого приложения - само приложение TrustedHosts
никак не читает и не изменяет.
- Манифест -
asInvoker(app.manifest:16): приложение стартует без запроса UAC вообще. Права администратора реально нужны только для локального режима (когда операция идёт против DNS-службы на этой же машине) - для удалённого управления (-ComputerName/CimSession) права проверяются на стороне целевого сервера через Kerberos/NTLM, локальная элевация тут вообще не при чём. - Если локальная операция реально упирается в нехватку прав, приложение само это
распознаёт (
DnsHelper.cs:30,IsRunningElevated, плюс детектирование "Access Denied" вInvoke()) и предлагает перезапуск с UAC через диалог (MainForm.cs:2463,OfferAdminRelaunch) -Process.StartсVerb="runas", что запрашивает UAC у самой ОС, не у кода приложения. Показывается один раз за сессию (MainForm.cs:2431,_adminPromptShown), не спамит при повторных отказах. - Права на конкретные операции DNS (создание/удаление зон, записей и т.д.) отдельно
проверяются на целевом сервере через Kerberos/NTLM-авторизацию (обычно требуется
членство в группе
DnsAdmins/Domain Admins) - то, что пользователь администратор на своей локальной машине, никак не даёт ему прав на чужом DNS-сервере.
changes.log(FileLogger.cs:15) фиксирует только реальные изменения - создание/ удаление зон, scope, записей, подсетей, политик, а также попытки аутентификации.- Запись о попытке входа (
FileLogger.LogChange("AUTH", ...),ServerAuthDialog.cs:143) содержит: имя сервера, введённый логин, успех/неуспех, текст ошибки (если была) - пароль в лог не передаётся ни при каком результате, методLogChange(FileLogger.cs:49) в принципе не принимает такой параметр. settings.iniхранит только пользовательские настройки интерфейса (позиции разделителей, историю адресов серверов) - учётные данные там не хранятся вообще, ни в каком виде.
В v2.1.0 добавлялись два чекбокса в окне аутентификации:
- "Подключаться через HTTPS" - WinRM поверх TLS (порт 5986) вместо обычного HTTP (5985).
- "Пропустить проверку сертификата" - при HTTPS принимать любой сертификат сервера без
проверки цепочки доверия и совпадения имени (
New-CimSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck).
Почему убрано:
- Ненадёжно на практике. В реальном тестировании HTTPS-путь либо падал на несовпадении
сертификата (сертификаты почти никогда не выпускаются на IP-адрес, только на имя сервера),
либо - даже с пропуском проверки сертификата и успешным TLS-рукопожатием - сервер отвечал
Access Deniedна уровне уже самого WinRM/CIM. Причина в конкретной конфигурации HTTPS-листенера на сервере, не в чём-то поправимом в этом приложении. - "Пропустить проверку сертификата" - осознанное снижение защиты транспорта. Такая опция принимает любой сертификат, включая поддельный (атака "человек посередине"), без предупреждения пользователю в моменте подключения. Даже если она физически не используется, сам факт наличия такого переключателя - обоснованный повод для вопросов при разборе кода. Проще и честнее убрать код целиком, чем оставлять выключенным.
- Обычный путь (TrustedHosts + Kerberos/NTLM) уже подтверждён рабочим - то же самое,
что делает стандартный
Enter-PSSession, ничего дополнительного не требуется.
Сейчас в DnsHelper.TryAuthenticate (DnsHelper.cs:53) нет параметров, включающих HTTPS
или отключающих проверку сертификата - такой код физически отсутствует в файле, не просто
скрыт из интерфейса.
Для полноты - явно перечислено, чего в коде нет:
- Не открывает никаких сетевых портов самостоятельно (весь сетевой ввод-вывод - через
штатные командлеты
New-CimSession/Invoke-Command-подобные механизмы PowerShell/CIM). - Не хранит и не передаёт учётные данные в открытом виде на диск или по сети сверх того, что делает сам WinRM при обычной Kerberos/NTLM-аутентификации.
- Не содержит захардкоженных учётных данных, ключей или токенов.
- Не отключает и не ослабляет какие-либо системные настройки безопасности Windows (файрвол, WinRM-конфигурацию, TrustedHosts) - все подобные действия выполняются пользователем вручную, вне приложения, отдельными системными командами.
- Не собирает и не отправляет телеметрию за пределы локальной сети - единственное сетевое
обращение вовне (не к DNS-серверу) - необязательная проверка обновлений через GitHub API
(
UpdateChecker.cs), которую пользователь запускает вручную кнопкой в окне "О программе".