Anteriores entradas relacionadas:
[Análisis] Prey, software antirrobo de Código Abierto
Usando la Geolocalización MAC en nuestro favor. Parte I

Actualmente no funciona, debido a que al parecer, Google tiene deshabilitada la respuesta JSON de cuando enviamos una petición para geolocalizar

Índice:
1.-Geolocalización con un script en PHP mediante file_get_contents
2.-Geolocalización con un script en PHP mediante cURL
3.-Geolocalización a través de la shell (también usando cURL)
4.-Geolocation API Specification (W3C)

Siguiendo el hilo argumentativo del análisis que hice a Prey, hice una primera parte que quedó un poco escueta, sobre la que hablé de Geolocalización MAC. Pudimos usar un software para tratar de geolocalizar MACs, e incluso desde la página del MapXSS de Samy. Pero nos quedó pendiente una cosa: geolocalizar MACs por nuestros medios.

En esta entrada voy a tratar 4 formas distintas de geolocalizar una MAC, tres de ellas (las primeras) usando la API de Google. Dos de estas formas serán a través de scripts en PHP: uno de ellos usando cURL, y otro mediante file_get_contains. La otra forma, un tanto curiosa, será a través de la shell (en la que también necesitaremos tener cURL instalado). Con respecto a la forma que no usa la API de Google, usaremos la especificación de la W3C para geolocalizar, que está disponible en algunos navegadores.

1.-Geolocalización con un script en PHP mediante file_get_contents

Los dos primeros métodos funcionan internamente igual: hacemos una enviamos una petición JSON mediante POST, esperando recibir una respuesta que deberiamos de recibir, y posteriormente cuando la tengamos, la decodificamos y obtenemos un array con todos los valores y datos que deseamos, nuestra preciada dirección.

Antes de poner el código, una pequeña aclaración: si probamos este código en un servidor web remoto de algún hosting, es muy probable (casi 100%) de que no funcione. Esto tendriamos que probarlo en nuestro propio servidor PHP. Esto es debido a que los hostings deshabilitan (o deberian) la función file_get_contents por una vulnerabilidad que se encontró en la misma.

Aquí dejo el código explicado:

<?php
//Nuestra MAC, la que queramos localizar
$mac = "xx-xx-xx-xx-xx-xx";      
 
//Preparamos los datos que enviaremos mediante JSON                                                              
$datos = '{
    "version": "1.1.0",
    "request_address":"true",
    "wifi_towers": [{
        "mac_address": "' . $mac . '"
    }]
}';
 
$datos_completos = array(
  'http'=>array(
    'method' => "POST",
    'header'  => 'Content-type: application/x-www-form-urlencoded',
    'content' => $datos
  )
);
 
//Utilizamos file_get_contents para hacer la petición a la API de Google
$respuesta = file_get_contents(
    'http://www.google.com/loc/json',
    false,
    stream_context_create($datos_completos)
);
 
//Decodificamos lo que nos devuelve
$respuesta = json_decode($respuesta, true);
 
//Obtenemos los resultados
echo "<b>Direccion Geografica aproximada</b>:<br>";
 
foreach($respuesta['location']['address'] as $clave => $valor)
   echo $clave . ": " . $valor . "<br>";
 
echo "<b>Coordenadas aproximadas</b>:<br>";
echo "Latitud: " . $respuesta['location']['latitude'] . "<br>Longitud: " . $respuesta['location']['longitude']; 
?>

A continuación escribiré una estructura de tipo árbol de los datos que nos devuelve Google tras este envio, ya que nos devuelve una matriz multidimensional, y viene bien saber el contenido de esta:


$respuesta (Array)

>access_token
>location: Array
|-->latitude
|-->longitude
|-->accuracy
|-->address: Array
|---|-->country
|---|-->country_code
|---|-->region
|---|-->country
|---|-->city
|---|-->street
|---|-->postal_code

2.-Geolocalización con un script en PHP mediante cURL

