Malditos spammers, esto es una guerra o ¿Cómo cortar el acceso a tu IIS desde una IP mediante programación?
Una larvada, oculta y desconocida guerra, para mi mucho más importante que la de Afganistan o la de Iraq, me mantiene regularmente ocupado. Es la lucha contra los comentarios de spam en Geeks.ms. La verdad es que si no me lo tomase como un hobby, como una extraña partida de ajedrez, como un juego de inteligencia, una arcana lucha entre el bien y el mal… ya tendría una ulcera de estomago de tanto cargarme el la p**a madre de los p**os spammers.
La guerra ha tenido diferentes batallas como todas las guerras que se precien. Y también algunos daños colaterales, ninguno de gravedad extrema gracias a Dios, como usuarios que no han podido acceder a su sitio favorito, o autores que no han podido publicar o han sido banneados del sitio, e incluso algún comentario perdido en la onda expansiva de algún script un poco desviado de su objetivo.
Hemos jugado numerosas partidas los spammers y yo. De momento, dado que el sitio no está totalmente tomado por el spam pese a sus intentos y que nunca he tenido quejas sobre este tema, creo que voy ganando. Aunque por poco: solo puedo actuar reactivamente y evitar que los comentarios de spam perduren. Aunque este en si mismo es una victoria, el simple hecho de hacer ver que el sitio está defendido, hace que los spammers mas perezosos abandones sus ataques y dirijan sus esfuerzos hacia otros sitios más vulnerables.
En esta batalla, he usado y uso numerosas armas. Durante un tiempo tuvimos captchas por todos los lados, los viejos del lugar lo recordarán, luego solo comentarios de usuarios autenticados (algo que odio, pues creo que Geeks.ms debe ser lo más abierto y accesible posible para los usuarios licitos), luego incluso tuve que capar el registro de usuarios con mail de determinados dominios de correo…
Lo interesante del tema es el continuo toma y dada. Ellos intentan algo, yo lo detecto e implemento una medida de protección. Rara vez comento de manera explicita estas medidas en el blog, algunas de ellas curiosas, por razones obvias de no dar información al enemigo. Aunque de manera clara, mi particular guerra ha inspirado algún que otro post, como por ejemplo: Protegerse de las inyecciones de SQL por URL, fruto de una de las más cruentas batallas libradas en esta guerra.
Hoy os vengo a contar una medida que he usado durante mucho tiempo, pero que ha caído en desuso. Ya digo que lo que ayer les funcionaba a los spammers hoy no les funciona y viceversa. Ahora este mecanismo ya no sirve ya que los spammers, que serán unos cabr*nes pero no gilip*yas del todo, spoofean sistemáticamente la IP. Pero quizás vosotros si que lo podáis sacar partido para para ataques que podáis sufrir en vuestro sitio o en otras situaciones.
Durante mucho tiempo, los muy capullos, no cayeron en la cuenta de que, cuando un bot se ponía a inyectar comentarios yo podía evitar que lo volviese a hacer con el simple mecanismo de bannear su IP. Como Community Server me permite de manera simple saber que comentarios se habían considerado spam y la IP origen del comentario, yo banneaba la IP que había creado los comentarios y borraba los comentarios recientes de esa IP. Alguna vez alguien perdió un comentario y se quedo fuera de Geeks.ms un tiempo por culpa de este mecanismo, daños colaterales, ya digo, inevitables en toda batalla.
Bueno dejando las batallas del abuelo cebolleta vamos a dar el toque técnico que el título del post promete: ¿Cómo cortar el acceso a tu IIS a una IP mediante programación?. Pues con esta simple función que usa el modelo de objetos de IIS por WMI.
/// <summary>
/// Ban an IP from IIS
/// </summary>
/// <param name="IP">IP to ban</param>
/// <param name="siteIdentifier">IIS site identifier</param>
private void IISBanIP(string IP, string siteIdentifier)
{
try
{
//Get the directory entry for the root of the IIS server
DirectoryEntry IIS =
new DirectoryEntry(
@"IIS://localhost/w3svc/" + siteIdentifier + "/root");
//Get the IPSecurity property
Type type = IIS.Properties["IPSecurity"][0].GetType();
object IPSecurity = IIS.Properties["IPSecurity"][0];
//Get the IPDeny list from the IPSecurity object
Array oldIPDenyList = (Array)type.InvokeMember("IPDeny",
BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.GetProperty,
null, IPSecurity, null);
List<object> newIPDenyList = new List<object>(oldIPDenyList.Length);
foreach (object ip in oldIPDenyList)
newIPDenyList.Add(ip);
newIPDenyList.Add(IP + ", 255.255.255.255");
//Add the updated list to the IPSecurity object
type.InvokeMember("IPDeny",
BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.SetProperty,
null, IPSecurity, new object[] { newIPDenyList.ToArray() });
IIS.Properties["IPSecurity"][0] = IPSecurity;
//Save changes
IIS.CommitChanges();
IIS.RefreshCache();
ShowMessage("IP {0} was banned", IP);
}
catch (Exception e)
{
ShowMessage("Error banning IP: {0} Error:{1}", IP, e.InnerException.Message);
}
}
Os preguntaréis como protejo ahora Geeks.ms… el día que los sepáis será por que un spammer lo ha averiguado antes ;).
¡Ojala os sirva! Contra el spammer ¡Aur, aur... Desperta ferro!.