我们在应对网站的恶意请求时候,一个解决方法就是把有问题的请求IP封杀掉。
如果想快速处理这种问题,就需要编写一段代码,达到一定门槛,自动封杀。再复杂点就是不是永久封杀,还可以自动在一定时间后解封。
封杀的逻辑代码看后面提供的。
需要说明的是:IIS7时,情况发生了不同。
下面的代码,在处理封杀IP时候,不论IIS6还是IIS7 都可以把需要封杀的IP加入封杀列表。但是需要注意的是我们代码写的是全部替换原先的数据。但是在IIS7下,执行的效果是原先的不替换,新加一批封杀IP。当然IIS7下,如果新加的IP原来就有了,则会报如下异常:
System.Runtime.InteropServices.COMException was caught
Message="当文件已存在时,无法创建该文件。 (异常来自 HRESULT:0x800700B7)"
Source="System.DirectoryServices"
ErrorCode=-2147024713
StackTrace:
在 System.DirectoryServices.DirectoryEntry.CommitChanges()
在 IIS_Security_ConsoleApplication.Program.IPDeny() 位置 D:\MyCodes\IIS_Security_ConsoleApplication\IIS_Security_ConsoleApplication\Program.cs:行号 109
InnerException:
这就是说,IIS7, 我们可以通过编程接口增加封杀IP名单,但是没发通过编程接口剔出封杀IP。
参考代码:
这里提供了两套参考代码,其实原理都是一样的。
在IIS 6 下,都没有任何问题, IIS 7 下都会有没发删除原先已有数据的问题。
代码一:
using System.DirectoryServices;
using System.Reflection;
using System;
class Program
{
static void IPDeny()
{
try
{
string serverName = "localhost";
// retrieve the directory entry for the root of the IIS server
System.DirectoryServices.DirectoryEntry IIS = new System.DirectoryServices.DirectoryEntry(
string.Format("IIS://{0}/w3svc/1/root", serverName));
// retrieve the list of currently denied IPs
Console.WriteLine("Retrieving the list of currently denied IPs.");
// get the IPSecurity property
Type typ = IIS.Properties["IPSecurity"][0].GetType();
object IPSecurity = IIS.Properties["IPSecurity"][0];
// retrieve the IPDeny list from the IPSecurity object
Array origIPDenyList = (Array)typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public
| BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null);
// 罗列已经被拒绝的地址
foreach (string s in origIPDenyList)
Console.WriteLine("Before: " + s);
// check GrantByDefault. This has to be set to true,
// or what we are doing will not work.
bool bGrantByDefault = (bool)typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public
| BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null);
Console.WriteLine("GrantByDefault = " + bGrantByDefault);
if (!bGrantByDefault)
{
// 必须设置 默认允许访问
typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] { true });
}
// 更新被拒绝的IP列表
// 注意这里是完全替换
// 如果你想保留原先的拒绝列表,需要原先的拒绝列表也在这个数组中
Console.WriteLine("Updating the list of denied IPs.");
object[] newIPDenyList = new object[4];
newIPDenyList[0] = "192.168.1.21, 255.255.255.255";
newIPDenyList[1] = "192.168.1.22, 255.255.255.255";
newIPDenyList[2] = "192.168.1.23, 255.255.255.255";
newIPDenyList[3] = "192.168.1.24, 255.255.255.255";
Console.WriteLine("Calling SetProperty");
// add the updated list back to the IPSecurity object
typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] { newIPDenyList });
IIS.Properties["IPSecurity"][0] = IPSecurity;
Console.WriteLine("Commiting the changes.");
// commit the changes
IIS.CommitChanges();
IIS.RefreshCache();
// 检查更新后的数据
Console.WriteLine("Checking to see if the update took.");
IPSecurity = IIS.Properties["IPSecurity"][0];
Array y = (Array)typ.InvokeMember("IPDeny",
BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
| BindingFlags.GetProperty, null, IPSecurity, null);
foreach (string s in y)
Console.WriteLine("After: " + s);
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.ToString());
}
}
}
代码二:
using System.DirectoryServices;
using System.Reflection;
using System;
static void SetIPSecurityProperty(string metabasePath, string member, string item)
{
// metabasePath is of the form "IIS://<servername>/<path>"
// for example "IIS://localhost/SMTPSVC/1"
// member is of the form "IPGrant|IPDeny|DomainGrant|DomainDeny"
// item is of the form "<ipaddress|domain>", for example, 157.56.236.15 or domain.microsoft.com
Console.WriteLine("\nEnumerating the IPSecurity property at {0}:", metabasePath);
try
{
if (("IPGrant" != member) && ("IPDeny" != member) && ("DomainGrant" != member) && ("DomainDeny" != member))
{
Console.WriteLine(" Failed in SetIPSecurityProperty; second param must be one of IPGrant|IPDeny|DomainGrant|DomainDeny");
}
else
{
DirectoryEntry path = new DirectoryEntry(metabasePath);
path.RefreshCache();
object ipsecObj = path.Invoke("Get", new string[] { "IPSecurity" });
Type t = ipsecObj.GetType();
Array data = (Array)t.InvokeMember(member, BindingFlags.GetProperty, null, ipsecObj, null);
Console.WriteLine(" Old {0} =", member);
bool exists = false;
foreach (object dataItem in data)
{
Console.WriteLine(" {0}", dataItem.ToString());
if (dataItem.ToString().StartsWith(item))
{
exists = true;
}
}
if (exists)
{
Console.WriteLine(" {0} already exists in {1}", item, member);
}
else
{
object[] newData = new object[data.Length + 1];
data.CopyTo(newData, 0);
newData.SetValue(item, data.Length);
t.InvokeMember(member, BindingFlags.SetProperty, null, ipsecObj, new object[] { newData });
path.Invoke("Put", new object[] { "IPSecurity", ipsecObj });
path.CommitChanges();
path.RefreshCache();
ipsecObj = path.Invoke("Get", new string[] { "IPSecurity" });
data = (Array)t.InvokeMember(member, BindingFlags.GetProperty, null, ipsecObj, null);
Console.WriteLine(" New {0} =", member);
foreach (object dataItem in data)
Console.WriteLine(" {0}", dataItem.ToString());
Console.WriteLine(" Done.");
}
}
}
catch (Exception ex)
{
if ("HRESULT 0x80005006" == ex.Message)
Console.WriteLine(" Property IPSecurity does not exist at {0}", metabasePath);
else
Console.WriteLine("Failed in SetIPSecurityProperty with the following exception: \n{0}", ex.Message);
}
}
static void Main(string[] args)
{
// 获取目前服务器上有哪些站点
DirectoryEntry root = new DirectoryEntry("IIS://localhost/W3SVC");
foreach (DirectoryEntry dir in root.Children)
{
if (dir.SchemaClassName == "IIsWebServer")
{
string ww = dir.Properties["ServerComment"].Value.ToString();
Console.Write("IIS://localhost/W3SVC/{0}/ROOT/ {1}\r\n", dir.Name, ww);
}
}
// IPDeny();
SetIPSecurityProperty("IIS://localhost/w3svc/1/root", "IPDeny", "192.168.5.79");
Console.ReadLine();
}
参考资料:
Blocking IIS IP Addresses with ASP.NET
http://www.west-wind.com/WebLog/posts/59731.aspx
How to Programmatically add IP Addresses to IIS's Deny Access List
http://www.codeproject.com/KB/security/iiswmi.aspx
HOWTO: 通过 IP 地址或域名称限制站点访问
http://support.microsoft.com/default.aspx/kb/324066
使用ADSI来操作IIS的路径
http://blog.joycode.com/ghj/archive/2004/06/08/24047.aspx
Setting IP Security Using System.DirectoryServices
http://www.cnblogs.com/drw/articles/17951.html
如何通过WEB方式,来控制iis的禁用IP名单。
http://blog.joycode.com/ghj/archive/2004/06/08/24075.aspx
Setting IP Security Using System.DirectoryServices
http://msdn.microsoft.com/en-us/library/ms524322(VS.85).aspx
how to automate adding denied IPs for IIS
IIS 7.0: Configure IPv4 Address and Domain Name Allow Rules
http://technet2.microsoft.com/windowsserver2008/en/library/d0de9475-0439-4ec1-8337-2bcedacd15c71033.mspx?mfr=true