web.configをPowerShellから変更する

Exchange Server 2013/2016では、これまでのバージョンと同じく細かいカスタマイズを行う場合やバグフィックスの為にweb.confgを直接書き換えるというシーンが比較的あります。

例)
クライアント固有のメッセージのサイズ制限を構成する
MSExchangeApplicationLogic Event 3018 in Exchange Server 2013
Exchange Server 2013 doesn’t display all OUs when it creates a new mailbox
Using security groups to set calendar permissions does not work in an Exchange resource forest

しかしながら、こちらのファイルはCUを適用する度にデフォルトの状態にリセットされます。CUは基本的に四半期に一度リリースされますので、3か月に一度設定がクリアされるという形になります。

毎回メモ帳などを利用して書き戻すというのも運用上の負担になりますし、作業漏れやミスによって障害が引き起こされる可能性もあるので、今回はその変更作業をPowerShellを利用して行いたいと思います。

web.configは中身はXMLドキュメントになりますので、Get-Contentした物を[XML]キャストすればPowerShellから普通に扱えます。例えば、KB2882961対策でOWAのweb.configのAppSettingsの欄に<add key=”UseDisabledAccount” value=”1″ />を加えたい場合、以下の様に行います。

$webConfig = "C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa\web.config"
$AppSetKey = "UseDisabledAccount"
$AppSetValue = "1"
$doc = [XML](Get-Content $webConfig)
$newAppSetting = $doc.CreateElement("add")
$doc.configuration.appSettings.AppendChild($newAppSetting)
$newAppSetting.SetAttribute("key",$AppSetKey);
$newAppSetting.SetAttribute("value",$AppSetValue);
$doc.Save($webConfig)

同様に、AppSettings以外のsystem.webなどの項目も書き換えられます。例えば、ActiveSyncの最大送受信サイズを20MBにするためにCASのweb.configの既存のmaxRequestLengthを書き換える場合は、

$webConfig = "C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\sync\web.config"
$ObjKey = "maxRequestLength"
$NewValue = "20480"
$doc = [XML](Get-Content $webConfig)
$obj = $doc.configuration."system.web".httpRuntime.$ObjKey
if ($obj -ne $null) {
  $doc.configuration."system.web".httpRuntime.$ObjKey = $NewValue
  $doc.Save($webConfig)
} else {
  Write-Host "$ObjKey not found"
}

こんな感じです。(既存の値を変更するので、既存の値の存在チェックを入れています)

なお、同様に既存のweb.configの設定内容を確認することもできますので、書き戻しが必要かどうかチェックする際にも利用することが可能です。色々ご自分の環境に合わせてお試しいただくと良いかと思います。

Microsoft MVPを再受賞しました

おかげさまで、MicrosoftのMVPアワードをOffice Servers and Servicesの分野で受賞しました。
2012年にOffice 365で初受賞して以来、5年連続での受賞となります。

これも偏にblogやコミュニティ運営などでご協力を頂いている皆さまの応援のおかげと感謝しております。

これからもよろしくお願い致します。

MVP_Logo_Horizontal_Secondary_Blue286_RGB_300ppi

Exchange 2013/2016の更新失敗時の対応

Exchange Server 2013 / 2016の累積更新プログラム(CU)を初めとする更新プログラムの適用においては、インストール開始時にExchange関連のサービスが停止されるのみならず、自動起動の状態が「無効」として設定されます。
20160719_01

これにより、インストール中に故障が発生してOS再起動した場合などにおいても、更新が中途半端になされた状態でExchange Serverが立ち上がって全体の動作に悪影響を及ぼすなどの事が無いように設計されております。

反面、これも万能ではなく、意図せずサービスが無効化された状態のままインストーラーが終了(しかも再開ができない)してしまうケースが比較的に多く存在します。再現性は無いのですが、以下私が遭遇したケースです。

  • インストーラーが異常終了してしまった
  • 途中でハードウェア障害でOSが再起動した
  • 厳密な名前の検証を無効化せずに中間更新プログラム(IU)を適用した
  • SCCM経由で他の更新プログラムと一緒にExchangeの更新プログラムをインストールした

正常に動作しているサーバーのサービスの状態と見比べながら戻すのが一番単純な方法ですが、特に時間に追われているメンテナンス作業などの場合は途方に暮れることになってしまいます。

こうしたケースにおいて覚えておいた方が良いコマンドがあるので紹介します。

① PowerShellを管理者モードで開く
② インストールディレクトリのBin(C:\Program Files\Microsoft\Exchange Server\V15\Bin)に移動
③ .\ServiceControl.ps1 AfterPatch

更新プログラム適用の処理において、実際にはどういった処理がされているかは C:\ExchangeSetupLogs\ExchangeSetup.log にも詳細が記録されておりますので、そちらを参考にしても良いかと思います。

