domingo, 25 de julio de 2010

Chat p2p Netcat cifrado con OpenSSL

Este artículo lo escribí pensando en incluir un canal cifrado para el chat p2p que comenté días atrás en: La navaja suiza.

Quería incluir un cifrado sencillo simétrico (utilizando DES) con OpenSSL y además quería hacerlo para cada entrada enviada entre Cliente y Servidor y no por todo un bloque.

Como me gustó tanto este ejercicio, creé los siguientes scripts (que de preferencia recomiendo ejecutar en el orden en que son presentados):
  1. start_server.sh Inicia el netcat como escucha y envía la salida a un archivo (OUTPUT_FILE). Podrá notar que siempre que se corre este script, es vaciado el contenido del OUTPUT_FILE
  2. start_client.sh Comienza la lectura sigilosa de un archivo (de tipo PIPE*) utilizando el comando tail -f. Cada nueva entrada en este archivo (INPUT_FILE) será enviada al servidor haciendo uso de netcat.
  3. receiver.sh Este script y el mencionado seguidamente, son los encargados de tomar las entradas o salidas de netcat y cifrarlas o descifrarlas. En este caso, este script toma lo que ha recibido el servidor (OUTPUT_FILE) y lo descifra (puesto que dentro del mismo quedará el contenido cifrado)
  4. send.sh Este script permite enviar un mensaje desde el cliente al servidor, para lo cual utiliza el archivo INPUT_FILE, donde coloca el mensaje cifrado.

*: En el siguiente enlace podrá conseguir información bastante útil acerca de archivos FIFO.

En definitiva, los scripts start_server.sh y start_client.sh establecen la conexión TCP a través de netcat. Luego, los scripts send.sh y receiver.sh cifran y descifran los mensajes que viajarán entre cliente y servidor. Para utilizar estos scripts correctamente, deberá tener en el cliente los archivos start_client.sh y send.sh, y en el servidor, los archivos start_server.sh y receiver.sh.

Los scripts:

Script: start_server.sh
#!/bin/bash
OUTPUT_FILE='output'
PORT='1234'

if [ $# -eq 2 ]
then
        OUTPUT_FILE=$1
        PORT=$2
elif [ $# -gt 0 ]
then
        echo "Usage: start_server.sh [output_file port]"
        exit
fi

cat /dev/null > $OUTPUT_FILE && netcat -l -p $PORT > $OUTPUT_FILE

Script: start_client.sh.
#!/bin/bash
SERVER='localhost'
PORT='1234'
INPUT_FILE='input'

if [ $# -gt 3 ]
then
        echo "Usage: start_client.sh [server] [port] [input_file]"
        exit
else
        if [ $1 ]; then SERVER=$1; fi
        if [ $2 ]; then PORT=$2; fi
        if [ $3 ]; then INPUT_FILE=$3; fi
fi

if [ -p $INPUT_FILE ]
then
        tail -f $INPUT_FILE | netcat $SERVER $PORT
else
        echo "$INPUT_FILE isn't a pipe file. First, you may want to run: mkfifo $INPUT_FILE"
fi

Script: receiver.sh
#!/bin/bash
PASSWORD='1234'
OUTPUT_FILE='output'

if [ $# -gt 2 ]
then
        echo "Usage: receiver.sh [output_file] [password]"
        exit
else
        if [ $1 ]; then PASSWORD=$1; fi
        if [ $2 ]; then OUTPUT_FILE=$2; fi
fi

tail -f $OUTPUT_FILE | \
        while read -r line
        do
                echo $line | openssl enc -d -a -des3 -pass pass:$PASSWORD
        done

Script: send.sh
#!/bin/bash
PASSWORD='1234'
INPUT_FILE='input'

if [ $# -lt 1 ] || [ $# -gt 3 ]
then
        echo "Usage: send.sh message [password] [input_file]"
        exit
else
        if [ "$1" ]; then MESSAGE=$1; fi
        if [ $2 ]; then PASSWORD=$2; fi
        if [ $3 ]; then INPUT_FILE=$3; fi
fi

if [ -p $INPUT_FILE ]
then
        echo $MESSAGE | openssl enc -e -a -salt -des3 -pass pass:$PASSWORD -out $INPUT_FILE
else
        echo "$INPUT_FILE isn't a pipe file. Probably you don't have a server_client running"
fi

Un ejemplo:

En una consola (Consola #1 - Servidor):
$ ./start_server.sh &
$ ./receiver.sh

En otra consola (Consola #2 - Cliente):
$ mkfifo input
$ ./start_client.sh &
$ ./send.sh "primer envío"



No hay comentarios:

Publicar un comentario