Статья от одного из наших постоянных читателей – philzy :).
Я являюсь совладельцем сервиса cloud-desktop.net, и недавно у меня возникла проблема. Один из клиентов попросил восстановить виртуалку из бэкапа. Я восстановил ночную реплику за 2 мин., однако клиент сказал, что не может получить к ней доступ. Прошло 30 минут траблшутинга – виртуалка из реплики, оказывается, имеет другой MAC-адрес (да и IP), следовательно слетел доступ.
Я в курсе про то, что для таких случаев придуман DNS, но сервис работает именно через IP и этому есть простое объяснение – DNS разрешение имен не всегда корректно работает в haproxy [backend] server. Так как это ключевой элемент системы, то для снижения количества возможных проблем и было выбрано такое решение.
В общем, выдача IP-адреса через MAC-адрес – это не мой метод, и в качестве альтернативы я решил рассмотреть использование Client id или DHCP Option 61, использующий не привязанный к MAC-адресу метод выдачи IP-адресов через DHCP.
Я создал DHCP-пул на mikrotik и решил начать тестирование. Казалось, что это будет просто и понятно.
Увы… Windows 10, как впрочем и все остальные десктопные представители этой ОС, не всегда используют эту DHCP Option 61 [для проверки уникальности]. И выдают в этом поле вот такое:
Т.е. ничего.
Прим.: серверные версии дают в этом поле текущее значение mac-адреса со значением индекса сетевой карты (0,1,2…)
Это меня не устраивало, и я решил выяснить, почему так происходит.
Гугление дало только пару мутных ссылок по этой теме:
- social.technet.microsoft.com/Forums/ru-RU/ea654b2c-5c07-4bdf-acdf-a63e4d7f7de0/dhcp-client-identifier?forum=windows7ru
- www.itprotoday.com/management-mobility/jsi-tip-2845-how-can-i-keep-same-dhcp-client-reservation-if-mac-address-changes
Зато стало понятно, что в реестре есть некий ключ типа REG_DWORD:
1 |
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\'X'\Parameters\Tcpip |
который называется DhcpClientIdentifier.
Допустимый диапазон значений 0x0 – 0xFFFFFFFF. Размер изменяемого значения DhcpClientIdentifier – 4 байта, 8 шестнадцатеричных символов в группе по 2 шестнадцатеричных символа. Группы передаются в обратном порядке. Если размер изменяемого значения DhcpClientIdentifier менее 8 шестнадцатеричных символов, то в конец добавляется ноль.
Но далее у меня встал вопрос, а если параметры DWORD (8 цифр) меня не устраивают, и я хочу ЦифроБуквы, то что делать?
Тут я вспомнил, что есть замечательный тип REG_BINARY, которому все равно, что передавать.
Я еще разок перечитал RFC – www.ietf.org/rfc/rfc4361.txt и понял, что в моем случае RFC будет несколько нарушен, так как я хочу передавать в Client id имя виртуалки, а не уникальный идентификатор сетевого устройства.
Согласен, что это может привести к проблемам, если у клиента будет 2 и более сетевых карты, но для меня это не критично, так как у клиента всегда будет только одна сетевая карта.
Поставив простой эксперимент по записи данных в бинарном виде, я понял что тип REG_BINARY передает то, что я хочу и без всякой инверсии порядка следования. Таким образом стало ясно, что нужен простой и незатейливый Powershell скрипт:
1 2 3 4 5 6 7 8 9 10 |
$client_id="v12345678" $hexified=[System.Text.Encoding]::ASCII.GetBytes($client_id) $objWin32NAC = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -namespace "root\CIMV2" -computername "." -Filter "IPEnabled = 'True' AND DHCPEnabled ='True'" foreach ($objNACItem in $objWin32NAC) { $nic=($objNACItem.SettingID) New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\$nic -Force -Name DhcpClientIdentifier -PropertyType Binary -Value ([byte[]]$hexified) } Write-Host $nic Write-Host $hexified |
[System.Text.Encoding]::ASCII.GetBytes($client_id) – вот эту строку я стал передавать в Client id, когда понял что значения передаются ASCII-символами без всяких хитрых и сложных преобразований (и без всякого UNICODE).
В скрипте оставлена возможность, что сетевых карточек будет более чем одна, но это скорее «на всякий случай».
и проверяем еще раз:
MAC-адрес сменился с 00:50:56:B4:F0:90 на 00:50:56:B4:F0:91, а IP-адрес остался тот же.
УРА!!!
Конечно, такое можно сделать и для нескольких карточек, используя индекс сетевой карты и имя компьютера (например), но в моем случае это не нужно.