Exchange2013のマルウェア対策をProxy経由で更新

インターネットへの直接接続が無い環境でのExchange 2013組み込みのマルウェア対策のパターンファイル更新についてメモ。

Exchange Server 2010の頃のFPE(Forefront Protection for Exchange)はGUIで設定できる項目があったのですが、Exchange Server 2013では標準に組み込まれて、Exchange管理シェル(EMS)からも設定することができません。

winhttpで設定することもできるのですが、意外とBypass-listを書くのが面倒だったりするので、FPEの頃のようにパターンファイル更新のみ特定のProxyサーバ経由で実行するように設定できます。

  1. http://forefrontdl.microsoft.com/server/scanengineupdate に対して、認証なしで接続できるようにProxyサーバを設定
  2. PowerShellを管理者として開いて以下のコマンドを実行する
Add-PSSnapin Microsoft.Forefront.Filtering.Management.PowerShell
Set-ProxySettings -Enabled $true -Server [ProxyサーバのIP] -Port [Proxyサーバのポート]

しばらく待てば更新が開始されます。即時で実行したい場合は、以下のコマンドで。

cd 'c:\Program Files\Microsoft\Exchange Server\v15\scripts\'
.\Update-MalwareFilteringServer.ps1 -Identity [対象のExchangeサーバのFQDN]

【登壇情報】6/25 Cloud Samurai 2016

6/25(土)に日本Microsoft品川本社で行われるInteract x Cloud Samurai 2016 Summerに登壇させて頂く事になりました。

タイトルは【オンプレミス x Exchange Server 2016 という選択肢】ということで、Exchange Onlineではなくサーバ製品であるExchange Server 2016について話をさせて頂きたいと思います。

Microsoft_Exchange_2016[1]

Exchange Serverってそれなりにまだ出ているみたいだけど、普段なかなか勉強会で話を聴く機会がないよね…って話がありまして、誰も喋らないのであればじゃあ私が、ということで枠を頂きました。

内容としてはまだこれから考えていくのですが、なるべく具体的に、実際に役に立つ内容となるようにしたいと思ってます。今考えてる(というか、自分が聴きたい内容なのですが)トピックは、以下の感じです。全部喋れるかわかりませんが…。こういった事が聴きたいとかのリクエストもあれば是非御連絡下さい。

  • Exchange Onlineとはどういった違いがあるの?
  • 実際作るとどういったH/W構成になるの?
  • 構築や運用で気をつけるべき所とかあるの?
  • 価格はどれくらい?
  • 2010とか2013とどう違うの?

お時間が許すようであればご参加頂ければ幸いです。

 

ARRからのアクセスでSchannel 36871

Forefront TMGがサポート切れとなり、Microsoftが提供しているIISモジュールであるARR(Application Request Routing)を利用してExchange ServerのOWAやActiveSyncなどをインターネットに公開されている方も多いかと思います。

ある特定の環境下でARRを利用していると、ある時からARR上にSchannel 36871(内部エラー:10013)が記録され続け、そのままアクセスできない状態が続くことがあります。
20160501_02

10013のエラーコード自体は、サーバ側から返された利用可能な暗号化スイートの一覧にクライアント側で対応した物が無いという物なのですが、Schannelの設定はARRのクライアント側もExchangeのCASのサーバ側も同じに設定していますし、そもそも通常時は利用できているのでそういったことは無いのではと推測しました。

色々と検証したところ、以下のような事が分かって来ました。

  • 発生する環境は、SSL3.0を無効化した環境
  • 発生するタイミングは接続先のCASが起動してきたタイミング
  • ヘルスチェックを有効化している環境もしくは、アクセスが多いタイミングで発生する可能性が高い
  • 一度発生すると出続ける

以上のことから、Exchange Server側でIISが立ち上がりきる前にARRからアクセスし、TCPセッションの確立自体は成功したものの、その後のSSL通信の確立に失敗した為に発生。かつARRは都度セッションを張るのでは無く、一度張ったセッションを再利用し続ける仕様の為に発生している可能性が高いと思われます。

こちらを解消するためには、ARR側のOSを再起動しても勿論直りますが、一番簡単なのはARRのアプリケーションプールをリサイクルすることにより、完全に立ち上がったCASに対してセッションを張り直して貰うことです。

あとは、これを自動的に事象発生時に実行して貰うように、以下の様なスクリプトを作成してタスクスケジューラでイベントログをトリガーにして起動すれば自動的に復旧してくれます。
20160501_03

Import-Module WebAdministration
$SysDate = Get-Date -Format "yyyy/MM/dd HH:mm:ss"
$HostName = hostname

