Sunteți pe pagina 1din 5

DESARROLLO • Perl: Scripting

Evitamos las molestas páginas de bienvenida WiFi

APROBADO

RÁPIDO

Un script en Perl ahorra a los usuarios la molesta tarea de pulsar en las páginas de bienvenida del proveedor de WiFi, acepta automáticamente los términos de uso y permite acceder lo más rápido posible sin un navegador. POR MICHAEL SCHILLI

48 Número 72

A ntes de que los hoteles, cibercafés o aeropuertos dejen que los nuevos usuarios acce-

dan a sus redes WiFi, redirigen las peticiones del navegador (Figura 1), haciendo que

sus potenciales clientes tengan primero que lidiar con una página de bienvenida

(Figura 2). Al llegar a esa página, lo que se ve son términos de uso sin fin – que nadie lee de todos modos – casillas de verificación que tenemos que habilitar, anuncios o las tres cosas. Los proveedores de WiFi configuran estas páginas de bienvenida como obstáculos que les permiten centralizar el registro de direcciones MAC del cliente en la red WiFi y recordar al usuario sus obligaciones como inter- nauta ejemplar. Una vez que hemos pasado por todas estas etapas obli- gatorias, el punto de acceso baja su puente levadizo y nos da el acceso web y la capacidad de abrir conexiones TCP arbitrarias a Internet (Figura 3).

Sin Web No Hay Acceso

En algunos casos, los usuarios ni siquiera quieren acceder a la web, sino que sólo desean abrir un túnel SSH. Luego, con un terminal abierto y el navegador cerrado, se sor- prenden de que se les asigne una dirección IP, aunque el cortafuegos, obviamente, está bloqueando el acceso a Internet. El script Perl splash descrito en este artículo ayuda a los usuarios con este dilema colándose a tra- vés de los formularios web que se encuentran entre el usuario con muchas ganas de empezar y el acceso pleno a Internet. Para ello, splash pulsa en todos los enlaces, activa todas las casillas, acepta todas las coo- kies y las envía gentilmente de regreso al proveedor de WiFi, que piensa que se trata de un ser humano real y vivo que está utilizando su navegador para toda esta comunica- ción.

utilizando su navegador para toda esta comunica- ción. Figura 1: El usuario ha solicitado google.com, pero

Figura 1: El usuario ha solicitado google.com, pero previamente la red WiFi lo lleva a la página de bienvenida del proveedor.

WWW.LINUX - MAGAZINE.ES

Perl: Scripting • DESARROLLO

Perl: Scripting • DESARROLLO Figura 2: El WiFi del hotel redirige la primera petición del navegador

Figura 2: El WiFi del hotel redirige la primera petición del navegador a una página de bienvenida.

petición del navegador a una página de bien v e nida. Figura 3: Los usuarios simplemente

Figura 3: Los usuarios simplemente tienen que pulsar para acceder a los términos de usuario, y podrán navegar durante 24 horas.

Tácticas de Plugin Flexibles

Pero, ¿cómo puede un sencillo script mane- jar lo que podrían ser miles de configuracio- nes diferentes de páginas de bienvenida? Los proveedores de WiFi podrían crear comple- jas formas o incluso utilizar su artillería pesada como animaciones Flash o JavaScript para defenderse de los scripts automáticos. Para contrarrestar esto, el script confía en una estrategia de plugin que permite al usua- rio, o a un tercero, modificarlo para controlar los nuevos métodos. Cada plugin prueba su propio enfoque para flanquear la página de bienvenida. Por ejemplo, el plugin ClickAllLinks.pm se hace camino pulsando en todos los enlaces de la página, mientras que CheckBoxFill.pm

 

Listado 1:

SplashJumper.pm

01

############################

02

package SplashJumper;

03

############################

04

# Mike Schilli, 2010

05

# (m@perlmeister.com)

06

use strict;

07

use warnings;

08

use Module::Pluggable

09

require => 1;

10

11

sub new {

12

bless {}, shift;

13

}

14

15

1;

habilita todas las casillas de verificación que aparecen en el primer formulario web antes de pulsar el botón enviar. Los usuarios sólo tienen que añadir nuevos plugins en el direc- torio de plugins, a continuación el script los recoge automáticamente, sin necesidad de ninguna configuración, y lo intenta con ellos como una nueva táctica. Cada vez que un plugin completa su eje- cución, el script Splash hace una petición a http:// www. google. com para ver si real- mente devuelve la página web o si aparece otra página de bienvenida en el camino. Si el

