Windows ファイヤーウォールを使用してWindows Azureインスタンスでアクセス制限を実施する方法

Windows Azureにデプロイしたアプリに、特定のIPからのみ接続できるようにアクセス制限をする必要がある場合、Windowsファイヤーウォールの設定をプログラム的に変更することて対応できます。スタートアップ時と(Windows Azureゲストエージェントがファイヤーウォールの設定を戻してしまうので)ロールの変更時に設定する必要があります。

アクセス制限をしたい理由

Windows AzureにPaaSクラウドサースをデプロイすると、インターネット上にデプロイされます。
これは、インターネット上で誰でもアクセスできることを意味します(アプリケーションの認証ロジックがあるかもしれませんが)。
通常は、これは問題にはなりません。アプリを構築しデプロイすれば使用できるようになるからです。
しかし、特定マシンからのみ接続できるようにアクセス制限をしたいことがあります。

  • 未リリースで、準備が整うまでは非公開にしたいアプリケーション。
  • 複数の異なる環境のデプロイ(開発、テスト用など)があって、アプリケーションの認証ロジックを変更せずに許可された人だけがアクセスできるようにしたい
  • アプリケーションがインターナルユーザーのみ使用することを想定して設計されており、リモートから接続を許可したくない。この場合は、個別ユーザー認証のためアイデンティティソリューションを使用すべきです。
  • RDPや別のポートで運用している管理画面のような管理サービスに追加のセキュリティを施したい場合。

IISの「IPアドレスおよびドメインの制限」では不十分?

IIS干すテッドサービスへのトラフィックのみをブロックすることに興味がある場合、
IISの「IPアドレスおよびドメインの制限」機能が選択肢の一つになります
(詳細は、Liam CavanaghのBlog参照)。デフォルトではインストールされていないので、「IPアドレスおよびドメインの制限(IP and Domain Restrictions)」昨日をセットアップスクリプトをでインストールする必要があります。

この解決策では、RDPなどのIIS以外の接続も制限したい場合不十分です。

Windows Firewallでのアクセス制限

この場合、Windows Azure VMのローカルで動作しているWindows Firewallの設定を変更してあげる必要があります。通常、特定IPアドレスとポートからのみアクセスを許可するように設定するのは簡単です。

ここでは、Windows Server 2012、Windows Azure osFamilyの3で動作する、Netowork Security PowerShellコマンドレットを使用して、80と3389の2つのポートへの接続を特定IPからのみ許可する設定例を提示します。

# SetFirewallRestrictions.ps1
$date = Get-Date
Write-Host "Updating firewall rule restrictions at " $date "`r`n"
$allowedRanges = ('3.2.1.0/24', '1.2.3.4') 
Get-NetFirewallPortFilter | ? LocalPort -eq '80' | Get-NetFirewallRule | Set-NetFirewallRule -RemoteAddress $allowedRanges
Get-NetFirewallPortFilter | ? LocalPort -eq '3389' | Get-NetFirewallRule | Set-NetFirewallRule -RemoteAddress $allowedRanges

このスクリプトが呼び出されてたときログを出力するように.cmdファイルでラップします。

rem SetFirewallRestrictions.cmd
cd /d %~dp0
Powershell set-executionpolicy remotesigned -force
Powershell .\SetFirewallRestrictions.ps1 >> SetFirewallRestrictions.out.log 2>> SetFirewallRestrictions.err.log

スタートアップタスクで呼び出されるように、ServiceDefinition.csdefファイルを設定します。セキュリティ設定を昇格するように<Runtime>エレメントで設定します。

<ServiceDefinition name="FirewallTest" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2013-03.2.0">
  <WebRole name="WebRole1" vmsize="Small">
   ...  
    <Startup>
      <Task commandLine="Startup\SetFirewallRestrictions.cmd" executionContext="elevated" taskType="simple" />
    </Startup>
    <Runtime executionContext="elevated" />
  </WebRole>
</ServiceDefinition>

スタートアップタスクを設定すると、Windows Azureは自動的にファイヤーウォールの設定を更新し、IP制限を設定しインスタンスを起動します。ロースをスケールさせると、Windows Azure Gesut Agentは、Windows Firewallの設定を再作成します。IP制限を継続するには、ロールのトポロジーが変わった際に、スクリプトを再適用する必要があります。

アプリケーションがスケールしたときに、ファイヤーウォールルールを再適用するために、RoleEntryPointクラスで、RoleEnvironment.Changedイベントを使用します。

public class WebRole : RoleEntryPoint
{
    public override bool OnStart()
    {
        RoleEnvironment.Changed += RoleEnvironment_Changed;
        return base.OnStart();
    }

    void RoleEnvironment_Changed(object sender, RoleEnvironmentChangedEventArgs e)
    {
        if (e.Changes.Any(ch => ch is RoleEnvironmentTopologyChange))
        {
            var processStartInfo = new ProcessStartInfo(@"Startup\SetFirewallRestrictions.cmd");
            var process = Process.Start(processStartInfo);
        }
    }
}

元記事

MSDNブログ:Using Windows Firewall to restrict access to Windows Azure instances