ADSI (System.DirectoryService.DirectoryEntry) を使用して、IIS のディレクトリセキュリティ設定でIPアドレスによるアクセス制限を設定するサンプルを掲載します。最後に、VBScript を使用して、アクセス制限を設定するサンプルも掲載します。

加えて、IPアドレスとドメイン名の制限がされているディレクトリを列挙するサンプルを表示します。

確認環境

  • 動作環境:Windows Server 2003, IIS 6.0
  • 開発環境: Visual Studio 2008 Professional
  • .NET 2.0

- 参考サイト
IISのADSIリファレンス(IIS5.0ですが)
http://msdn.microsoft.com/ja-jp/library/cc338173.aspx
Setting IP Security Using ADSI(IPアドレスによる制限を行うVBScriptのサンプルが載っています)
http://msdn.microsoft.com/en-us/library/ms525526.aspx

1. SDSを使用してIISのディレクトリセキュリティを設定する

Visual Studio 2008 を起動して、コンソールアプリケーションプロジェクトを新規作成します。プロジェクトにSystem.DirectoryServices.dll の参照を追加しておきます。

System.DirectoryServices を使用してアクセス制限をして見ます。

// GetDataPaths引数の属性フラグ
private const int IIS_ANY_PROPERTY = 0;
private const int IIS_INHERITABLE_ONLY = 1;

static void Main(string[] args)
{
    // すべてのWebサイト全体に対してIPアドレスによるアクセス制限を行う
    using (DirectoryEntry webSiteRoot = GetEntry("localhost", "/W3SVC"))
    {
        SetIIsIpRestriction(webSiteRoot, false);
    }
    Console.ReadLine();
}
public static void SetIIsIpRestriction(DirectoryEntry webdir ,bool grantByDefault)
{
    object o = webdir.InvokeGet("IPSecurity");
    Type ipsecType = o.GetType();
    ipsecType.InvokeMember("GrantByDefault", BindingFlags.SetProperty | BindingFlags.Public, null, o, new object[] { grantByDefault });

    webdir.InvokeSet("IPSecurity", o);
    webdir.Invoke("SetInfo", new object[] { });
}
public static DirectoryEntry GetEntry(string server, string path)
{
    // WebサイトのルートのADSIオブジェクトのパス
    // IIS://localhost/W3SVC
    // Webサイトの識別子が1のWebサイトのADSIオブジェクトの場合は
    // IIS://localhost/W3SVC/1/Root
    // 詳細はIISのヘルプを参照
    DirectoryEntry entry = new DirectoryEntry("IIS://" + server + path);
    object o = entry.NativeObject;

    return entry;
}

プログラムでは、Type型のInvokeMemberメソッドなどリフレクションを使用してWebサーバ全体に対してディレクトリセキュリティの既定では、すべてのコンピュータからのアクセスを拒否するに設定しています。

遅延バインドがサポートされていないC#では、DirectoryEntryのみを使用するととっても大変です。IPSecurityに該当する型を ComImportAttribute を使用して定義することもできるかもしれませんが、大変だと思います。

2. サブディレクトリでIPアドレスによるセキュリティが再定義されているディレクトリを列挙する

ディレクトリセキュリティはサイトレベルやサブディレクトリレベルで定義することができます。そして、サブディレクトリに設定されたディレクトリセキュリティが優先されます。次のサンプルでは、サブディレクトリでディレクトリセキュリティが設定されているディレクトリのパスを列挙します。

static void Main(string[] args)
{
    // すべてのWebサイト全体に対してIPアドレスによるアクセス制限を行う
    using (DirectoryEntry webSiteRoot = GetEntry("localhost", "/W3SVC"))
    {
        //ListInheritedProperty(webSiteRoot);
        SetIIsIpRestriction(webSiteRoot, false);
    }
    Console.ReadLine();
}
/// <summary>
/// 引数で指定されたディレクトリ以下にIPアドレスによる制限が
/// 再定義されているADSPATHの一覧を取得する
/// </summary>
/// <param name="webdir"></param>
public static void ListInheritedProperty(DirectoryEntry webdir)
{
    string webpath = webdir.InvokeGet("ADsPath") as string;
    Regex regex = new Regex("^(IIS://).+/(W3SVC/Info/Templates)");
    object[] o = webdir.Invoke("GetDataPaths", "IPSecurity", IIS_INHERITABLE_ONLY) as object[];
    foreach (string adsPath in o)
    {
        if (adsPath == webpath)
        {
            Console.WriteLine("現在のパスに定義されています");
        }
        if (regex.IsMatch(adsPath))
        {
            Console.WriteLine("テンプレートに定義されてています。");
        }
        Console.WriteLine(adsPath);
    }
}

GetDataPaths メソッドを使用すると、引数で指定されたサイトやディレクトリ以下で特定のプロパティが定義されているパスを取得することができます。このメソッドを使用して、IPSecurityプロパティが定義されているディレクトリのADSIパスを出力しています。また、定義しているディレクトリのパスが引数で指定されたパスか、テンプレートなのかも調べています。

3.WSHでIPアドレスによるアクセス制限をする

遅延バインディングがサポートされているVBScriptで1,2 の処理を実装してみます。記事の最初に紹介しているリンクのVBScript を改良したものですが、Comオブジェクトを使用する場合にVBScript (いまはPowerShellですかね) はとっても素敵です。

'IPアドレスによるアクセス制限を設定し
'IPSecurityが定義されている子ディレクトリ
'のADSIPathを表示する

'====================
'    定数
'====================
Const IIS_ANY_PROPERTY = 0
Const IIS_INHERITABLE_ONLY = 1

Sub ListDefinedIPSecurityPath (adsiObj)
  WScript.Echo "再定義されているAdsiPath 一覧"
  pathList = adsiObj.GetDataPaths("IPSecurity" , IIS_INHERITABLE_ONLY )

  If Err.Number = 0 Then
    For Each p in pathList
        WScript.Echo p
    Next
  End If
End Sub

'--------------------------------------------------
' メイン
'--------------------------------------------------
Sub Main()
    WScript.Echo("IPアドレスによるアクセス制限開始") 
    grantByDefault = True
    adsPath = "IIS://localhost/W3SVC"
    Set IIsWebVirtualDirObj = GetObject(adsPath)
    Set IIsIPSecurityObj = IIsWebVirtualDirObj.IPSecurity

    ' 除外するIPアドレスのリスト構築
    Dim IPList(1)
    IPList(0) = "123.0.0.1,255.255.255.0"
    IPList(1) = "133.10.10.2"

    IIsIPSecurityObj.GrantByDefault = grantByDefault
    If IIsIPSecurityObj.GrantByDefault = True Then
      ' メタベースに設定を書き込む
      IIsIPSecurityObj.IPDeny = IPList 
    Else
      ' メタベースに設定を書き込む
      IIsIPSecurityObj.IPGrant = IPList 
    End If
    IIsWebVirtualDirObj.IPSecurity = IIsIPSecurityObj 
    IIsWebVirtualDirObj.Setinfo 

    WScript.Echo("IPアドレスによるアクセス制限完了") 

    ' 情報を最新にする
    IIsWebVirtualDirObj.Getinfo 

    WScript.Echo ""
    WScript.Echo("IPアドレスによるアクセス制限が設定されている子ディレクトリ列挙") 
    ListDefinedIPSecurityPath (IIsWebVirtualDirObj)

    ' 正常終了
    WScript.Quit(0)
    On Error Goto 0
End Sub

'エントリ
Main

 今回の説明は以上です。間違い、指摘点等がありましたらご連絡ください。