• Exchange Server 2010 How-to: Установка ролей Client Access и Hub Transport в NLB кластере на Windows Server 2008 R2

    imageС учетом нововведений в Exchange Server 2010, которые приближают роль Client Access к действительно оправдывающей своё название компоненте, перед нами возникает задача обеспечения максимально возможной отказоустойчивости этой роли в продуктивной среде. На сегодняшний день существуют лучшие методики и рекомендации Microsoft, которые обеспечение отказоустойчивости Exchange посредствам WNLB уже не признают как рекомендуемые, а вместо этого предлагают использовать аппаратные решения обеспечения балансировки нагрузки и отказоустойчивости. Однако в реальной практике, по тем или иным причинам, не все себе могут позволить придерживаться таких рекомендаций, и поэтому использование NLB на платформе Windows Server в такой ситуации будет вполне приемлемым вариантом. Я пошагово опишу на практическом примере процедуру установки ролей Exchange Server 2010 SP1 - Client Access (CA) и Hub Transport (HT) на два сервера, включённых в NLB кластер на Windows Server 2008 R2 в среде виртуализации Hyper-V Server 2008 R2.

    С точки зрения сетевого взаимодействия, схема отказоустойчивого NLB кластера из двух серверов Exchange 2010 с ролями Client Access и Hub Transport в нашем случае будет выглядеть так:

    clip_image002

    Среда исполнения

    В качестве серверов, на которые будет произведена установка Exchange Server 2001 SP1, будет использоваться два виртуальных сервера на базе хостов виртуализации на ОС Hyper-V Server 2008 R2. Каждый виртуальный сервер имеет следующую конфигурацию:

    • ОС Windows Server 2008 R2 Standard EN;
    • Объем выделенной ОЗУ - 4 Gb;
    • Число логических процессоров – 4;
    • Жёсткий диск – VHD фиксированного размера в 60 Gb;
    • Два синтетических сетевых адаптера

    При создании второго сетевого адаптера, который будет использоваться для построения NLB в свойствах виртуальной машины Hyper-V необходимо разрешить спуфинг МАС адресов (Enable spoofing of MAC addresses)

    image

    На Microsoft есть статья, описывающая возможные проблемы, связанные с построением NLB кластеров в окружении Hyper-V -KB953828 - Windows Server 2008 Hyper-V virtual machines generate a Stop error when NLB is configured or when the NLB cluster does not converge as expected


    Подготовка ОС к созданию кластера NLB

    После того как виртуальные машины сконфигурированы, на них установлена ОС и установлены все последние обновления с Windows Update, приступаем к настройке ОС для подготовки к созданию NLB кластера.

    Первым делом через Server Manager установим компоненту (фичу) Network Load Balancing

    image

    Так же компоненту NLB можно установить с помощью команды:

    dism /online /enable-feature /featurename:NetworkLoadBalancingFullServer

    clip_image007

    Дополнительную информацию об альтернативных способах установки NLB можно найти в статье MSDN Blogs - Clustering and High-Availability - Installing Network Load Balancing (NLB) on Windows Server 2008 R2

    Как обозначилось ранее, на каждом виртуальном сервере мы имеем по два сетевых интерфейса. Назовём их NIC1 и NIC2 и условимся что, согласно нашей схемы, NIC1 будет отвечать за управление самим сервером (будет зарегистрирован в DNS на FQDN имя сервера) а NIC2 (для которого включён спуфинг MAC адресов) будет участником NLB кластера.

    clip_image008

    Откроем окно настройки сетевых подключений и в меню Advanced > Advanced Settings и проверим порядок использования подключений (Connections). NIC1 должен иметь приоритет над NIC2.

    clip_image009

    Так же в свойствах сетевого подключения, которое будет использоваться для подключения к NLB кластеру (в нашем случае - NIC2) можно отключить все компоненты, за исключением TCP/IP:

    clip_image010

    В свойствах компонента TCP/IP зададим только выделенный IP адрес и маску подсети и по кнопке Advanced откроем окно дополнительных настроек

    clip_image011

    Обратите внимание на то, что в системах Windows Server 2008/2008R2 IP форвардинг пакетов между локальными интерфейсами внутри системы по умолчанию выключен, и для того чтобы наш NLB интерфейс стал доступен, нам нужно включить IP форвардинг на сетевом подключении входящем в NLB кластер командой:

    netsh interface ipv4 set interface “NIC2 – NLB” forwarding=enabled

    В окне дополнительных настроек TCP/IP на закладке DNS отключим механизм регистрации в DNS

    clip_image012

    После этого в локальной доменной зоне прямого просмотра DNS нам необходимо создать статическую А-запись для будущего NLB кластера.

    clip_image013


    Создание кластера NLB

    На первом виртуальном сервере (KOM-AD01-HT01) открываем консоль Network Load Balancing Manager. (меню Пуск > Administrative Tools). Выбираем пункт меню Cluster > New Cluster

    clip_image014

    Вводим имя первого узла, который хотим добавить в NLB, кнопкой Connect подключаемся к нему, и получив с него набор доступных интерфейсов, выбираем нужный:

    clip_image015

    На странице параметров хоста (Host Parameters) оставляем настройки по умолчанию:

    clip_image016

    В следующем окне мастера создания кластера добавляем IP адрес NLB кластера, на который мы ранее в DNS зарегистрировали А-запись.

    clip_image017

    Далее указываем FQDN кластера NLB (по той самой A-записи), а также режим его работы. Если серверы Exchange 2010 CAS установлены на VMware ESX или имеют другие требования к выбору многоадресного режима нужно выбрать режим Multicast , в нашем же случае нужно выбрать опцию одноадресного режима - Unicast.

    clip_image018

    На странице правил портов (Port rules) удаляем имеющееся по умолчанию правило и добавляем необходимые нам правила. При добавлении правила портов убираем флажок All и указываем конкретный интерфейс NLB и диапазон портов, который хотим добавить в кластер NLB.

    clip_image019

    В общей сложности, в нашем примере балансировке в NLB кластере мы будем подвергать следующие порты:

    • TCP 25 – Отправка почты по SMTP (для Legacy приложений);
    • TCP 80 – Перенаправление HTTP > HTTPS в IIS;
    • TCP 110 – Получение почты по POP3 (для Legacy приложений);
    • TCP 143 – Подключение по IMAP4;
    • TCP 443 - Outlook Anywhere, Exchange ActiveSync и Outlook Web App;
    • TCP 135 – MAPI RPC для подключения клиентов;
    • TCP 1024-65535 – MAPI RPC (Динамический диапазон RPC) для подключения клиентов;
    • TCP 993 – Secure IMAP (в Filtering mode Affinity установить в значение None);
    • TCP 995 – Secure POP (в Filtering mode Affinity установить в значение None);

    Диапазон динамических портов RPC при желании можно изменить до использования конкретного статического порта. Пример того как это можно сделать описан в статье Новая служба RPC Client Access Service в Exchange 2010 (обратите внимание на то, что в статье упор делается на RTM Exchange Server 2010, а с выходом SP1 процедура настройки статических портов RPC несколько изменилась).

    clip_image020

    Все необходимые параметры кластера заданы, создаем его по нажатию кнопки Finish и после первоначальной инициализации, если в конфигурации не допущены ошибки, NLB кластер запуститься в конфигурации с одним узлом

    image

    Далее, переходим на имя NLB кластера и пунктом меню Add Host to Cluster вызываем мастер добавления второго хоста в кластер.

    clip_image022

    Указываем имя нашего второго виртуального сервера (KOM-AD01-HT02), выполняем к нему подключение(Connect) и выбираем соответствующее сетевое подключение на этом удалённом сервере:

    clip_image023

    Значения на странице параметров хоста (Host Parameters) оставляем по умолчанию (приоритет хоста в кластере NLB будет выбран автоматически и при желании его можно изменить в много-хостовых конфигурациях)

    clip_image024

    Далее получаем список настроенных ранее портов, и если нет необходимости его изменять, завершаем процедуру и получаем уже полноценный Windows NLB кластер из двух хостов

    clip_image025


    Подготовка ОС к установке Exchange Server 2010 SP1

    Предварительные требования к ОС для установки Exchange Server 2010 можно найти по ссылке - TechNet Library - Exchange 2010 Prerequisites. Перед развёртыванием Exchange Server 2010 в AD должны быть проведены процедуры расширения схемы, подготовки леса и домена. Порядок проведения этих процедур описан в статье Exchange Server TechCenter - Prepare Active Directory and Domains.

    Так как на наших виртуальных серверах мы планируем включение роли Hub Transport, нам желательно предварительно скачать и установить Microsoft Office 2010 Filter Packs. Фильтры IFilter, входящие в пакет Microsoft Office 2010 Filter Pack используются в подсистеме поиска Exchange для индексирования текстового содержимого в форматах файлов Microsoft Office 2007/2010.

    В Exchange Server 2010 SP1 программа установки Exchange должна сама зарегистрировать фильтры IFilter из пакета фильтров Office 2010 Filter Pack в службе поиска Exchange, в отличие от RTM версии, где регистрацию нужно проводить в ручную, поэтому всё, что нам предварительно нужно сделать, это скачать 64-битную версию пакета и установить её…

    clip_image026

    Далее все необходимые системные компоненты для ролей Client Access и Hub Transport можно быстро установить с помощью PowerShell:

    Import-Module ServerManager

    Add-WindowsFeature NET-Framework,RSAT-ADDS,Web-Server,Web-Basic-Auth,Web-Windows-Auth,Web-Metabase,Web-Net-Ext,Web-Lgcy-Mgmt-Console,WAS-Process-Model,RSAT-Web-Server,Web-ISAPI-Ext,Web-Digest-Auth,Web-Dyn-Compression,NET-HTTP-Activation,RPC-Over-HTTP-Proxy -Restart

    После окончания установки компонент, сервер выполнит перезагрузку. И так как набор используемых в ОС компонент расширился, сразу после перезагрузки выполним запрос к серверу WSUS и установим все доступные обновления.

    Мы планируем наши сервера для роли Client Access и поэтому необходимо изменить тип запуска службы Net.Tcp Port Sharing Service на Автоматический. Сделать это можно также командой PowerShell:

    Set-Service NetTcpPortSharing -StartupType Automatic

    Дополнительно, перед установкой роли Client Access, нам необходимо учесть требования раздела «Install the Exchange 2010 SP1 Hotfixes for Windows Server 2008 R2» онлайн документации и вручную скачать и установить обновления (которые не распространяются через WSUS), необходимые для корректного сосуществования с Exchange Server 2010 SP1:

    · KB982867 - WCF services that are hosted by computers together with a NLB fail in .NET Framework 3.5 SP1
    · KB979744 - A .NET Framework 2.0-based Multi-AppDomain application stops responding when you run the application
    ·
    KB983440 - An ASP.NET 2.0 hotfix rollup package is available for Windows 7 and for Windows Server 2008 R2
    ·
    KB977020 - FIX: An application that is based on the Microsoft .NET Framework 2.0 Service Pack 2 and that invokes a Web service call asynchronously throws an exception on a computer that is running Windows 7

    Скачаем по ссылкам указанным в KB пакеты исправления соответствующие нашей платформе – x64 и произведём их установку. После установки этих обновлений потребуется перезагрузка системы.

    clip_image027

    Без предварительной установки этих обновлений инсталлятор Exchange Server 2010 SP1 попросту не даст установить роль Client Access.


    Установка Exchange Server 2010 SP1

    Распаковываем ISO дистрибутив Exchange Server 2010 с интегрированным SP1 и запускаем Setup.exe в режиме Run as Administrator.

    Выбираем пункт 3 - Choose Exchange language option и указываем то, что для установки используем только языковые пакеты, входящие в состав дистрибутива

    image

    Затем выбираем пункт 4 - Install Microsoft Exchange

    Проходим шаги Introduction, License Agreement, Error Reporting и на шаге Installation Type выбираем Custom Exchange Server Installation, а так же на всякий случай отмечаем галку автоматической установки недостающих системных компонент:

    image

    На шаге выбора ролей отмечаем роли Client Access Role и Hub Transport Role

    image

    На следующем шаге нам будет предложено ввести FQDN имя нашего CA сервера (массива) опубликованное в Интернет. В моём случае точка публикации находится на другом сервере и поэтому я оставлю это значение пустым.

    image

    Затем инсталлятор проверит наличие в системе всех необходимых компонент для возможности установки выбранных ролей

    image

    Если проблемы не выявлены, можно запускать непосредственный процесс установки.

    image

    После окончания успешной установки необходимо будет произвести перезагрузку сервера.


    Установка последнего Rollup для Exchange Server 2010 SP1

    Информацию о текущих версиях Exchange Server можно найти по адресу - TechNet Wiki - Exchange Server and Update Rollups Builds Numbers

    На момент написания этой заметки, последним пакетом исправлений является - Update Rollup 2 for Exchange Server 2010 SP1 - 14.1.270.1 (12/9/2010) KB2425179

    Порядок установки последнего накопительного пакета обновлений описан в статье - TechNet Library - Install the Latest Update Rollup for Exchange 2010. Следуя его рекомендациям, для ускорения процесса установки, на время установки можно отключить проверку списков отзывов сертификатов в свойствах Internet Explorer (Открываем Internet Explorer и в меню Tools > Internet Options > Advanced > Security отключаем флажок Check for publisher’s certificate revocation).

    clip_image040

    Дополнительные сведения см. в статье 974445 базы знаний Майкрософт Создание образов NGEN занимает слишком много времени

    Для установки Rollup открываем командную строку в режиме Run as Administrator и запускаем из неё программу установки обновления, в нашем случае это файл Exchange2010-KB2425179-x64-en.msp, дожидаемся окончания установки и снова перезагружаем сервер, чтобы удостовериться в том, что все необходимые службы Exchange Server стартуют в штатном режиме.

    clip_image041


    Подготовка и привязка SAN сертификата

    Для корректной работы защищённого доступа к службам массива Client Access необходимо создать новый сертификат, так как FQDN, используемый для доступа в серверы Client Access в NLB кластере, не соответствует FQDN, заданному в поле общих имён или в поле альтернативных имён в SSL сертификате, который автоматически устанавливается на каждом сервере Client Access во время установки Exchange Server 2010. То есть нужно создать сертификат, в котором присутствуют несколько FQDN (сертификат с альтернативными именами объекта – SAN - Subject Alternative Name) – FQDN Client Access Array, FQDN каждого узла кластера NLB и служебные имена (такие как Autodiscover)

    Для создания запроса для нового SAN сертификата можно использовать Exchange Management Shell (командлет New-ExchangeCertificate):

    $RequestData = New-ExchangeCertificate -GenerateRequest -SubjectName "E = V.Pupkin@holding.com,CN = KOM-AD01-CA01.Holding.com,OU = KOMI,O = Holding Ltd.,L = Syktyvkar,S = Komi republic,C = RU" -DomainName kom-ad01-ca01.holding.com, kom-ad01-ht01.holding.com, kom-ad01-ht02.holding.com, autodiscover.holding.com, kom-ad01-ca01, kom-ad01-ht01, kom-ad01-ht02 -KeySize 1024 -PrivateKeyExportable $true

    Set-Content -path "C:TempCAS_SAN_Cert.req" -Value $RequestData

    Далее, на основании полученного файла запроса в локальном центре сертификации (если он настроен на поддержку сертификатов с Subject Alternative Name) можно получить сертификат.

    В нашем случае для отправки запроса и получения сертификата будет использоваться веб-узел локального центра сертификации Active Directory Certificate Services.

    На странице Advanced Certificate Request перейдём по ссылке “Submit a certificate request by using a base-64-encoded CMC or PKCS #10 file, or submit a renewal request by using a base-64-encoded PKCS #7 file.” и скопируем содержимое сгенерированного ранее запроса

    clip_image042

    После того как размещённый запрос на сертификат обработан администратором центра сертификации, мы можем с этого же веб-узла локального центра сертификации Active Directory Certificate Services загрузить сертификат в формате «Base 64 encoded» по ссылке « View the status of a pending certificate request » а затем «Download certificate chain».

    image

    Теперь импортируем полученный сертификат, используя Exchange Management Shell с помощью командлета Import-ExchangeCertificate:

    Import-ExchangeCertificate -FileData ([Byte[]]$(Get-Content -Path С:Temp CAS_SAN_Cert.p7b -Encoding byte -ReadCount 0))

    После импорта сертификата командлет вернёт нам Thumbprint, по которому можно будет проверить текущее состояние сертификата с точки зрения Exchange и его привязки к сервисам командлетом Get-ExchangeCertificate:

    Get-ExchangeCertificate -Thumbprint <thumbprint> | FL

    clip_image045

    В данный момент мы видим, что сертификат используется только службами IMAP и POP и нам нужно включить сертификат для остальных клиентских служб и SMTP. Для этого воспользуемся командлетом Enable-ExchangeCertificate:

    Enable-ExchangeCertificate –Thumbprint <thumbprint> -Services "IMAP, POP, IIS, SMTP"

    Теперь наш новый сертификат необходимо установить на втором узле NLB кластера (на сервере KOM-AD01-HT02). Для этого нужно произвести на сервере KOM-AD01-HT01 экспорт этого сертификата с закрытым ключом из хранилища Certificates /Local Computer/Personal. Сделать это можно через оснастку управления сертификатами.

    clip_image046

    в Certificate Export Wizard на странице Export Private Key выберите опцию Yes, export the private key

    image

    На странице Export File Format выберите Personal Information Exchange – PKCS #12 (.PFX) и поставьте отметку напротив Include all certificates in the certificates path if possible.

    image

    Затем введите пароль для защиты закрытого ключа, который мы в дальнейшем будем использовать для импорта сертификата на сервер KOM-AD01-HT02

    image

    Далее указываем имя файла и завершаем мастер экспорта сертификата. Полученный файл в формате PFX копируем на наш второй сервер (KOM-AD01-HT02) и, открыв на нём Exchange Management Shell, выполняем импорт сертификата с помощью командлета Import-ExchangeCertificate:

    clip_image053

    При этом появиться запрос на ввод учетных данных. В поле User name можно ввести любой текст, а в поле Password нужно ввести пароль, который мы ранее задали при экспорте сертификата в формате PFX. После того как сертификат успешно импортирован, как описывали ранее, выполняем привязку этого сертификата к службам Exchange на этом сервере:

    Enable-ExchangeCertificate –Thumbprint <thumbprint> -Services "IMAP, POP, IIS, SMTP"


    Создание массива Client Access Array (CAA)

    Теперь собираем сам массив Client Access Array. Для этой цели воспользуемся командлетом New-ClientAccessArray:

    New-ClientAccessArray -Fqdn KOM-AD01-CA01.holding.com -Site "MyMainSite" -Name "KOM-AD01-CA01.holding.com"

    Посмотреть свойства и проверить текущее состояние массива можно с помощью командлета Get-ClientAccessArray

    clip_image054


    Настройка Client Access URLs в массиве CAA

    Теперь для каждого сервера CAS в массиве CAA должны быть установлены URL обеспечивающие доступ к службам Exchange через NLB. То есть мы должны проверить следующие URL:

    · Autodiscover. Виртуальный каталог - /Autodiscover
    · Outlook Web Apps. Виртуальный каталог - /OWA
    · Exchange Control Panel. Виртуальный каталог - /ECP
    · Exchange Active Sync. Виртуальный каталог - /Microsoft-Server-ActiveSync
    · Offline Address Book. Виртуальный каталог - /OAB
    · Exchange Web Services. Виртуальный каталог - /EWS

    Итак, на каждом CAS сервере, входящем в ферму NLB (Массив CAA):


    1) Параметр AutoDiscoverServiceInternalUri должен быть установлен в значение CAA FQDN. Проверить это можно следующим скриптоблоком:

    $CASArrayName = "KOM-AD01-CA01.holding.com"

    $CAAObj = Get-ClientAccessArray | Where-Object {$_.Name -eq $CASArrayName}

    $CAAHosts = $CAAObj.Members

    Foreach ($CASHost in $CAAHosts)

    {

    Get-ClientAccessServer -Identity $CASHost.Name | FL Identity,AutoDiscoverServiceInternalUri

    }

    Результат должен быть примерно таким:

    clip_image055


    2) Для каждой веб-службы значение параметра InternalNLBBypassURL должно быть установлено в значение Server FQDN. Проверить это можно следующим скриптоблоком:

    $CASArrayName = "KOM-AD01-CA01.holding.com"

    $CAAObj = Get-ClientAccessArray | Where-Object {$_.Name -eq $CASArrayName}

    $CAAHosts = $CAAObj.Members | Select-Object Name

    Foreach ($CASHost in $CAAHosts)

    {

    Get-WebServicesVirtualDirectory -Server $CASHost.Name  | FL Identity, InternalNLBBypassUrl

    }

    Результат должен быть примерно таким:

    clip_image056


    3) Параметры InternalURL и ExternalURL для каждой веб-службы должны быть заданы в соответствии с таблицей:

    Виртуальный каталог

    InternalURL

    ExternalURL
    (AD Сайт с подключением к Интернету)

    ExternalURL
    (AD сайт без подключения к Интернету)

    /OWA

    NLB FQDN

    NLB FQDN (Внешнее имя)

    X

    /ECP

    NLB FQDN

    NLB FQDN (Внешнее имя)

    X

    /Microsoft-Server-ActiveSync

    NLB FQDN

    NLB FQDN (Внешнее имя)

    X

    /OAB

    NLB FQDN

    NLB FQDN (Внешнее имя)

    X

    /EWS

    NLB FQDN

    NLB FQDN (Внешнее имя)

    X

    Для быстрого получения информации о том, какие в текущий момент значения InternalURL и ExternalURL установлены на всех серверах массива CAA можно использовать скриптоблок:

    $CASArrayName = "KOM-AD01-CA01.holding.com"

    $CAAObj = Get-ClientAccessArray | Where {$_.Name -eq $CASArrayName}

    $CAAHosts = $CAAObj.Members | Select Name

    Foreach ($CASHost in $CAAHosts)

    {

    Write-Host $CASHost.Name "Client Access URLs:" -ForegroundColor Cyan

    Write-Host ""

    $UrlOWA = Get-OwaVirtualDirectory -Server $CASHost.Name

    Write-Host "OWA Internal:" $UrlOWA.InternalUrl

    Write-Host "OWA External:" $UrlOWA.ExternalUrl

    $UrlECP = Get-EcpVirtualDirectory -Server $CASHost.Name

    Write-Host "ECP Internal:" $UrlECP.InternalUrl

    Write-Host "ECP External:" $UrlECP.ExternalUrl

    $UrlASc = Get-ActiveSyncVirtualDirectory -Server $CASHost.Name

    Write-Host "ASc Internal:" $UrlASc.InternalUrl

    Write-Host "ASc External:" $UrlASc.ExternalUrl

    $UrlOAB = Get-OabVirtualDirectory -Server $CASHost.Name

    Write-Host "OAB Internal:" $UrlOAB.InternalUrl

    Write-Host "OAB External:" $UrlOAB.ExternalUrl

    $UrlWeb = Get-WebServicesVirtualDirectory -Server $CASHost.Name

    Write-Host "EWS Internal:" $UrlWeb.InternalUrl

    Write-Host "EWS External:" $UrlWeb.ExternalUrl

    Write-Host ""

    }

    Для того чтобы быстро установить все значения InternalURL в FQDN CAA воспользуемся скриптоблоком:

    $CASArrayName = "KOM-AD01-CA01.holding.com"

    $CAAObj = Get-ClientAccessArray | Where {$_.Name -eq $CASArrayName}

    $CAAFQDN = $CAAObj.Fqdn

    $CAAHosts = $CAAObj.Members | Select Name

    Foreach ($CASHost in $CAAHosts)

    {

    $OWADirObj = Get-OwaVirtualDirectory -Server $CASHost.Name

    Set-OwaVirtualDirectory -Identity $OWADirObj.Identity -InternalUrl "https://$CAAFQDN/owa"

    $ECPDirObj = Get-EcpVirtualDirectory -Server $CASHost.Name

    Set-EcpVirtualDirectory -Identity $ECPDirObj.Identity -InternalUrl "https://$CAAFQDN/ecp"

    $AScDirObj = Get-ActiveSyncVirtualDirectory -Server $CASHost.Name

    Set-ActiveSyncVirtualDirectory -Identity $AScDirObj.Identity -InternalUrl "https://$CAAFQDN/Microsoft-Server-ActiveSync"

    $OABDirObj = Get-OabVirtualDirectory -Server $CASHost.Name

    Set-OabVirtualDirectory -Identity $OABDirObj.Identity -InternalUrl "http://$CAAFQDN/OAB"

    $WebDirObj = Get-WebServicesVirtualDirectory -Server $CASHost.Name

    Set-WebServicesVirtualDirectory -Identity $WebDirObj.Identity -InternalUrl https://$CAAFQDN/EWS/Exchange.asmx

    }


    Подключение баз данных Exchange к CAA

    Если базы данных на серверах с ролью Mailbox создаются после создания массива CAA, то значение атрибута RpcClientAccessServer каждой БД должно быть задано как FQDN массива CAA. Проверить это можно с помощью команды:

    Get-MailboxDatabase | Format-List Name,RpcClientAccessserver

    clip_image057

    Если базы данных были созданы до настройки CAA, то значение атрибута RpcClientAccessServer будет иметь FQDN конкретного сервера с ролью Client Access. Переопределить это значение, указав FQDN массива CAA можно командой:

    Set-MailboxDatabase "MyDB" -RpcClientAccessServer "KOM-AD01-CA01.holding.com"


    Проверяем работоспособность Client Access Array

    Проверить работоспособность CAA можно, например, с помощью MS Outlook 2007/2010, служба Autodiscover должна разрешить имя сервера как FQDN массива. Откроем мастер добавления новой учетной записи в Outlook, утвердительно ответим на вопрос о настройке учетной записи электронной почты..

    clip_image058

    Дождёмся окончания процесса автоконфигурации..

    clip_image059

    После окончания работы мастера откроем в Outlook свойства созданного профиля учетной записи и проверим то, что подключение настроено на FQDN массива CAA

    image

    Обратите внимание на то, что при использовании клиентов Outlook 2003 может возникнуть проблема при подключении, если на серверах Exchange в службе RPC Client Access включено требование шифрования. Проверить текущее состояние этой настройки можно командой:

    Get-RpcClientAccess | Format-List Server,EncryptionRequired

    Дальше можно проверить возможность подключения к OWA с указанием всех вариантов имени CA/CAA в URL используемых при создании SAN сертификата и поочерёдно сымитировать отказ одного из серверов в NLB кластере, чтобы удостовериться в том, что сервисы клиентского доступа Exchange Server при этом остаются доступными.

    Дополнительная информация:

    TechNet Library - Exchange Server 2010 Library.
    Exchange Server TechCenter - White Paper: Understanding the Relative Costs of Client Access Server Workloads in Exchange Server 2010
    MSExchange.ru - Новая служба RPC Client Access Service в Exchange 2010
    Yannick Varloud Blog - Exchange Server 2010 : How to setup a Client Access Array

  • AD DS – Выбор DC для операции ввода в домен с помощью PowerShell командлета Add-Computer

    imageВ большой доменной инфраструктуре AD DS с большим количеством сайтов можно столкнуться с ситуацией, когда при вводе в домен новых компьютеров в сайте с единственным контроллером RODC операция ввода в домен происходит не на ближайшем RWDC а на отдалённом. Это приводит к тому, что перед тем как можно будет начать использовать в домене такой компьютер, потребуется выждать репликацию от удалённого DC до местного RODC. Избежать данной ситуации можно используя утилиту NETDOM, явным образом указывая ближайший контроллер домена, на котором мы хотим произвести процедуру джойна:

    image

    Но так как по умолчанию в клиентских системах этой утилиты нет, хочется воспользоваться каким-то подручным средством без выполнения дополнительным манипуляций. И тут нам на помощь приходит PowerShell с командлетом Add-Computer… но когда я решил воспользоваться им на практике, то выяснилось что встроенный хелп PowerShell об этом командлете (равно как и сайт TechNet Script Center) о чём-то нам не договаривает.

    Попытка выполнить ввод в домен строго по описанию не сработала, то есть при использовании командлета в виде…

    Add-Computer -DomainName 'MYDOM' -Credential 'MYDOMadmin' -OUPath 'OU=Clients,OU=Branch,DC=mydom,DC=com' -Server 'MYDOMBestDC' -PassThru –Verbose

    … приводила к ошибке, которая фиксировалась в логе NetSetup.LOG (расположен в каталоге C:Windowsdebug) примерно в следующем виде:

    02/03/2011 11:43:51:403 ----------------------------------------------------

    02/03/2011 11:43:51:403 NetpDoDomainJoin

    02/03/2011 11:43:51:403 NetpMachineValidToJoin: 'MyWS001'

    02/03/2011 11:43:51:403    OS Version: 6.1

    02/03/2011 11:43:51:403    Build number: 7600 (7600.win7_gdr.100618-1621)

    02/03/2011 11:43:51:403    SKU: Windows 7 Профессиональная

    02/03/2011 11:43:51:403 NetpDomainJoinLicensingCheck: ulLicenseValue=1, Status: 0x0

    02/03/2011 11:43:51:403 NetpGetLsaPrimaryDomain: status: 0x0

    02/03/2011 11:43:51:403 NetpMachineValidToJoin: status: 0x0

    02/03/2011 11:43:51:403 NetpJoinDomain

    02/03/2011 11:43:51:403    Machine: MyWS001

    02/03/2011 11:43:51:403    Domain: MYDOMBestDCMYDOM

    02/03/2011 11:43:51:403    MachineAccountOU: OU=Clients,OU=Branch,DC=mydom,DC=com

    02/03/2011 11:43:51:403    Account: MYDOMadmin

    02/03/2011 11:43:51:403    Options: 0x23

    02/03/2011 11:43:51:403 NetpLoadParameters: loading registry parameters...

    02/03/2011 11:43:51:403 NetpLoadParameters: DNSNameResolutionRequired not found, defaulting to '1' 0x2

    02/03/2011 11:43:51:403 NetpLoadParameters: DomainCompatibilityMode not found, defaulting to '0' 0x2

    02/03/2011 11:43:51:403 NetpLoadParameters: status: 0x2

    02/03/2011 11:43:51:403 NetpValidateName: checking to see if 'MYDOM' is valid as type 3 name

    02/03/2011 11:43:53:697 NetpCheckDomainNameIsValid for MYDOM returned 0x54b, last error is 0x0

    02/03/2011 11:43:53:697 NetpCheckDomainNameIsValid [ Exists ] for 'MYDOM' returned 0x54b

    02/03/2011 11:43:53:697 NetpJoinDomainOnDs: Domain name is invalid, NetpValidateName returned: 0x54b

    02/03/2011 11:43:53:697 NetpJoinDomainOnDs: Function exits with status of: 0x54b

    02/03/2011 11:43:53:697 NetpDoDomainJoin: status: 0x54b

    Как видно из лога, имя домена формируется как то не совсем адекватно. Немного поигравшись с использованием разных вариантов передачи параметров и проведя аналогию с использованием утилиты NETDOM, был найден работающий вариант, а именно:

    Add-Computer -DomainName 'mydom.comBestDC' -Credential 'MYDOMadmin' -OUPath 'OU=Clients,OU=Branch,DC=mydom,DC=com' -PassThru –Verbose

    То есть вместо параметра Server можно использовать передачу имени DC в параметре DomainName. Данный способ проверен и работает как на Windows 7, так и на Windows XP SP3.

    Если у кого-то есть комментарии по поводу того, как можно ещё обуздать механизм ввода в домен для компьютеров в сайте с RODC будет интересно их здесь услышать.

    Дополнительная информация для размышления:

    Windows Server TechCenter Forums - Selection of DC during a workstation join to domain operation

    Blog Jorge 's Quest For Knowledge! - DC Locator Process in W2K, W2K3(R2) and W2K8 - PART 1

  • PowerShell - Поиск неиспользуемых учетных записей пользователей и компьютеров в домене

    Для быстрого поиска в домене давно не используемых учетных записей пользователей можно использовать оснастку ‘Active Directory Users and Computers’ (dsa.msc), создав в ней запрос.

    image

    Читать далее...

  • PowerShell – Поддержание групп безопасности политики репликации паролей RODC в актуальном состоянии

    imageПри использовании контроллеров домена «только на чтение» (RODC) для каждого RODC должна быть определена доменная группа безопасности, в которую входят учетные записи пользователей, чьи учетные данные могут реплицироваться на этот RODC. В крупной географически распределённой инфраструктуре с большим количеством контроллеров домена задача поддержания состава этих групп безопасности «в рукопашную» может стать проблемой, особенно если учесть «человеческий фактор», когда например, в каком-то из удалённых подразделений местный администратор создаёт новую учетную запись доменного пользователя, а включить в группу репликации паролей эту запись забывает. Для того чтобы исключить в данном случае «человеческий фактор», можно автоматизировать данный процесс с помощью PowerShell. Рассмотрим пример скрипта, который можно включить в планировщик задач на контроллере домена на периодическое выполнение.

    Читать далее...

  • PowerShell – Поддержание группы безопасности для Password Settings objects (PSOs) в актуальном состоянии

    imageПо мотивам применения Password Settings objects (PSOs) с нацеливанием объектов PSO на доменные группы безопасности встаёт вопрос о поддержании состава этих групп в актуальном состоянии. В моём окружении все учетные записи, находящиеся в определённом OU, должны быть включены в доменную группу безопасности, к которой применяется PSO, что само по себе уже есть критерий, по которому можно автоматизировать задачу поддержания группы в актуальном состоянии с помощью PowerShell. Представляю соответствующий скрипт.

    Читать далее...

  • Powershell - Сброс SusClientId на проблемных клиентах Windows Update в домене

    imageПо мотивам борьбы с проблемой отображения в консоли WSUS некорректно клонированных клиентов, наткнулся на интересную заметку - ShS's Blog - Скрипт для удаленного сброса клиента службы Автоматического обновления. Представленный в этой статье скрипт был взят за основу и несколько переработан. В частности основные переменные были вынесены в отдельный блок, исключено использование временного файла, добавлена обработка исключения возникающего при обращении к 64-битным клиентским ОС, добавлена обработка исключений возникающих при удалении несуществующих ключей реестра, добавлен более детальный вывод хода выполнения скрипта на консоль.

    Скрипт работает в двух режимах, в зависимости от значения переменной $ResetSusClientId. Если значение переменной $ResetSusClientId = 0 (по умолчанию), - производится только сравнение данных о компьютерах полученных из AD и WSUS с выводом информации о значении ключа реестра SusClientId по всем проблемным клиентам. Если значение переменной $ResetSusClientId = 1, производится попытка сброса идентификационной информации клиента WU с последующей его перерегистрацией на сервере WSUS.

    ###############################################################
    # Требования: Powershell 2.0, WSUS API (Добавляется в систему при установке консоли WSUS) 
    #
    Write-Host  'Loading WSUS API...' -ForegroundColor Green
    [reflection.assembly]::LoadWithPartialName('Microsoft.UpdateServices.Administration') 
    Write-Host ''
    #
    # Блок переменных 
    # $WUSrvName – Имя сервера WSUS
    # $WUSrvPort – Порт подключения к серверу WSUS
    # $WUSrvHTTPS – Признак использования шифрования при подключении к серверу WSUS ($true или $false)
    # $ADSearchOU – ADSI путь к контейнеру с доменными учетными записями пользователей (в формате LDAP://distinguishedName)
    # $ADSearchFilter - Фильтр поиска объектов в AD (действующие учетные записи компьютеров)
    # $ResetSusClientId – Признак необходимости форсированной смены идентификатора SusClientId у отсутствующих на WSUS клиентов (1 или 0) 
    #
    $WUSrvName = 'KOM-AD01-SRV-WSUS'
    $WUSrvPort = 8530
    $WUSrvHTTPS = $false
    $ADSearchOU = 'LDAP://OU=Domain Computers,DC=mydom,DC=com'
    $ADSearchFilter = '(&(objectCategory=computer)(!userAccountControl:1.2.840.113556.1.4.803:=2))'
    $ResetSusClientId = 0
    #
    # Получаем список всех компьютеров зарегистрированных на WSUS-сервере: 
    Write-Host  'Getting WU clients data from Server' $WUSrvName 'on port' $WUSrvPort '...' -ForegroundColor Green
    $WSUS = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($WUSrvName, $WUSrvHTTPS, $WUSrvPort)
    $WSUScomps = $WSUS.GetComputerTargets() 
    $WSUSCompNames = $WSUScomps | ForEach { $_.FullDomainName.ToUpper() } 
    #
    # Получаем список учетных записей компьютеров из Active Directory: 
    Write-Host  'Getting AD computers from OU' $ADSearchOU '...' -ForegroundColor Green
    $ADcomps = (New-Object System.DirectoryServices.DirectorySearcher([ADSI]$ADSearchOU, $ADSearchFilter)).findAll() 
    $ADCompNames = $ADcomps | ForEach {$_.GetDirectoryEntry().dNSHostName.ToString().ToUpper()} 
    #
    # Получаем имена компьютеров, которые есть в Active Directory, но отсутствуют в WSUS:
    Write-Host 'Matching...' -ForegroundColor Green
    $NoWSUSCompNames = $ADCompNames | Where { $WSUSCompNames -notcontains $_ } | Sort-Object
    #
    # Блок смены идентификатора SusClientId 
    If ($NoWSUSCompNames.Count -eq $null) 
    {Write-Host 'Good. No differences.' -ForegroundColor Green}
    Else
    {
    Write-Host 'Found problem computers...' -ForegroundColor DarkRed
    Write-Host ''
    ForEach ($PC in $NoWSUSCompNames)
    {
    $Ping = New-Object System.Net.NetworkInformation.Ping
    Trap {Write-Host $PC 'can not ping' -ForegroundColor DarkRed; continue}
    If ($Ping.send($PC).Status -eq 'Success' ) {
    Write-Host $PC 'available' 
    #
    # Для того чтобы данный метод обращения к удалённому реестру успешно отработал на 64 битных системах скрипт должен запускаться в 64 PS
    # Пример проверки битности - http://poshcode.org/2027
    $is64 = [bool](gwmi win32_operatingsystem -computer $PC | ?{$_.caption -like '*x64*' -or $_.OSArchitecture -eq '64-bit'})
    $isShell32 = [bool]((Get-Process -Id $PID | ?{$_.path -like '*SysWOW64*'}) -or !([IntPtr]::Size -eq 8))
    If ($is64 -and $isShell32)
    {Write-Warning 'Unable to open registry keys because PC is running an x64 OS. Script must be run from a PowerShell x64 shell' }
    Else
    {
    $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $PC)  
    $RegKey= $Reg.OpenSubKey('SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate',$true)  
    $RegKeyValue1 = $RegKey.GetValue('SusClientId')
    #Trap {Write-Host $PC 'can not get registry key value' -ForegroundColor DarkRed; continue}
    Write-Host 'current SusClientId -' $RegKeyValue1
    If ($ResetSusClientId -eq 1) 
    {
    Write-Host 'attempt to reset SusClientId...'
    #
    # Останавливаем на удаленном компьютере службу Windows Update
    Write-Host 'stop Windows Update service (wuauserv)...'
    [System.Reflection.Assembly]::LoadWithPartialName('system.serviceprocess')
    $wuauserv=New-Object System.ServiceProcess.ServiceController('wuauserv',$PC)
    $Stopped=$true
    If ($wuauserv.Status -ne 'Stopped') {
                Try {
                            $wuauserv.Stop()
                            $wuauserv.WaitForStatus('Stopped',(new-timespan -seconds 10))
                            }
                Catch {
                            Write-Warning 'can not stop Windows Update service (wuauserv).'
                            $Stopped=$false
                            }
    }
    #
    # Удаляем идентификационные ключи клиента Windows Update из реестра, предварительно проверив их наличие  
    If ($Stopped) {
                Write-Host 'delete Windows Update registry keys...'
                If($RegKeyValue1 -ne $null){$RegKey.DeleteValue('SusClientId')}
                $RegKeyValue2 = $RegKey.GetValue('SusClientIdValidation')
                If($RegKeyValue2 -ne $null){$RegKey.DeleteValue('SusClientIdValidation')}
                $RegKeyValue3 = $RegKey.GetValue('PingID')
                If($RegKeyValue3 -ne $null){$RegKey.DeleteValue('PingID')}
                $RegKeyValue4 = $RegKey.GetValue('AccountDomainSid')
                If($RegKeyValue4 -ne $null){$RegKey.DeleteValue('AccountDomainSid')}
                $Started=$true 
                }
    #
    # Запускаем на удаленном компьютере службу Windows Update
    Write-Host 'start Windows Update service (wuauserv)...'
    Try {
                $wuauserv.Start()
                $wuauserv.WaitForStatus('Running',(new-timespan -seconds 15))
                }
    Catch {
                Write-Warning 'can not start Windows Update service (wuauserv).'
                $Started=$false
                }
    #
    # Запускаем процедуру перерегистрации клиента Windows Update на сервере WSUS
    If ($Started) {
                Start-Sleep -Seconds 5
                Write-Host 'reset authorization of WU client...'
                $RemoteProcess=([wmiclass]"\$PCrootcimv2:Win32_Process").create('cmd /c wuauclt /resetauthorization /detectnow')
                Write-Host "running return code - $($RemoteProcess.ReturnValue), process ID - $($RemoteProcess.ProcessId)"
                }
    }
    }
    }
    Else 
    { 
    Write-Host $PC 'not available' -ForegroundColor DarkRed }
    Write-Host ''
    }                                 
    }
  • PowerShell – Поиск пользователей домена с устаревшими паролями

    В некоторых случаях может возникнуть ситуация, когда по какой либо причине в домене не работают глобальные  парольные политики безопасности. При этом, исходя из нормальных соображений поддержания должного уровня безопасности учетных данных, требуется найти всех доменных пользователей, у которых срок действия пароля больше определённого периода.

    Для этой задачи как отправную точку я использовал PS-скрипт User Counting and Password Age Checking с блога Steve Tibbetts, несколько переработав его. В частности была убрана ненужная мне в данной ситуации зависимость от командлетов Quest, добавлена возможность управления выводом отключенных учетных записей, изменён вывод  в удобоваримый вид с сортировкой по дате установки пароля, добавлена возможность установки признака смены пароля для учетных записей с «прокисшими» паролями. Вот что получилось:

    # Блок переменных

    # $LDAPPath - ADSI путь к контейнеру с доменными учетными записями пользователей (в формате LDAP://distinguishedName)

    # $CountDisabledUsers - Признак вывода сведений об отключенных учетных записях (1 или 0)

    # $PWAgeDaysLimit - Максимально возможный период действия пароля в днях

    # $PWDMustChange - Признак необходимости форсированной установки атрибута требующего смену пароля (1 или 0)

    #

    $LDAPPath = 'LDAP://OU=Domain Users,DC=mydom,DC=com'

    $CountDisabledUsers = 0

    $PWAgeDaysLimit = 90

    $PWDMustChange = 0

    #

    # Блок поиска

    #

    $RootDomainOU = [ADSI]$LDAPPath

    $Searcher = New-Object System.DirectoryServices.DirectorySearcher($RootDomainOU)

    $Filter = '(objectCategory=person)(objectClass=user)'

    If ($CountDisabledUsers -eq 0) { $Filter = $Filter + '(!(userAccountControl:1.2.840.113556.1.4.803:=2))' }

    $Filter = '(&' + $Filter + ')'

    $Searcher.Filter = $Filter

    $Searcher.PageSize = 5000

    [Void]$Searcher.PropertiesToLoad.Add("cn")

    [Void]$Searcher.PropertiesToLoad.Add("sAMAccountName")

    [Void]$Searcher.PropertiesToLoad.Add("pwdLastSet")

    $Users = $Searcher.findall()

    #

    # Блок основного вывода

    #

    $PWDays = (Get-Date).AddDays(-$PWAgeDaysLimit)

    $UsersOldPWD = $Users | Where-Object {[datetime]::FromFileTime(($_.properties.pwdlastset)[0]) -le $PWDays}

    $UsersOldPWD | Select `

    @{label='User Full Name';expression={$_.properties.cn}},`

    @{label='sAMAccountName';expression={$_.properties.samaccountname}},`

    @{label='Last Password Set';expression={[datetime]::FromFileTime(($_.properties.pwdlastset)[0])}}`

    | Sort -Property 'Last Password Set'`

    | Format-Table –AutoSize

     

    Write-Host '---------------------------------------------------'

    write-host 'Total user accounts in OU: ' $Users.Count

    write-host 'Users with passwords not changed in' $PWAgeDaysLimit 'days: ' $UsersOldPWD.Count

    Write-Host '---------------------------------------------------'

    #

    # Блок смены атрибута учетных записей

    #

    If ($PWDMustChange -eq 1) {

    Write-Host 'Set for users with old password - Change PWD at next Logon'

    If ($UsersOldPWD.Count -eq $null)

    { Write-Host 'Ops...No account needs to be changed.'}

    Else

    {

                ForEach ($User in $UsersOldPWD)

                {

                Write-Host 'Modify user:' $User.Properties.cn

                $Account=[ADSI]$User.Path

                $Account.put("pwdLastSet", 0)

                $Account.setinfo()

                }    

    }

    Write-Host '---------------------------------------------------'

    }

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

    image

  • Exchange Server 2007 – Включение почтовых ящиков для списка пользователей из файла

    Для массового включения почтовых ящиков для уже существующих в домене пользователей приготовим *.CSV файл с разделителем – запятая. В первой строке файла будут описаны заголовки значений, в последующих строках – сами значения.

    В нашем примере в качестве используемых значений будут имя пользователя в домене в формате DOMAINUser и алиас для создаваемого почтового ящика к этому имени пользователя. В обычном текстовом редакторе файл будет выглядеть так:

    DomainUser,mailAlias
    MYDOMivanov-ip,I.Ivanov
    MYDOMpetrov-sa,S.Petrov
    MYDOMsidorov-dg,D.Sidorov

    Чтобы убедиться в том, что PowerShell  действительно может разобрать наш файл по значениям выполним команду:

    Import-CSV C:Users.csv

    Результат вывода должен быть таким:

    image

    Непосредственно для импорта содержимого файла и включения на основе этих данных почтовых ящиков выполним:

    $DBId =  'MailboxServerStorageGroupDataBase'

    Import-CSV C:Users.csv | ForEach-Object { Enable-Mailbox -Identity $_.DomainUser -Alias $_.mailAlias –Database $DBId } | Get-Mailbox | Select Alias,WindowsEmailAddress

     

  • PowerShell – Сравнение включённых правил брандмауэра на двух компьютерах

    Compare Windows Firewall rules with PowerShellСтолкнулся с ситуацией, когда в разборе полётов у одного из Hyper-V серверов с включенным брандмауэром Windows Firewall потребовалось сравнить  действующие правила с другим сервером. Первое, что пришло в голову - с помощью PowerShell удалённо через вызов Invoke-Command слить правила Windows Firewall с обоих серверов в текстовые файлы и затем сравнить их содержимое.

    Читать далее...

  • PowerShell – Получение информации о локальных пользователях и группах

    Чтобы быстро получить информацию о списке локальных пользователей на удалённом компьютере можно воспользоваться подключением через PowerShell к интерфейсу WMI с запросом в одну строку:

    Get-WmiObject Win32_UserAccount -ComputerName MyPC -Filter "Domain= MyPC'"

    Тоже самое, но уже при обращении к интерфейсу ADSI:

    $computerName = "MyPC"

    $computer = [ADSI]"WinNT://$computerName,computer" 

    $computer.psbase.Children | Where-Object { $_.psbase.schemaclassname -eq 'user' } | Format-Table Name, Description -autoSize

    Если нужно получить информацию с локального компьютера в переменной $computerName укажем значение "."

    По аналогии для получения списка локальных групп безопасности удалённого компьютера используем команду:

    Get-WmiObject Win32_Group -ComputerName MyPC -Filter "Domain='MyPC'"

    ..или

    $computerName = "MyPC"

    $computer = [ADSI]"WinNT://$computerName,computer" 

    $computer.psbase.Children | Where-Object { $_.psbase.schemaclassname -eq 'group' } | Format-Table Name, Description -autoSize

    Если же мы хотим получить картину в целом по всем существующим группам безопасности и членам, входящим в эти группы используем более сложную конструкцию:

    $computerName = "MyPC"

    $computer = [ADSI]"WinNT:// $computerName,computer"

    $computer.psbase.children | where { $_.psbase.schemaClassName -eq 'group' } | foreach {

        write-host "Group:" $_.Name

        write-host "Descr:" $_.Description

        write-host "-----"

        $group =[ADSI]$_.psbase.Path

        $group.psbase.Invoke("Members") | foreach {

        $ADSIName = $_.GetType().InvokeMember("AdsPath", 'GetProperty', $null, $_, $null)

            if ($ADSIName -match "[^/]/[^/]") {

            [String]::Join("", $ADSIName.Split("/")[-2..-1])

            }

            else {

            $ADSIName.Split("/")[-1]

            }

        }

        write-host

    }

    Источники информации:

    Janel Blog - Script pour l'énumération des membres d'un groupe

    Powershellcommunity Forum - Listing local user accounts on remote machines