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