JASoft.org

El blog de José Manuel Alarcón Aguín. Programación web y mucho más...

MENÚ - JASoft: JM Alarcón

Direcciones MAC y cómo obtener información detallada sobre tarjetas de red con .NET.

Aparecido con la versión 2.0 de la plataforma, allá por 2005, el espacio de nombres System.Net.NetworkInformation resulta de gran utilidad a la hora de crear aplicaciones de diagnóstico de red basadas en la plataforma .NET. Gracias a las clases contenidas en éste podemos obtener información de todo tipo acerca de nuestros dispositivos de comunicaciones (tarjetas de red y otros adaptadores) de forma que resultaría fácil clonar algunas herramientas de diagnóstico del sistema operativo para adaptarlas a nuestras necesidades. En su día, ya hace muchos años, comenté lo fácil que era construir un clon de "ping.exe" para determinar el estado de un servidor remoto (si responde o no). También es sencillo responder a cambios en la conectividad con los eventos de la clase NetworkChange, como también expliqué en su momento, lo cual nos permite detectar cambios en la dirección IP o que se pierda la conexión a Internet por ejemplo.

Direcciones MAC

Ayer, para un experimento, estuve construyendo una pseudo-clon básico de la utilidad "ipConfig.exe" que viene con Windows (en concreto el resultado de ipconfig /all). En realidad la parte que me interesaba era la obtención de la dirección física de las tarjetas de red, lo que coloquialmente se denomina Dirección MAC.

Las direcciones "Media Access Control" (MAC) son las direcciones físicas de los adaptadores de red, independientes de protocolos y otros factores superiores, ya que se trata de números únicos en el mundo asociados a cada tarjeta de red y grabados físicamente en éstas por el fabricante. De modo que comprobando las direcciones MAC podemos estar seguros de que estamos en un determinado sistema o no (enseguida las salvedades a esto). Es más, generalmente todas las tarjetas de red llevan su MAC impresa en una etiqueta para que podamos verla a simple vista:

MACEnTarjeta

 

La mayoría de los routers inalámbricos del mercado permiten hacer un filtro por MAC de modo que sólo las tarjetas de red que estén en una lista de MACs concreta puedan conectarse a dicha red. Si bien esto detendrá a los script-kiddies y otros posibles atacantes con poca idea, no sirve de mucho a la hora de protegernos de verdad ya que cualquier hacker avezado puede determinar alguna MAC válida analizando el tráfico inalámbrico y falseando la dirección MAC de su tarjeta de red, el llamado "mac spoofing", algo muy fácil de hacer en todos los sistemas operativos. En las maquinas virtuales (por ejemplo en Hyper-V o Virtual Box) es muy sencillo asignar cualquier dirección MAC que elijamos a una tarjeta de red virtual, por lo que podríamos emular cualquier tarjeta de red del mundo muy fácilmente. Por ejemplo, esta es la de un Linux Fedora virtualizado que tengo bajo Virtual Box:

MACEnVirtualBox

Las MAC pueden ser utilizadas también para licenciar un software de modo que sólo pueda ejecutarse en un determinado equipo (atándolo a sus tarjetas de red). Este es el motivo, por ejemplo, de que si cambiamos de tarjeta de red en nuestro equipo tengamos que volver a activar Windows, si bien no es el único factor físico que controla el sistema de licenciamiento de Microsoft.

El código de ejemplo