"$SysDate $HostName ARR Recovery Script Start" | Out-File C:\scripts\recovery_arr\recovery_arr.log -encoding default -append
$site = "Default Web Site"
$pool = (Get-Item "IIS:\Sites\$site"| Select-Object applicationPool).applicationPool
Restart-WebAppPool $pool
sleep 300

$SysDate=Get-Date -Format "yyyy/MM/dd HH:mm:ss"
"$SysDate $HostName ARR Recovery Script End" | Out-File C:\scripts\recovery_arr\recovery_arr.log -encoding default -append

このイベントログは発生すると大量に出続けるので、同時起動を無しに設定し、スクリプト中で5分間のwaitを入れていますが、この値は環境により調整して下さい。WebアプリケーションプールはDefault Web Siteのみの想定です。別の発生要因により直らなかった場合はアラートを出すなどの処理を加えても良いかもしれません。

Exchange 2013 CU12の管理シェルの変更点

先日の投稿の続編です。

Exchange Server 2013 CU11から、Exchange管理シェルの接続先が自身のメールボックスのサーバに変更になった旨告知がありました。

その後ですが、CU12の公開に合わせて以下のような告知がありました。

Exchange 2013 CU12 および Exchange 2016 でのリモート PowerShell のプロキシ転送時の処理

しかし、CU11 に実装された変更により、オンプレミス環境のリモート PowerShell では予想外の問題が複数発生しました。これらの問題について詳細にコードを見直した結果、CU11 に実装された変更を取り消し、Exchange 2013 CU12 のリリース時に従来のサーバー バージョンによるルーティングを使用するように戻すことになりました。

Oh, 色々とスクリプトを修正していたのですが…。

まあ、Microsoft側も速い判断で良かったと思います。ということで、CU12以降を入れれば元通りということになりました。

 

Exchange 2013 CU11の管理シェルの変更点

昨年末ごろから、Exchange 2013の管理系の自作スクリプトが失敗する様になったという話を色々な所で耳にするようになりました。

Exchange Server 2013のコンソールからExchange管理シェルのプログラムを起動すると、黄色い字で「○○○(サーバ名)に接続しています/接続しました」と表示されます。

ただ、実際には別のサーバに接続しているケースがあります。例えば、下のスクリーンショットではmbxcas02ではなくmbxcas01に接続していることが、Get-ExchangeCertificateコマンドレットの実行結果からお分かり頂けると思います。
20160411_01

これは、Exchange Server 2013のCU 11から実装されたExchange管理シェル(EMS)の仕様変更に依るものです。

Exchange 管理シェルとメールボックスのアンカー設定

簡単に説明すると、今まではExchange管理シェルは接続した先のサーバにそのまま接続されていましたが、Exchange 2013 CU11からはCAS(クライアントアクセスサーバ)に接続した場合自分のメールボックスの存在するメールボックスサーバ(メールボックスを持たないアカウントの場合は調停メールボックスの存在するサーバ)に接続するようになりました。
20160411_02

なので、ローカルサーバへのオペレーションだと思って実行しているコマンドは違うサーバに対して実行されてしまうことがあります。接続先のサーバが異なるADサイトに存在をしている場合、AD情報の同期タイミングも考慮しなければいけません。

なお、CASの役割がインストールされていないサーバ(メールボックスのみやエッジトランスポートサーバ)の場合は影響ありません。

基本的な対処策としては、例えば Get-ExchangeCertificate であればGet-ExchangeCertificate -Server (hostname)などとして、明示的に実行先のサーバを指定するようにするという形になります。

いままで通りでやりたい場合は、PowerShellを管理者権限で立ち上げたあと、

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn

と実行すれば今までと同じ感覚で利用できますので、私なんかは.ps1スクリプトにしてデスクトップに置いておいてます。

Exchange 2010でドメインコントローラに接続できない

Exchange Server 2010で、ある日突然CASやメールボックスサーバがMSExchange ADAccessの2130,2102,2103など、いずれもドメインコントローラに接続できない旨のエラーが出てサービスが利用できなくなる事があります。
20151028_05

事象自体はOS再起動をすると治るのですが、たまに発生する割には、出る環境と出ない環境が決まっていて変だなと思って調査をしたのでそのメモを。

まず、この事象に陥ってもRDPでサーバに接続できます。でも、なぜかドメインコントローラに接続ができない、詳しく言うと、ドメインコントローラの名前解決のDNSに失敗します。nslookupでDNSサーバに接続しようとしても接続できません。
20151028_06

もっと調べると、この状態ですがTCPやICMPの通信には影響を及ぼさない(なのでRDP接続はできる)のですが、UDPでのみ通信ができないという状態だということが分かりました。

ここで、セッションの状態を見てみようとnetstat -anoを打ってみます。20151028_08 20151028_01

