[转载]动态封杀与解封IP (转) – greatqn – 博客园.
我们在应对网站的恶意请求时候,一个解决方法就是把有问题的请求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