A continuación dejo el código fuente de un pequeño programa que, haciendo uso del espacio de nombres NetworkInformation, muestra información sobre todos los adaptadores de red de nuestro equipo, incluyendo sus direcciones MAC:

   1: using System;
   2: using System.Net.NetworkInformation;
   3:  
   4: public class InfoTarjetasRed
   5: {
   6:     //Entrada a la aplicación de consola
   7:     public static void Main()
   8:     {
   9:         try
  10:         {
  11:             MuestraInfoTarjetasRed();
  12:         }
  13:         catch (Exception e)
  14:         {
  15:             string error = string.Format("---\nSe ha producido el siguiente error:\n{0}\n---", e.ToString());
  16:             Console.WriteLine(error);
  17:         }
  18:         finally
  19:         {
  20:             Console.Write("Pulsa cualquier tecla para continuar...");
  21:             Console.ReadKey();
  22:         }
  23:     }
  24:  
  25:     private static void MuestraInfoTarjetasRed()
  26:     {
  27:         //Obtengo el nombre del ordenador y el dominio actuales
  28:         IPGlobalProperties propsOrdenador = IPGlobalProperties.GetIPGlobalProperties();
  29:         Console.WriteLine("Información de los interfaces de red de: {0}.{1}", propsOrdenador.HostName, propsOrdenador.DomainName);
  30:         Console.WriteLine("\n\tNombre de host ...........: {0}", propsOrdenador.HostName);
  31:         
  32:         //Info de las tarjetas de red
  33:         NetworkInterface[] tarjetas = NetworkInterface.GetAllNetworkInterfaces();
  34:         if (tarjetas == null || tarjetas.Length < 1)
  35:         {
  36:             Console.WriteLine("No se han encontrado tarjetas de red");
  37:             return;
  38:         }
  39:         
  40:         //Recorremos las propiedades de cada tarjeta
  41:         foreach (NetworkInterface tarjeta in tarjetas)
  42:         {
  43:             //Nombre de la tarjeta
  44:             Console.WriteLine("\n{0}:",tarjeta.Name);
  45:             Console.WriteLine("  Descripción .............. : {0}", tarjeta.Description);
  46:             Console.WriteLine("  Tipo de interfaz ......... : {0}", tarjeta.NetworkInterfaceType);
  47:             Console.WriteLine("  Velocidad ................ : {0:n}", tarjeta.Speed);
  48:             Console.WriteLine("  Estado ................... : {0}", tarjeta.OperationalStatus);
  49:             Console.WriteLine("  Soporta Multicast ........ : {0}", tarjeta.SupportsMulticast);
  50:             Console.WriteLine("  Dirección física (MAC) ... : {0}", ObtenMACLegible(tarjeta.GetPhysicalAddress().GetAddressBytes()));
  51:             
  52:             //Propiedades de protocolos
  53:             IPInterfaceProperties propiedades = tarjeta.GetIPProperties();
  54:             //IPv6?
  55:             bool soportaIPv6 = tarjeta.Supports(NetworkInterfaceComponent.IPv6);
  56:             Console.WriteLine("  ¿Soporta IPv6? ........... : {0}", soportaIPv6);
  57:         }
  58:     }
  59:     
  60:     //Pasamos los bytes de la dirección física a Hexadecimal para mostrarlos como MAC
  61:     private static string ObtenMACLegible(byte[] bytes)
  62:     {
  63:         string MAC = "";
  64:         for(int i = 0; i< bytes.Length; i++)
  65:         {
  66:             MAC += String.Format("{0}", bytes[i].ToString("X2"));
  67:             // Se mete un guión tras cada byte excepto en el último
  68:             if (i != bytes.Length -1)
  69:             {
  70:                 MAC += ("-");
  71:             }
  72:         }
  73:         return MAC;
  74:     }
  75: }

Lo único que se hace para visualizar la MAC de un modo más legible es separar sus bytes con guiones y expresarlos en hexadecimal, que es la forma más común (método ObtenMACLegible del final).

El resultado por la consola es similar al siguiente (he cambiado las MAC por seguridad):

MACSalidaConsola

 

Te puedes descargar el código fuente y el ejecutable (InfoTarjetasRed.zip, 3.57 KB) para probarlo por tu cuenta. ¡Espero que te sea útil!

¿Este post te ha ayudado?, ¿has aprendido algo nuevo? Pues ¡ayúdame a ayudar a otros! No te costará nada y puedes conseguir premio. Es muy importante. Pulsa para saber más...
José Manuel Alarcón José Manuel Alarcón
Fundador de campusMVP.es, el proyecto de referencia en formación on-line para programadores en lengua española. Autor de varios libros y cientos de artículos. Galardonado como MVP de Microsoft desde 2004. Gallego de Vigo, amante de la ciencia y la tecnología, la música y la lectura. Ayudando a la gente en Internet desde 1996.
Descarga GRATIS mi último libro (no técnico): "Tres Monos, Diez Minutos".
Banner

Comentarios (6) -

Excellente!! ... Probando...

Responder

Gracias por el aporte, ahora a probarlo. He llegado aquí buscando hacer lo mismo, averiguar la MAC, pero de todos los equipos conectados a nuestra red, o poder saberlo a partir de la IP o nombre del Host.

Responder

Buenos días JM.

Gracias por este artículo de tu Blog. Te quería preguntar si existe alguna posibilidad de obtener la dirección MAC en el entorno Web. ¿Se puede obtener la dirección MAC de un usuario que visite una página web? Según he leído parece que no es posible porque la dirección mac no se llega a envía en la comunicación cliente - servidor.

Muchas gracias por todo y Feliz año 2014! :-)

Responder

Spain José M. Alarcón

Hola Santi,

No es posible obtener las direcciones MAC de los clientes que se conectan a tu servidor IIS. Incluso aunque crearas un filtro para IIS que actuara antes que todos los demás para pasar esa información a los siguientes niveles, no te valdría de nada ya que los diferentes routers que atraviesan los paquetes para llegar al servidor modifican la dirección MAC de origen por lo que no podrás obtenerla.

Saludos,

Responder

Muy buen ejemplo

Responder

Hola, Bien por el código funciona!!
Consulta , es posible  saber cual de las tarjetas es la que tiene conexión a Internet ?

Responder

Agregar comentario