Siguiente: Salida
Subir: Control de acceso
Anterior: Control de acceso
  Índice General
Conexión
El código fuente del script conexion es muy sencillo:
#!/usr/bin/perl -w
#-----------------------------------------------------------------------
# Script: conexion
# Version: 1.0
# Argumentos: login id_cola ubicacion
# Descripcion: Llama a la funcion conexion del modulo ControlNocat con
# los mismos parametros para registrar la entrada en la red
# en la tabla conexiones.
#-----------------------------------------------------------------------
use lib '/usr/local/nocat/lib/';
use ControlNocat;
use strict;
my $login=$ARGV[0];
my $id_cola=$ARGV[1];
my $ubicacion=$ARGV[2];
open (STDERR,">/dev/null");
&conexion($login,$id_cola,$ubicacion);
close (STDERR);
Este script se invoca desde la pasarela en el momento que un usuario es autenticado
y la pasarela acaba de cambiar sus reglas del cortafuegos, esto se realiza
en el método permit de la clase gateway.
Para invocar el script conexión nos tenemos que conectar por ssh desde la pasarela al servidor.
Para realizar esta conexión se ha creado un usuario llamado nocat en el servidor
de autenticación que es el propietario del script. El problema es el método para autenticar
a la pasarela desde el servidor, no se puede usar el sistema de introducir una clave. Lo que se ha
hecho es usar el método con clave pública en ssh. Se generan en la pasarela un par de claves RSA,
la clave pública y la clave privada, para hacer eso ejecutamos:
ssh-keygen -t rsa
Cuando nos pide una clave para proteger la clave privada pulsamos enter dos veces y
dejamos la clave privada sin proteger. Esto no presenta problemas ya que se supone que
la pasarela está protegida, en caso de que alguien pueda llegar a la clave privada querrá decir
que el sistema de protección ya ha fallado. El comando anterior crea el directorio .ssh dentro
del directorio home del usuario que lo ejecuta, y dentro de ese directorio está la clave privada
(id_rsa) y la clave pública (id_rsa.pub). En nuestro caso hemos creado un usuario nocat también
en la pasarela, y será este
usuario el que pueda conectarse al servidor sin necesidad de introducir ninguna clave.
Nos tenemos que asegurar que sólo pueda leer ese usuario
esas claves, para eso tecleamos:
chmod 700 /.ssh
Una vez hecho esto, creamos en el servidor de autenticación el usuario nocat y copiamos
la clave pública generada antes en /home/nocat/.ssh/authorized_keys. En el fichero de
configuración (/etc/ssh/sshd_config) debemos tener:
PubkeyAuthentication yes
Una vez que reiniciemos el servicio (/etc/init.d/sshd restart), el usuario nocat de la
pasarela podrá conectarse por ssh al servidor sin necesidad de introducir
ninguna clave.
En principio se invocó el script de conexión directamente desde el proceso gateway
de la pasarela, pero se comprobó que se introducía mucho retardo mientras se establecía
la conexión y se comprobaba la clave. La solución que se adoptó fue crear un proceso
que se ejecuta en background en la pasarela (p_remoto) y atiende peticiones continuamente.
Las peticiones tienen el siguiente formato:
servidor script [parámetros]
El servidor es la dirección del servidor, el script es el nombre del script que
se ejecuta remotamente, y una serie
de parámetros opcionales. El script lo busca en el directorio /usr/local/nocat/bin del servidor.
El modo de funcionamiento es escribir en un archivo FIFO una línea con el formato
anterior y el proceso p_remoto se encarga de atender la petición y ejecutar
el script deseado. El p_remoto crea un hijo cada vez que tiene que atender una petición,
y se queda esperando a que termine.
De esta manera, cuando se produce una conexión se libera al proceso gateway de esperar
la conexión ssh, permitiéndole continuar con su ejecución normalmente.
Pasemos a ver como quedó el método permit de la clase gateway. Introducimos unas líneas de comentarios
para indicar el lugar donde se insertaron las líneas.
sub permit {
my ( $self, $peer, $class ) = @_;
my $fw = $self->firewall( GatewayAddr => $peer->gateway_ip );
my $action;
# Stash the peer object for future use.
#
$self->add_peer( $peer );
# Update its expiration timestamp.
#
$peer->timestamp(1);
# Get *our* notion of what the peer's service class should be.
#
$class = $self->classify( $peer, $class );
my $prior_class = $peer->status;
if ( $prior_class ne $class ) {
# Insert the rule for the new class of service...
#
$fw->permit( $class, $peer->mac, $peer->ip );
# *BEFORE* removing the rule for the *old* class of service, if any.
# This way we don't drop packets for stateful connections in the
# event of service upgrade.
#
if ( $prior_class and $prior_class ne DENY ) {
$self->log( 5, "Upgrading ", $peer->user,
" from $prior_class to $class service." );
$fw->deny( $prior_class, $peer->mac, $peer->ip );
$action = "Upgrade";
} else {
$self->log( 5, "User ", $peer->user, " permitted in class $class
with rate ",$peer->rate,"Kbit and ceil ", $peer->ceil,"Kbit" );
$action = PERMIT;
# Codigo insertado para pasar a p_remoto una peticion que ejecute el script
# conexion en el servidor y registre la conexion en la tabla conexiones
#
my $servidor=$self->{AuthServiceAddr};
my $login=$peer->user;
my $ubicacion=$self->{Ubicacion};
my $id=$peer->id_cola;
open (FIFO,">/home/nocat/param_fifo");
print FIFO "$servidor conexion $login $id $ubicacion";
close FIFO;
# Insertamos clase para la calidad de servicio
#
$fw->ins_qos($peer->ip, $peer->id_cola, $peer->rate,
$peer->ceil, $peer->prio);
}
$peer->status( $class );
# Guardamos los parametros anteriores
#
$peer->ceil_anterior( $peer->ceil);
$peer->rate_anterior( $peer->rate);
}
elsif ( $peer->ceil_anterior ne $peer->ceil or
$peer->rate_anterior ne $peer->rate)
{#Si cambian los parametros de conexion
$self->log(5,"Upgrading ", $peer->user, "from Rate",
$peer->rate_anterior,"Kbit Ceil", $peer->ceil_anterior,"Kbit to ",
$peer->rate,"Kbit", $peer->ceil,"Kbit");
$fw->del_qos($peer->ip, $peer->id_cola);
$fw->ins_qos($peer->ip, $peer->id_cola, $peer->rate,
$peer->ceil, $peer->prio);
$peer->ceil_anterior( $peer->ceil);
$peer->rate_anterior( $peer->rate);
$action = "Renew";
}
else
{
$self->log( 5, "User ", $peer->user, " renewed in class $class
with rate", $peer->rate,"Kbit and ceil", $peer->ceil,"Kbit" );
$action = "Renew";
}
# Tell the parent process about it.
$self->notify_parent( $action => $peer );
}
Siguiente: Salida
Subir: Control de acceso
Anterior: Control de acceso
  Índice General
Jesús Martín
2003-09-16