intento de acceso no se realiza correcta- mente, el script lo intenta con el siguiente plugin. De lo contrario, nos devuelve un mensaje de éxito y finaliza.

Abajo con el Muro

La Figura 4 muestra cómo reacciona el script si la conexión de red no está activa porque el usuario no ha seleccionado ninguna de las redes WiFi disponibles o no ha introducido la contraseña WPA. Mientras las peticiones a Google devuelvan errores, o se congelen durante más de cinco segundos, el script se

 

Listado 2: ClickAllLinks.pm

01

#############################

20

02

package SplashJumper::Plugin::

21

for

ClickAllLinks;

22

my $link ($mech->links())

03

#############################

23

{

04

# Mike Schilli, 2010

24

05

# (m@perlmeister.com)

25

INFO “Clicking on “,

06

#############################

26

$link->url();

07

use Log::Log4perl qw(:easy);

27

my $resp =

08

28

$mech->get($link);

09

#############################

29

10

sub register {

30

INFO “Got “,

11

#############################

31

length($resp->content()),

12

return “click-all-links”,

32

“ bytes back”;

13

10;

33

14

}

34

$mech->back();

15

35

}

16

#############################

36

}

17

sub process {

37

18

#############################

38 1;

19

my ($self, $mech) = @_;

WWW.LINUX - MAGAZINE.ES

Número 72

49

DESARROLLO • Perl: Scripting

DESARROLLO • Perl: Scripting Figura 4: Si la conexión de red está desactivada, el script intenta

Figura 4: Si la conexión de red está desactivada, el script intenta alcanzar el servidor de Google a intervalos de 5 segundos.

toma un breve descanso y luego lo intenta de nuevo. Una vez que el cliente tiene una dirección IP y las peticiones web al menos muestran la página de bienvenida, el script lanza un plugin tras otro en la pared artificial (Figura 5) hasta que finalmente la derrumba. El Listado 1 muestra la clase de base Splas- hJumper para todos los plugins, la cual sim- plemente define un constructor. Tira del módulo Module::Pluggable de CPAN y le pasa el parámetro require => 1. El módulo comprueba entonces el subdirectorio Splas- hJumper/Plugin en busca de los archivos .pm, ejecuta una instrucción require, y los carga en el script activo.

El Mejor Primero

El Listado 2 muestra un típico plugin con el módulo ClickAllLinks. Cuando se carga el script principal del plugin, llama al método register(), que devuelve el nombre de la tác- tica actual y un número de prioridad. El script principal ordena los plugins numérica- mente en base a los números de prioridad que reporta, llamando a los plugins con menor valor en primer lugar. Esto significa que los plugins pueden decidir entre ellos quién va primero. Para reducir el tiempo de

entre ellos quién va primero. Para reducir el tiempo de Figura 5: Si el script encuentra

Figura 5: Si el script encuentra una página de bienvenida, aplica pri- mero el método click-all-links.

de objetos WWW::Mechanize::Link y utiliza un bucle for para iterar sobre la lista. La fun- ción INFO, importada de los tesoros de Log4perl, le indica al usuario curioso qué enlace está pulsando actualmente el plugin. El método get() del simulador de navegador ejecuta a continuación la petición web.

Mecanizar con Autocheck

El control explícito de errores no se realiza aquí porque WWW:: Mechanize se ejecuta en modo autocheck de forma predetermi- nada. Genera una excepción por cada error que encuentra, y el bloque eval{} agrupado alrededor de la llamada al plugin en el script principal (véase el Listado 4, línea 81) los agrupa antes de que el programa principal pase a gestionar el error. En la línea 30 (Listado 2), el plugin utiliza

a continuación la instrucción INFO para indi- car el número de bytes devueltos al pulsar el enlace, y el método back() en la línea 34 pulsa el botón Atrás del navegador virtual para volver a la página de bienvenida. El plugin CheckBoxFill del Listado 3 uti- liza un enfoque diferente. Busca a través del archivo HTML de la página de bienvenida con el objetivo de encontrar el primer formu- lario de la web y luego utiliza la instrucción form_number(1) para configurarla como current_form. El método find_input() extrae todos los campos de entrada de tipo “casilla

de verificación” del formulario, y el bucle for de las líneas 27-29 los selecciona a todos lla- mando a sus métodos check(). La línea 32 llama entonces a submit_form() para enviar

el formulario web de vuelta al servidor, antes

de que la línea 34 vuelva a la página de bien- venida para asegurarse de que el próximo plugin encuentra las condiciones de partida normales. Este método hace posible controlar páginas de bienvenida como las que se muestran en las Figuras 6 y 7, las cuales requieren que el usuario marque una casilla de verificación y luego pulse un botón que envía el formulario.

ejecución, lo lógico es ejecutar los plu- gins con mayores oportunidades de

éxito en primer lugar. Los dos plugins que veremos aquí definen prioridades de 10 y 50, respectivamente, de modo que el script siempre probará Clic- AllLinks primero antes de aplicar la táctica que Check- BoxFill muestra en el Listado 3. Cuando se ejecuta un plugin de contra- ataque a la página de bienvenida, el script llama a su método process() y le pasa el simulador de navegador $mech, un objeto de la clase WWW::Mechanize. Este módulo CPAN es perfecto para capturar páginas web, analizar su contenido y profundizar en sus enlaces. A menudo se utiliza para imple- mentar screen scrapers, ya que proporciona más o menos un conjunto completo de fun- cionalidades del navegador (excepto el código JavaScript o plugins de Flash), acepta cookies automáticamente, y los devuelve al servidor. En el plugin Click-AllLinks, el método links() identifica todos los enlaces de la página de bienvenida recuperados en forma

 

Listado 3: CheckBoxFill.pm

01 #############################

19

02 package SplashJumper::Plugin::

20

$mech->form_number(1);

CheckBoxFill;

21

03

#############################

22

my @inputs =

04

# Mike Schilli, 2010

23

$mech->current_form

05

# (m@perlmeister.com)

24

->find_input(undef,

06

#############################

25

“checkbox”);

07

use Log::Log4perl qw(:easy);

26

08

27

for my $input (@inputs) {

09

#############################

28

$input->check();

10

sub register {

29

}

11

#############################

30

12

return “checkbox-fill”, 50;

31

INFO “Submitting form 1”;

13

}

32

$mech->submit_form(

14

33

form_number => 1);

15

#############################

34

$mech->back();

16

sub process {

35

}

17

#############################

36

18

my ($self, $mech) = @_;

37 1;

50 Número 72

WWW.LINUX - MAGAZINE.ES

El Listado 4 finalmente muestra el pro- grama principal, Splash. Empieza por defi- nir en la línea 13 la URL de prueba, que el script recupera para descubrir si la conexión a Internet está activa. La página de Google es perfecta para esto, porque es ligera y es muy probable que esté disponible en una conexión a Internet que funcione. La línea 16 inicializa el entorno de trabajo Log4perl en el nivel DEBUG para dar al usuario infor- mación detallada sobre el plugin en ejecu- ción en ese momento y las acciones que está llevando a cabo en el navegador virtual. Gracias a la utilización de Module::Plug- gable, los objetos de la clase de base Splash- Jumper disponen de un método plugins() que devuelve una lista de todos los plugins instalados en el subdirectorio de Plugin. La línea 28 comprueba si cada plugin propor- ciona un método register(), como se requiere, y omite plugins no implementados correctamente, devolviendo un mensaje de error en este sentido al mismo tiempo. Los plugins correctamente implementa- dos devuelven sus tácticas como $algo en la línea 35 y su prioridad numérica preferida en la variable $order. El script empaqueta la

Perl: Scripting • DESARROLLO

información que encuentra en una matriz y empuja una referencia al final de la matriz @ways. La línea 44 ordena los ele- mentos de esta matriz numérica- mente por el campo order, de manera que un plugin con una prioridad de 10 ejecuciones se ejecuta antes (before) que un

plugin con una prioridad de 50. El simulador de navegador WWW::Mechanize establece su tiempo de espera a cinco segundos en la línea 50. Esto significa que el bloque del bucle de las líneas 53 a 62 sólo se congela en el método get() durante cinco segundos antes de darse por vencido, durmiendo durante cinco segundos , y a continuación vuelve a inten-

durante cinco segundos , y a continuación vuelve a inten- Figura 6: La red WiFi del

Figura 6: La red WiFi del aeropuerto de San Diego requiere que el usua- rio marque una casilla de verificación y entonces envía el formulario web.

tar acceder al servidor de Google. Al final del bloque, que Perl repite ejecutando un redo, al menos la red local WiFi está funcio- nando y al cliente se le asigna una dirección IP válida. Sin embargo, el proveedor de WiFi aún podría haber encaminado las peti- ciones a www.google.com a un servidor interno que produce la página de bienve- nida.

podría haber encaminado las peti- ciones a www.google.com a un servidor interno que produce la página

DESARROLLO • Perl: Scripting

DESARROLLO • Perl: Scripting Figur a 6: La r ed W iFi del aer o puer

Figura 6: La red WiFi del aeropuerto de San Diego requiere que el usuario marque una casilla de verificación y entonces envía el formulario web.

error que se pro- duzca en el plu- gin, y la línea 88 comprueba la variable $@ para ver si ha suce- dido algo.

Instalación

Para asegurarnos

El bucle for de las líneas 65 a 95 intenta burlar la página de bienvenida con una gran variedad de plugins, y una vez que la URL de la última solicitud es igual a la URL de prueba (es decir, no se redirige a la página de bienvenida), la línea 72 decide que la página de bienvenida ha sido derrotada y la cone- xión a Internet está abierta. Si no es este el caso, la línea 85 llama al método process() para el próximo plugin en línea con igual o mayor prioridad. El bloque eval{} de las líneas 81 a 86 atrapa cualquier

para el próximo plugin en línea con igual o mayor prioridad. El bloque eval{} de las
para el próximo plugin en línea con igual o mayor prioridad. El bloque eval{} de las
para el próximo plugin en línea con igual o mayor prioridad. El bloque eval{} de las

de que el script encuentra el módulo SplashJumper, éste deberá estar instalado en la ruta de la bús- queda del script %INC: la forma más sencilla de hacerlo es poner los dos en el mismo directorio. Los plugins se almacenan en el recién creado subdirectorio SplashJumper/Plugin, de modo que el diseño del archivo se parece a esto:

splash

SplashJumper.pm

SplashJumper/Plugin/U

ClickAllLinks.pm

SplashJumper/Plugin/U

CheckBoxFill.pm

Algunos plugins adicionales podrían contro- lar múltiples formularios web, o incluso sor- tear los trucos de JavaScript. También nece- sitan almacenarse en el directorio Plugin. Su método register() tiene que asignar un nom- bre para la táctica, y decide una prioridad para definir el orden en que se ejecutará.

Después de abrir la tapa de su portátil en el aeropuerto, sólo tiene que lanzar el script splash. Su salida nos indica cómo lucha nuestro guerrero de bolsillo en su nuevo entorno y si logra vencer esos obstáculos

artificiales.

RECURSOS

[1] Listados de este artículo: http:// www.linux-magazine.es/Magazine/

Downloads/72

 

Listado 4: Splash

01

#!/usr/local/bin/perl -w

33

}