と、延々と続くUDPの待ち受けポート。どうやらこいつが原因のようです。TCPの動的ポート枯渇というのは497日問題で良く聞いた話ですが、UDPにも動的ポートがあります。どうやらこれが枯渇しているようです。
20151028_04

netstatの結果より調べたプロセスを特定します。タスクマネージャーを開き、必要に応じて更に列の選択でコマンドラインを表示させます。(w3wp.exeの場合、ワーカープロセスの特定に使います)
20151028_09

こちら場合によっていくつかケースがあるのですが、多くの場合はCASはOWAかExchangeServicesのIISのワーカープロセス、メールボックス(特にパブリックフォルダを有している)の場合はRPC Client Accessが多いです。
20151028_02

サービスの再起動か、ワーカープロセスの場合はIISマネージャーから、被疑アプリケーションプールのリサイクルを実施します。
20151028_03

これでしばらく待つとMSExchange ADAccessが自動的にドメインコントローラを見つけてくれ、動作が再開します。

 

そもそもの原因なのですが、どうやら上記を初めとする一部のExchangeアプリケーションが全ドメインコントローラに接続できないタイミングで、そのアプリケーションでリークが発生。UDPの動的ポートが掴みっぱなしになり、そのポートが徐々に溜まっていき、16000超の領域を全部埋め尽くすと、今回の様な事象になるようです。

確かに、検証環境でADが1台しかなかったり、複数台有ってもメンテナンスの時などに一定時間(例えば15分)とか開けずに1台目のドメインコントローラが上がってきたタイミングですぐに2台目を再起動するなどの運用をしている環境でたまに発生していました。

特に直す気配も無さそうなので、対策としては

  1. 常時最低1台はMSExchange ADAccessからドメインコントローラに接続できているようにする
  2. UDPの動的ポートの数を増やす
  3. UDPのポート数を監視(1万くらいになったら対象プロセスを再起動)

とかになりますね。

DuplicateDeliverによる配信不可

Exchange Serverでは、以前のバージョンより同じメールが複数届いた場合に最初の1通のみ受信し、残りのメールを重複として削除するシングルインスタンス機能が備わっています。Exchange Server 2013においても同機能が備わっております。

重複と検出判断されたメールは、メッセージ追跡ログを見ると、2通目以降のメールには Source STOREDRIVER EventId DUPLICATEDELIVER が記録され、メールボックスには最初の1通だけ配送されます。
20150311_01

、同一のメッセージと見なされる条件は以下の通りです。

  • 同一のMessageIDヘッダであること
  • 同一のDateヘッダであること
  • 同一のメールボックスへの配送であること

参照:How does duplicate detection work? / Exchange 2007 で重複するメッセージを検出する方法

この機能自体は、ユーザー側のメールを読む負荷を軽減すると共に、メールのループ防止などの意味で重要な役割を担っているのですが、一定のケースで2通目以降のメールを受け取りたい場合があります。例えば、

  1. ウィルスが誤検知されて添付ファイルが削除されたメールをアンチウィルスソフトから再送する場合
  2. ユーザが誤って削除して復元できなくなったメールをジャーナルアーカイブから再送する場合
  3. システム上の制約で同じMessageIDで送信してくるメールを受信する場合
  4. Toに自身のアドレスが、Ccにメーリングリストが入っていて、メーリングリスト毎にフォルダ分けしている場合

などです。Exchange Server 2007/2010では、デフォルトで1時間の間このメッセージの重複を検知します。また、情報自体は7日間保存しております。この時間を変更する際には、レジストリの HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MSExchangeIS\<Server_Name>\Private-<GUID>\ 配下のDeliveredTo Expiration in Hours や DeliveredTo Cleanup Interval in Seconds を変更する事により変更することが可能でした。

ところが、Exchange Server 2013においては、検証する限りでこの設定が変更になっているようで、今までデフォルトでは1時間待てば配送されていた物が、7日間配送されないようになっておりました。また、今まで設定していたレジストリを設定してみても動作は変わりません

Microsoftのサポートに問い合わせて調査したところ、Exchange Server 2013 CU7現在、上記設定は7日にハードコーディングされており変更できなくなっているとのことでした。

Exchange Serverは、基本的にExchange Onlineと同じコードがベースになっているという話を聞いたことがあるので、Online側でカスタマイズ不可としてハードコーディングされているのであれば、それも考えられるかなとは思う反面、今までとデフォルト値を変更した上に設定変更も不可…というのはちょっと厳しいかなとも感じております。

最近、Exchange Onlineの挙動を見る限りでは、重複検出期間が24時間に仕様が変更になったっぽいので、オンプレも今後のCU8やそれ以降で挙動が変更にならないかどうか注視していきたいと思います。

関連記事: 重複メッセージの除去(Exchange Online)