Curso NMAP
Curso NMAP
Curso NMAP
Función Socket
Sintaxis
La invocación a la función Socket retorna un valor distinto de cero si la ejecución fue exitosa, ó cero
en caso de que haya ocurrido un error.
Ejemplo
$pf_inet = PF_INET();
$sock_stream = SOCK_STREAM();
$numero_protocolo = getprotobyname("TCP");
$estado=socket(SOCKET, $PF_INET, $SOCK_STREAM, $numero_protocolo);
if ($estado != 0) { print ("Error en creación de socket!") }
else { print ("Socket creado!") }
Función Bind
Sintaxis
Ejemplo
$numero_puerto = 7593;
$direccion = pack("Sna4x8", 2, $numero_puerto, $direccion_ip);
bind (SOCKET, $direccion);
La invocación a la función Bind retorna un valor distinto de cero si la ejecución fue exitosa, ó cero en
caso de que haya ocurrido un error.
La dirección de red de un host puede ser obtenida por medio de la función gethostbyname(), que
utiliza como argumento el nombre mnemónico del host en cuenstión.
Ejemplo
$numero_puerto = 7593;
($d1,$d2,$d3,$d4,$dirección_ip)= gethostbyname("www.unlu.edu.ar");
$direccion = pack("Sna4x8", 2, $numero_puerto, $direccion_ip);
bind (SOCKET, $direccion);
Ejemplo
$numero_puerto = 7593;
while (getservbyport($numero_puerto, "tcp")
{
$numero_puerto++
}
($d1,$d2,$d3,$d4,$dirección_ip) = gethostbyname("www.unlu.edu.ar");
$direccion = pack("Sna4x8", 2, $numero_puerto, $direccion_ip);
bind (SOCKET, $direccion);
Función connect
Sintaxis
Ejemplo
listen (SOCKET, 5)
La invocación a la función connect retorna un valor distinto de cero si la ejecución fue exitosa, ó cero
en caso de que haya ocurrido un error.
Función listen
A partir de un socket creado, esta función lo pasa a estado de apertura pasiva (ó modo escucha). Si
se trabaja sobre un transporte orientado a la conexión, se espera por conexiones entrantes. En caso
sobre transporte no orientado a la conexión, se espera por datagramas entrantes.
Sintaxis
Ejemplo
listen (SOCKET, 5)
La invocación a la función Listen retorna un valor distinto de cero si la ejecución fue exitosa, ó cero
en caso de que haya ocurrido un error.
Función accept
Esta función espera hasta que un proceso solicite conexión y -una vez conectado- retorna la
dirección de este.
Sintaxis
Ejemplo
#################################################
#!/usr/bin/perl
use Socket;
$server = "www.unlu.edu.ar";
$port = 80;
# Establecimiento de conexión
$server_addr =(gethostbyname($server));
$server_struct = pack("S n a4 x8", AF_INET, $port, $server_addr);
$proto = (getprotobyname('tcp'));
# cierre de conexión
close(MISOCK);
#################################################
El módulo utilizado “Socket” contiene la definición de una serie de constantes utilizadas en el código
anterior. En las variables $server y $port se hallan la dirección de red -en formato nemónico- y el
puerto del servicio al que se quiere acceder.
Una estructura de datos (en formato C) es creada con la función pack, la cual contiene la constante
AF_INET (extraida del módulo Socket) que indica el tipo de dirección de red a utilizar (en este caso
protocolo internet), $port y $server_addr que son datos propios del equipo a conectar.
La función socket() permite crear sockets, donde en nuestro caso, MISOCK es un descriptor, PF_INET
la constante que indica que se utilizará protocolo de red de internet, SOCK_STREAM que el transporte
será orientado a la conexión y $proto contiene el código de protocolo de transporte a utilizar (en el
ejemplo TCP).
Una vez que el socket ha sido creado se procederá a realizar una conexión con el servicio remoto (en
nuestro caso con www.unlu.edu.ar puerto 80), para lo cual se utiliza la función connect() que lleva
por parámetros: el descriptor del socket local (MISOCK), y la estructura creada que contiene datos
del hosts que brindará servicio (en nuestro caso $server_struct).
Una vez establecida la conexión se dispone de una canal bidireccional confiable para el intercambio
de datos entre el equipo local y el equipo remoto que brinda servicio. Utilizando el descriptor de
socket (MISOCK) se pueden realizar operaciones de lectura (recepción de datos) y escritura (envio de
datos). Las dos primeras líneas se utilizan a los efectos de deshabilitar operaciones de buffer, dado
que se trabajará con mensajes cortos no es necesario contar con buffers. La función select()
selecciona por defecto un canal de salida (siempre se inicia con STDOUT por defecto) y asignando un
valor distinto de cero a la variable $| se desactivan las operaciones de buffer sobre tal canal. A
continuación se volvio a seleccionar el canal de salida por defecto y se envió al socket el mensaje
HTTP “GET /” (recuperar la página web establecida por defecto). Mientras la conexión siga
establecida se leeran datos enviados por el servidor web (recordar que un servidor web luego de
enviar un archivo cierra su conexión). Un cierre de conexión realizado por el servidor es interpretado
como el evento fin de archivo por parte del cliente.
#################################################
#!/usr/bin/perl
use Socket;
$este_host = 'localhost';
$port = 4000;
# Atendiendo clientes
for (;;) {
$host_remoto = accept(NUEVOSOCK, SSOCK);
die "Error en operación accept(): $!\n" unless ($remote_host);
#
# Aquí se situa el código específico del protocolo de aplicación
#
close(NUEVOSOCK);
}
#################################################
Este programa define un proceso servidor bajo protocolo TCP que atenderá por conexiones entrantes
en el puerto 4000. Los comentarios del ejemplo anterior se puede observar que rigen para el
presente código. Se arma una estructura que contiene la dirección local y luego se crea un socket
con descriptor SSOCK.
Accept() espera por una conexión entrante, en caso de no existir en la cola, espera hasta que se
detecte una. Cuando accept detecte una conexión se crea un nuevo socket que la identifica, en el
ejemplo se utiliza el descriptor NUEVOSOCK para su referencia, toda la escritura y lectura se realiza a
través de NUEVOSOCK. Accept retorna una estructura que contiene la dirección del equipo remoto,
la estructura instanciada es igual a la definida en la variable $server_struct, para desempaquetarla
se utiliza la función unpack() de la siguiente forma:
use Socket;
$docroot = '/home/florge';
$this_host = 'localhost';
$port = 4000;
# Cierre de conexión
close(NEWSOCK);
}
#################################################
Fork es utilizado para que cuando se detecte una conexión entrante (por medio de accept) se invoke
a fork para generar un proceso hijo que la atienda y paralelamente seguir esperando por nuevas
conexiones.
En el ejemplo siguiente si luego de ejecutar al función fork se obtiene un cero (se está en presencia
del proceso hijo) se sale de la estructura for {(last unless(fork())} y en caso de ser el padre se cierra
el socket y se continua atendiendo nuevas conexiones entrantes.
for ( ;; )
{
$remote_host = accept(NEWSOCK, SOCK);
die "accept() error: $!\n" unless ($remote_host);
# Si fork devuelve <> 0 soy el padre e ire a atender nuevas conexiones,
# de lo contrario (fork devolvio 0) soy el hijo y saldré del for
last unless (fork());
close(NEWSOCK);
}
# He descubierto (sin ayuda de terapia) que soy el hijo
# de aquí en más continua el código a ejecutar como hijo
Existe una notificación al padre por parte del proceso hijo, informándole que ha finalizado su
ejecución. Se realiza mediante el uso de la interfaz de señales. SIGCHLD es la señal que recibe el
padre informando tal evento y ademas debe dar acuse de recibo (si el hijo no lo recibe queda en un
estado denominado zombie). La forma para que un programa responda a tal señal es a través de la
siguiente instrucción $SIG{"CHLD"} = "IGNORE"; la cual se instancia en la apertura de todo
programa que utilize la función fork.
Agregando seguridad
Es necesario restringir el acceso solamente al directorio ($docroot) donde se almacenan las páginas
webs. Para ello se puede utilizar la función chroot() la cual convierte a un directorio pasado como
argumento en la raiz del sistema de archivos de un proceso determinado.
#################################################
#!/usr/bin/perl
use Socket;
$SIG{"CHLD"} = "IGNORE";
$docroot = '/home/florge/html';
$this_host = 'localhost';
$port = 4000;
$user = "nobody";
# Set up socket
#
$proto = (getprotobyname("tcp"))[2];
socket(SOCK, PF_INET, SOCK_STREAM, $proto) ||
die "Failed to initialize socket: $!\n";
# *** If we've fallen out of the loop, then we're the child. ***
# All done
#
close(NEWSOCK);
#################################################
El módulo IO::Socket – Condensado de [http://perlnet.sander.tsx.org].
IO::Socket es una interface que posibilita que scripts Perl puedan acceder a servicios de red
operando bajo protocolo TCP/IP. La creación de un socket se realiza invocando a una función
constructor de la clase IO::Socket::INET, donde retornará un descriptor asociado. En el siguiente
ejemplo se crea un socket:
use IO::Socket;
$socket = IO::Socket::INET->new(Proto=>"tcp",
LocalPort=>"3322",
Listen=>1)
or die "Error en apertura de socket \n";
El siguiente programa ejemplifica el uso de funciones de red con la finalidad de recuperar un archivo
HTML de un servidor HTTP:
#################################################
#!/usr/bin/perl
use IO::Socket;
$socket = IO::Socket::INET->new(Proto=>"tcp",
PeerAddr=>$host,
PeerPort=>"80",
Reuse=>1)
or die "Error en conexion\n";
# buffering off
# $socket->autoflush(1);
# Solicitar recurso
print $socket "GET $documento HTTP/1.0\n\n";
# Recepcion del documento
while (<$socket>) { print }
close $socket;
#################################################
#################################################
#!/usr/bin/perl
use IO::Socket;
$mi_socket = IO::Socket::INET->new(Proto=>"tcp",
LocalPort=>"2244",
Listen=>1)
or die "No se puede abrir socket\n";
#################################################
#!/usr/bin/perl
use IO::Socket;
use Time::localtime;
$server = IO::Socket::INET->new(Proto=>"tcp",
LocalPort=>$port,
Listen=>$maxconn,
Reuse=>1)
or die "Error en creacion de socket\n";
$client->autoflush(1);
# Analisis del requerimiento
@header = split(' ', <$client>);
$url = $header[1]; $httpver = $header[2];
}
close $server;
#################################################
Puede resultar útil verificar periodicamente por el estado de una conexión. La función defined
permite realizar tal acción y determinar si el vínculo sigue activo o se ha roto. El ejemplo siguiente
deterrmina tal estado cada 10 segundos.
#################################################
#!/usr/bin/perl
use IO::Socket;
while (defined($socket)) {
print "Conexión Activa !!!\n";
sleep(5);
}
El módulo IO::Select
#################################################
#!/usr/bin/perl
use IO::Socket;
# include the select package
use IO::Select;
$max_clients = 10;
$port = 1234;
$new_client = IO::Socket::INET->new(Proto=>"tcp", LocalPort=>$port, Listen=>$max_clients,
Reuse=>1);
# create a new selection and add our basic socket for incoming connections
$sel = IO::Select->new($new_client);
Definición de alarmas
Es posible que bajo ciertas cirunstancias (por ejemplo: exigencia de un protocolo) sea necesario
establecer una alarma (timer). El descriptor ALRM es necesario definir como primer paso, luego,
utilizando la función alarm se controla la duración máxima. El ejemplo que sigue muestra una
implementación de la función alarm:
#################################################
#!/usr/bin/perl
use IO::Socket;
close $conexion;
#################################################
El módulo IO::Socket permite operar con el protocolo de transporte UDP. Los métodos send y recv
permiten enviar y recibir datagramas. Los ejemplos siguientes ilustran un cliente y un servidor que
utilizan protocolo UDP
cliente UDP
#################################################
#!/usr/bin/perl
use IO::Socket;
$socket = IO::Socket::INET->new (Proto => 'udp',
PeerPort => 2222,
PeerAddr => 'localhost' );
$socket->send('Este es un mensaje!!!');
close($socket)
#################################################
Servidor UDP
#################################################
use IO::Socket;
$socket = IO::Socket::INET->new( Proto => 'udp'
LocalPort => 2222);
$socket->recv($mensaje, 1024);
print $mensaje;
close($socket);
#################################################
El módulo permite habilitar servicios multicast en redes IP. Su utilización principal es el transporte de
flujos de datos multimediales, donde existe un emisor y varios receptores de la misma información.
Los rangos de las direcciones IP entre 224.0.0.0 y 239.255.255.255 son reservados a grupos
multicast. Un mensaje que es enviado a cualquiera de las direcciones antedichas puede ser recibido
por n hosts. Un host que desee integrar un grupo, debe crear un socket con la función
IO::Socket::INET->new() y realizar una liga (bind) a un puerto local. El método mcast_add() permite la
subscripción a grupos multicast. El método recv() permite habilitar la recepción mensajes, el envio
se realiza mediante el método send(). Los métodos auxiliares mcast_set() y mcast_send() permiten
establecer un grupodestino por defecto y enviar mensajes a tal grupo respectivamente.
El máximo número de saltos permitidos para un mensaje puede definirse con el método mcast_ttl().
Para activar o desactivar la recepción de copias de mensajes producidos por la propia se utiliza el
método mcast_loopback().
use IO::Socket::Multicast;
# Creacion de un socket en el puerto 2222
my $s = IO::Socket::Multicast->new(LocalPort=>2222);
# Adicion a un grupo multicast
$s->mcast_add('226.226.226.226');
# Habilitar modo recepcion
$s->recv($datos,1024);
# Dejar un grupo
$s->mcast_drop('226.226.226.226');
# Definir ttl de mensajes
$s->ttl(6);
# Deshabilitar loopbacking
$s->loopback(0);
# Enviar un mensaje a un grupo
$s->mcast_send('Este es el mensaje','226.226.226.226:2222');
$s->mcast_set('226.226.226.226:2222');
$s->mcast_send('Este es otro mensaje');
#################################################
#!/usr/bin/perl
use strict;
use IO::Socket::Multicast;
use constant DESTINATION => '224.224.224.224:2244';
my $sock = IO::Socket::INET->new( Proto=>'udp',
PeerAddr=>DESTINATION);
while (1) {
my $mensaje = localtime. "\n";
$sock->send($mensaje) || die "Error en envio: $!";
} continue {
sleep 5;
}
#################################################
#!/usr/bin/perl
use strict;
use IO::Socket::Multicast;
use constant GROUP => '224.224.224.224';
use constant PORT => '2244';
my $sock = IO::Socket::INET->new( Proto=>'udp',
LocalPort=>PORT);
$sock->mcast_add(GROUP) || die "Error en conexion al grupo: $!\n";
while (1) {
my $data;
next unless $sock->recv($data,1024);
print $data;
}
#################################################