65

for my $ways (@ways) {

02

#############################

34

66

eval { $mech->get($url); };

03

# splash - Traverse WiFi

35

my ($algo, $order) =

67

04

#

Splash Pages

36

$plugin->register();

68

my $current_url =

05

# Mike Schilli, 2010

37

69

$mech->response->request

06

# (m@perlmeister.com)

38

push @ways,

70

->uri;

07

#############################

39

[ $algo, $plugin,

71

08

use strict;

40

$order ];

72

if ($current_url eq $url) {

09

use SplashJumper;

41

}

73

INFO “Link is up.”;

10

use WWW::Mechanize;

42

74

last;

11

use Log::Log4perl qw(:easy);

43

# sort by plugin priority

75

} else {

12

44

@ways = sort {

76

INFO “Link still down”;

13

my $url =

45

$a->[2] <=> $b->[2]

77

}

14

“http://www.google.com”;

46

} @ways;

78

15

47

79

my ($algo, $plugin, $order)

16

Log::Log4perl->easy_init(

48

my $mech =

80

= @$ways;

17

$DEBUG);

49

WWW::Mechanize->new();

81

18

50

$mech->timeout(5);

82

eval {

19

my $sj = SplashJumper->new();

51

83

INFO “Processing splash “,

20

52

# wait until network is up

84

“page $current_url “,

21

my @ways = ();

53

{

85

“with algo $algo”;

22

54

INFO “Trying $url”;

86

$plugin->process($mech);

23

for

55

eval { $mech->get($url); };

87

};

24

my $plugin ($sj->plugins())

56

if ($@) {

88

25

{

57

INFO

89

if ($@) {

26

58

“Connection down, retrying”;

90

ERROR

27

if (

59

sleep 5;

91

“Algo $algo failed ($@)”;

28

!$plugin->can(“register”))

60

redo;

92

} else {

29

{

61

}

93

INFO

30

ERROR “$plugin can’t do”,

62

}

94

“Plugin $algo succeeded”;

31

“ register()”;

63

95

}

32

next;

64

# try to get past splash page

96

}

52 Número 72

WWW.LINUX - MAGAZINE.ES