一剑飞虹

道可道非常道,名可名非常名
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

动态封杀与解封IP (转)

Posted on 2008-05-09 10:22  greatqn  阅读(491)  评论(0编辑  收藏  举报

我们在应对网站的恶意请求时候,一个解决方法就是把有问题的请求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

http://www.nukeforums.com/forums/viewtopic.php?p=54746&highlight=&sid=1176c746e2037ed24acac86dd53ca747

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