Aquí si ponemos el mismo código que enviamos en el script anterior, no nos funciona, así que tendremos que modificar la petición como veremos a continuación de una manera todavía más sencilla. Además de eso, tendriamos que cambiar la parte de file_get_contents por el cURL. Este código si que deberia de funcionarnos en un servidor remoto, y digo deberia porque yo no lo he conseguido, solo he conseguido que me aparezca el robot de Google tan mono advirtiéndome de un error “temporal” que no tengo ni idea de porqué puede ser… Pero vamos, que en nuestro servidor casero si que funciona.

Aquí el código:

 
//Datos que enviaremos
$datos_completos = '{version:"1.1.0",request_address:true,wifi_towers:[{mac_address:"xx-xx-xx-xx-xx-xx"}]}';
 
//Iniciamos cURL
$ch = curl_init();
//Configuramos cURL
curl_setopt($ch, CURLOPT_POST, 1); 
curl_setopt($ch, CURLOPT_POSTFIELDS, $datos_completos);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 
curl_setopt($ch, CURLOPT_URL,'www.google.com/loc/json'); 
 
$respuesta = curl_exec($ch);
curl_close($ch);
 
//Obtenemos la respuesta y posteriormente la decodificamos
$respuesta = json_decode($respuesta, true);
 
//Para terminar, printeamos los resultados
echo "<b>Direccion Geografica aproximada</b>:<br>";
 
foreach($respuesta['location']['address'] as $clave => $valor)
   echo $clave . ": " . $valor . "<br>";
 
echo "<b>Coordenadas aproximadas</b>:<br>";
echo "Latitud: " . $respuesta['location']['latitude'] . "<br>Longitud: " . $respuesta['location']['longitude'];

Esto nos devolverá exáctamente el mismo resultado que el anterior script.

3.-Geolocalización a través de la shell (también usando cURL)

Ya por último, acabaremos esta entrada geolocalizando de la forma más sencilla, a través de la shell, en la que solo tenemos que escribirlo y lo recibimos inmediatamente, como veremos en la siguiente imagen.

Usaremos el comando de cURL, por lo que propiamente es hacer lo mismo que en el segundo apartado, pero con la shell:


curl -d '{version:1.1.0,request_address:true,wifi_towers:[{mac_address:xx-xx-xx-xx-xx-xx}]}' www.google.com/loc/json

4.-Geolocation API Specification (W3C)

Para los que usamos twitter, esta especificación no nos deberia de parecer nueva, ya que desde hace tiempo tenemos la opción de añadir desde donde twitteamos usando este método.

A continuación, el código que nos permite esto:

<html>
<head>
<script type="text/javascript" src="http://code.google.com/intl/es-ES/apis/gears/gears_init.js"></script>
<script type="text/javascript">
 
function mostrar(posicion) {
  var latitud = posicion.coords.latitude;
  var longitud = posicion.coords.longitude;
  //Nos muestra las coordenadas
  alert("Latitud : " + latitud + " Longitud: " + longitud);
}
 
function obtenerLocalizacion(){
 
   if(navigator.geolocation){
	   //Si está disponible, llama a la función para mostrar las coordenadas
      navigator.geolocation.getCurrentPosition(mostrar);
   }else{
      alert("Este navegador no soporta la Geolocalización de la W3C");
   }
}
 
 
</script>
</head>
 
<body onLoad="obtenerLocalizacion()">
 
</body>
</html>

Tras ejecutarlo en Firefox por ejemplo, nos saldrá un aviso de si queremos compartir nuestra localización, que igual a alguno le suena haber visto anteriormente:

Y nos saldrá esto:

A veces no me funciona, igual es que tiene algún límite de peticiones por tiempo (como algunas APIs). Lo curioso (y bueno) del asunto, es que si analizamos con Wireshark los datos, podemos ver que pasan por SSL.

Para terminar con este apartado, decir que en el siguiente enlace disponemos más detalladamente datos relativos al uso de esta Geolocation API.

Saludos, lipman