Member of The Internet Defense League Últimos cambios
Últimos Cambios
Blog personal: El hilo del laberinto Geocaching

BulletProof

Última Actualización: 14 de febrero de 2013

Archivos de la lista de correo de BulletProof.

Repositorio Mercurial de BulletProof.


Introducción

BulletProof es un programa escrito en Python y que debería funcionar en casi cualquier sistema que disponga de un intérprete Python. El programa se ha probado en Microsoft Windows y en diversos sistemas Unix, pero no dispongo de ningún sistema Apple Macintosh para poder probarlo también en esas máquinas.

BulletProof nació para dar respuesta a la necesidad de poder tener conversaciones absolutamente privadas y confidenciales a través de una infraestructura ajena como puede ser una red de IRC. Administro varios servidores de IRC y sé perfectamente que no se graban conversaciones, pero cuando se está haciendo una entrevista de trabajo, se están discutiendo temas de empresa o ligando :-), y nuestras conversaciones atraviesan decenas de líneas de datos y de máquinas, toda prevención es poca.

He aprovechado mis conocimientos y experiencia en el mundo de la criptografía para crear un producto que garantiza confidencialidad incluso cuando se usan redes "enemigas".

El programa está escrito en Python porque es un lenguaje que me encantó desde el primer momento que lo ví, y me asegura una portabilidad muy simple entre diferentes plataformas. La prueba de ello es que el mismo código BulletProof funciona tanto en máquinas con MS Windows, como en máquinas Unix (incluyendo Linux, Solaris, etc). No he podido probarlo en Macintosh, desgraciadamente.


Instalación y configuración

  • BulletProof requiere que esté instalado el lenguaje de programación Python. Si no lo tenemos instalado ya, nos lo podemos bajar de su web. Se trata de un programa gratuito. La versión de Python a instalar depende de la versión de BulletProof que deseamos ejecutar:

    • BulletProof 1.151 y superiores: Python 2.3.

    • BulletProof 1.123 y superiores: Python 2.2.

    • BulletProof 1.70 hasta 1.122: Python 2.1.

    • BulletProof 1.14 hasta 1.69: Python 2.0.

    • BulletProof 1.13 e inferiores: Python 1.5.2.

    Debemos instalar el Python completo, incluyendo el soporte TCL/TK, si estamos trabajando en Windows.

  • Seguidamente descargamos la versión de BulletProof deseada. Se recomienda instalar la última, claro.

    • BulletProof 1.159 (22 KB). Creada el 24 de abril de 2006. Esta versión NO EXPIRA. ¡¡Comprueba la firma digital!!. Si no sabes hacerlo, aquí tienes su MD5, como mal menor: fc2e71de88619756877b283895f6bbc7.

  • Una vez descargado el fichero ZIP, lo descomprimimos y lo guardamos donde nos parezca. Cuando deseemos utilizarlo, simplemente hay que ejecutar el fichero "cliente.py".

  • A continuación debemos configurar nuestro cliente IRC de forma apropiada. Para ello debemos indicarle que utilice protocolo SOCKS 4, y que el servidor SOCKS es 127.0.0.1, en el puerto 1080. No es necesario nombre de usuario ni clave de acceso.

    • Versión 1.118 o superior:

      A partir de la versión 1.118, se soporta "SOCKS 4", "SOCKS 5" y "Proxy HTTP". En las descripciones siguientes, cuando se lea "SOCKS 4" deberá considerarse equivalente en el caso de "SOCKS 5" y "Proxy HTTP".

    • Versión 1.52 o superior:

      BulletProof escucha, por defecto, en la IP 127.0.0.1. Esa IP se corresponde con la propia máquina, y se utiliza para permitir conexiones locales, únicamente. Es decir, que sólo podrán utilizar BulletProof aquellos programas que se ejecuten en la propia máquina.

      En algunos casos puede interesar que BulletProof admita conexiones exteriores, ya sea para utilizarlo como "bouncer" o para, por ejemplo, dar servicio a toda una red local, sin necesidad de que los usuarios lo instalen en todas las máquinas. En una situación así, es conveniente instalar el programa en una máquina, y configurar BulletProof para que escuche en su IP de la red local, y no en 127.0.0.1. Naturalmente este cambio supone unos riesgos de seguridad (acceso a BulletProof por parte de usuarios no autorizados) que la persona responsable del sistema debe valorar.

      BulletProof permite que se le indique la IP en la que escuchar a través de la variable ip_listen. Para cambiar su valor por defecto (127.0.0.1), procedemos de la siguiente manera:

      • Cargamos el fichero config.txt en un editor de textos.

      • Buscamos una línea de la forma #ip_listen="127.0.0.1". Eliminamos el símbolo "#" al principio de esa línea, y ponemos entre comillas la IP en la que queremos escuchar. La IP debe corresponderse con una IP válida de la máquina. Si ponemos una cadena vacía (""), BulletProof escuchará en todas las IPs asignadas a la máquina.

    • Versión 1.30 o superior:

      Aparte del soporte SOCKS 4 nativo, estas versiones disponen de capacidades adicionales:

      • Nuestro cliente IRC no soporta SOCKS 4

        Podemos utilizar BulletProof para que actúe como proxy, conectándonos automáticamente a un servidor de IRC determinado cuando nos conectamos a 127.0.0.1. Ello obliga a configurar BulletProof adecuadamente, y cambiar dicha configuración si deseamos cambiar de servidor.

        Para cambiar la configuración por defecto, que nos conecta a IRC hispano a través del puerto 6667 local, hacemos:

        • Cargamos el fichero cliente.py en un editor de textos.

        • Buscamos una línea de la forma #configuracion.servidor="libres.irc-hispano.org". Eliminamos el símbolo "#" al principio de esa línea, y ponemos entre comillas el servidor IRC al que deseamos conectar.

        • Si queremos conectar al servidor IRC a través de un puerto distinto al 6667, debemos buscar una línea de la forma #configuracion.puerto_servidor=6667. Eliminamos el símbolo "#" inicial y ponemos el número de puerto del servidor que deseamos utilizar.

        • Si queremos modificar el puerto local para el cual actúa el proxy (opción que no se recomienda salvo que se sepa lo que se hace :-), debemos buscar una línea de la forma #configuracion.puerto_irc=6667. Eliminamos el símbolo "#" inicial y ponemos el número de puerto local que deseamos utilizar.

        La configuración por defecto nos conecta a IRC-Hispano. Si es lo que queremos, no hace falta que editemos nada.

        Para conectarnos al IRC utilizando esta opción, una vez configurada, sólo tenemos que indicar al cliente de IRC que se conecte a la máquina 127.0.0.1. BulletProof capturará dicha conexión y la enviará automáticamente al servidor IRC que se haya especificado en la configuración (podemos usar la configuración por defecto, como ya se ha dicho). Si hemos configurado un puerto local distinto del estándar (6667), debemos indicar también dicho puerto en la orden de conexión del cliente IRC.

    • Estamos dentro de una red local que usa SOCKS 4 pasa salir a Internet

      Si nuestro cliente de IRC está dentro de una red que emplea SOCKS 4 para conectarse al servidor de IRC, nuestro cliente tendrá activada ya la configuración SOCKS 4 hacia su pasarela actual, y no podemos instalar BulletProof con la configuración estándar, ya que no sabrá cómo conectarse a Internet.

      Si éste es el caso, debemos configurar nuestro cliente de IRC para que emplee BulletProof como proxy SOCKS 4 y configurar BulletProof para que use el proxy SOCKS 4 de la red para salir a Internet.

      Para ello, configuramos el cliente de la manera explicada y, a continuación, hacemos:

      • Cargamos el fichero cliente.py en un editor de textos.

      • Buscamos una línea de la forma #configuracion.servidor_socks_salida="". Eliminamos el símbolo "#" al principio de esa línea, y ponemos entre las comillas la dirección IP o el nombre DNS del servidor SOCKS 4 que hay que utilizar pasa salir a Internet.

      • Si dicho servidor SOCKS 4 no reside en el puerto estándar (1080), debemos buscar una línea de la forma #configuracion.puerto_socks_salida=1080. Eliminamos el símbolo "#" inicial y ponemos el número de puerto en el que reside el servidor SOCKS 4.

    • Tengo conflictos de puertos

      Si BulletProof entra en conflicto con puertos utilizados en la máquina del cliente IRC, no funcionará correctamente. En casos así, BulletProof permite modificar los puertos utilizados.

      • Conflicto en el puerto SOCKS 4

        El puerto SOCKS 4 por defecto es el 1080. Si dicho puerto es utilizado por otras aplicaciones, hay que cambiarlo. Para ello:

        • Cargamos el fichero cliente.py en un editor de textos.

        • Buscamos una línea de la forma #configuracion.puerto_socks=1080. Eliminamos el símbolo "#" al principio de esa línea, y ponemos el puerto SOCKS 4 local que deseemos utilizar.

      • Conflicto en el puerto IRC

        El puerto IRC por defecto es el 6667. Si dicho puerto es utilizado por otras aplicaciones, hay que cambiarlo. Para ello:

        • Cargamos el fichero cliente.py en un editor de textos.

        • Buscamos una línea de la forma #configuracion.puerto_irc=6667. Eliminamos el símbolo "#" al principio de esa línea, y ponemos el puerto IRC local que deseemos utilizar.

  • A partir de ahora, siempre que queramos conectarnos al IRC, debemos ejecutar primero BulletProof (ejecutando el fichero "cliente.py"), lo que nos abrirá una ventana MSDOS (si estamos en Windows) en la que nos aparecerá diversa información, y luego lanzar el cliente de IRC que utilicemos.


Comandos y modo de empleo

BulletProof interactúa con el usuario a través de comandos que se introducen a través del cliente IRC que se esté utilizando.

Los detalles dependen del cliente de IRC concreto, pero lo normal es enviar comandos a BulletProof utilizando el modo "raw". Es decir, si queremos ver la versión de BulletProof que estamos utilizando, podemos hacer "/raw bulletproof version". Todos los comandos siguen el mismo esquema, con el "raw", y el comando "bulletproof".

Los comandos disponibles son:

  • version

    Nos informa de la versión de BulletProof que estamos empleando.

    Ejemplo: "/raw bulletproof version".

  • list [objeto...]

    Si no se indica ningún objeto, nos proporciona la lista completa de claves. Indicando una serie de objetos, se mostrarán exclusivamente las claves asociadas a los mismos. Esta última funcionalidad está disponible a partir de la versión 1.69.

    Las claves no aparecen en ningún orden concreto. En cada línea se muestra la clave empleada y el objeto que estamos protegiendo con ella (un nick o un canal).

    Ejemplo: "/raw bulletproof list".

    Si una clave está deshabilitada, nos aparecerá el texto "DISABLED" al lado de la clave.

  • add (objeto) (clave)

    Con este comando ponemos una clave a un objeto determinado. Los objetos pueden ser nicks o canales. La clave en sí puede tener cualquier longitud; más que una palabra, se pueden utilizar frases enteras.

    Ejemplo: "/raw bulletproof add #pruebas esto es una prueba".

  • del (objeto)

    Eliminamos la clave de un objeto determinado.

    Ejemplo: "/raw bulletproof del jcea"

  • disable (objeto) (a partir de BulletProof 1.54)

    Los mensajes que nos remita el objeto siguen descifrándose, pero los que nosotros le enviemos van en texto claro.

    Ejemplo: "/raw bulletproof disable jcea"

  • enable (objeto) (a partir de BulletProof 1.54)

    Vuelve a activar la clave, tanto para cifrar como para descifrar.

    Ejemplo: "/raw bulletproof enable jcea"

El sistema funciona de la siguiente manera:

  • Cuando recibimos un mensaje, si no está cifrado lo imprime directamente. Si está cifrado , existen dos opciones:

    • El mensaje tenía como destino un canal.

      Vemos si tenemos alguna clave para ese canal, e intenta descifrar el mensaje con ella.

    • El mensaje iba dirigido específicamente a nosotros.

      Vemos si tenemos clave para el remitente del mensaje, e intentamos descifrarlo con ella.

    Si no tenemos una clave para el objeto en cuestión, o la clave que tenemos no coincide con la clave empleada para cifrar el texto, BulletProof nos mostrará el texto cifrado, tal cual.

    Para distinguir entre texto cifrado y texto sin cifrar, se sigue la siguiente convención: el texto no protegido (no cifrado) se imprime "tal cual", mientras que el texto protegido (cifrado) se imprime con un apóstrofe (´) al principio de la línea. Si la clave de descifrado está marcada como deshabilitada, el texto protegido se imprimirá con apóstrofe-asterisco-apóstrofe (´*´).

    De esta forma sabemos lo que nos llega protegido y lo que no.

  • A la hora de enviar, si el objeto destino tiene clave asociada habilitada, enviamos el texto cifrado con ella. Si no existe clave, o ésta está marcada como deshabilitada, enviamos el texto en "abierto".


Ejemplo de Script

No es mi trabajo hacer scripts, pero pongo un ejemplo para que se vean las posibilidades de integración sencilla con los clientes típicos:

  • mIRC 5.8:

    En los "pop-up", añadimos:

    -
    BulletProof:
    .list: .raw bulletproof list o bien .list: .raw bulletproof list $active
    .version: .raw bulletproof version
    .del: .raw bulletproof del $active
    .add: .raw bulletproof add $active $?
    .enable: .raw bulletproof enable $active
    .disable: .raw bulletproof disable $active
    


Detalles técnicos de funcionamiento

BulletProof utiliza RC4 como mecanismo de cifrado y descifrado. Se eligió ese sistema por ser muy eficiente y seguro, y no incrementar el tamaño del texto cifrado respecto al texto sin cifrar (algo que sí ocurriría si emplease un cifrado de "bloque").

Lamentablemente RC4 es un cifrado en flujo ("stream") y exige que el emisor y el receptor estén perfectamente sincronizados, lo que no es posible en un entorno IRC en el que puede haber split, lag, varios emisores enviando al mismo canal simultaneamente, etc.

El enfoque adoptado consiste en inicializar el sistema RC4 en cada línea transmitida y recibida, para sincronizar el transmisor y el receptor. Ello incrementa ligeramente el tamaño de los datos intercambiados, pero se logra que el sistema funcione sin que el emisor y el receptor tengan que cumplir ninguna restricción en absoluto.

Los detalles de implementación del cifrado son los siguientes:

  • Tomamos un valor aleatorio de 64 bits.

  • Inicializamos el algoritmo RC4 con una clave de línea. Los detalles se dan más abajo.

  • Tomamos el texto y le ponemos al final los 32 primeros bits del valor aleatorio. Ciframos el conjunto con RC4, inicializado de la forma anterior.

  • La salida será la concatenación de los 64 bits aleatorios del primer punto (es necesario enviarlos para que el receptor pueda "abrir" el mensaje) y el texto cifrado obtenido del punto anterior.

  • Dicha salida puede contener valores incompatibles con el IRC, y es necesario codificarlo. Para ello revisamos la salida generada, byte a byte, buscando valores inferiores a 33. Por cada byte que cumpla dicha proporción, emitimos un espacio (valor 32) y el byte en cuestión, sumándole 33. Es decir, si nos encontramos con un valor 7, emitimos un espacio (valor 32) y un 40 (33+7).

    De esta manera nos aseguramos de que el resultado sea compatible con las redes de IRC actuales.

    La expansión que produce esta codificación es del 12.5%, en media.

A la hora de decodificar, procedemos a la inversa:

  • Decodificamos el texto cifrado, quitando la codificación que lo hacía transparente a las redes de IRC. Para ello vamos revisando el texto byte a byte, hasta que encontramos un espacio. En ese caso, tiramos el espacio, tomamos el byte siguiente y le restamos 33.

  • Seguidamente tomamos los primeros 64 bits del mensaje.

  • Inicializamos el algoritmo RC4 con la clave de línea. Los detalles se dan más abajo.

  • Desciframos el resto del texto de entrada, usando el RC4.

  • Verificamos que los últimos 32 bits de texto descifrado coinciden con los primeros 32 bits del texto cifrado original. Si es así, podemos estar seguros de que hemos descifrado el mensaje de forma correcta, y visualizamos el mensaje descifrado.

    Si la verificación falla, mostramos el mensaje cifrado original, ya que la clave parece ser incorrecta.

La estructura del paquete de datos, prescindiendo de la codificación para hacerlo transparente al IRC, es la siguiente:

   inicialización RC4                      verificación
+-----------------------+                  +---------+
[aleatorio1] [aleatorio2] [texto original] [aletorio1]
  4 bytes      4 bytes        n bytes        4 bytes
+-----------------------+ +--------------------------+
       no cifrado                   cifrado

ATENCIÓN:

A partir de la versión 1.71, se incluye una admiración cerrada ("!") al principio de cada línea codificada, a modo de control de versión del programa. Ello permite ampliar en el futuro el programa para que soporte una gran variedad de sistemas de autentificación, cifrado, intercambio de clave, etc.

La codificación y decodificación se realiza exactamente igual que se ha descrito más arriba, salvo por la adición de una admiración cerrada al principio de la línea transmitica, una vez cifrada y codificada.

CLAVE DE LÍNEA

  • Admiración cerrada ("!")

    La clave se forma concatenando la clave del usuario y los 64 bits de salt.

  • Porcentaje ("%")

    Se toma la concatenación de la clave de usuario y los 64 bits de salt. La clave de línea se forma concatenando el hash MD5 y el hash SHA-1 del valor anterior.

    Disponible a partir de la versión 1.123, para solucionar un problema de mal uso del RC4.


Historia

  • 14/feb/13: Publicación del código fuente de BulletProof, con licencia AGPL v3.

  • 24/abr/06: La versión 1.159 de BulletProof NO CADUCA.

  • 01/Jul/03: Actualización de BulletProof a la versión 1.146. Soluciona un problema de bloqueo de una conexión cuando uno de los extremos se corta de forma abrupta.

    Esta versión se puede considerar "release candidate" oficial.

    Documento también la instalación sobre Mac OS X y sobre OS/2.

  • 11/Abr/03: Actualización de BulletProof a la versión 1.141. Soluciona un problema en el envío de líneas muy largas.

  • 17/Ene/03: Actualización de BulletProof a la version 1.136. Se soluciona un problema en Windows, donde no se detectaban los "connection refused". Se trata de un bug de Python bajo MS Windows.

  • 10/Sep/02: Actualización de BulletProof a la versión 1.129. Se soluciona un problema de compatibilidad con direcciones IP y SOCKS 5.

  • 24/Ene/02: Actualización de BulletProof a la versión 1.123

    La principal novedad de esta versión es el corregir el uso vulnerable de RC4 que estábamos haciendo. Ello supone que que esta versión es incompatible con las anteriores.

    Para evitar interrumpir el servicio, lo que hago es que esta versión puede recibir tanto formato antiguo como nuevo, sin problemas. A la hora de enviar, envía en formato antiguo hasta la fecha en la que caduca la versión anterior, y en formato nuevo a partir de ese momento.

  • 30/Oct/01: Actualización de BulletProof a la versión 1.118.

    • Notable simplificación en la gestión del banner inicial, sobre todo cuando estamos haciendo "SOCKS Forwarding" o el futuro "PROXY Forwarding".

    • La versión 1.94 utiliza código 100% de mi propiedad, no la librería que escribí pero que no es de mi propiedad. No obstante el código de la librería (que ya no se usa) seguía presente en el programa. Elimino dicho código.

    • Soporte de "HTTP PROXY".

    • Cuando indicamos un cambio de grupo o de usuario al programa, lanzado como root (en Unix), podemos indicar tanto valores numericos como nombres.

    • Soporte "SOCKS 5".

  • 04/Oct/01: Actualización de BulletProof a la versión 1.94.

    • Reescritura completa de buena parte de las interioridades de BulletProof. El resultado es más "orientado" a objetos, más simple y más flexible.

      Además, me deshago de un problema de licencias. Ahora el código es 100% mío.

    • Solucionado un problema de FLUSH cuando se cierra un extremo de la conexión. Ahora se intenta hacer flush de todo lo que quede en el pipe.

    • Ahora podemos utilizar BulleProof en redes de IRC que no envíen nada al conectarse. Por ejemplo, irc.zope.net y los servidores irc.openprojects.org.

  • 06/Sep/01: Actualización de BulletProof a la versión 1.75.

    • Podemos desactivar el puerto de escucha SOCKS y el puerto de escucha de forwarding directo.

    • Bajo Unix, podemos cambiar de usuario y grupo, al lanzar el programa.

    Estas dos funcionalidades están documentadas en el fichero config.txt.

  • 28/May/01: Actualización de BulletProof a la versión 1.71.

    • Esta nueva versión incluye un número de versión en el intercambio cifrado, con el fin de soportar nuevos sistemas de cifrado, autentificación, intercambio de claves, etc.

  • 11/Abr/01: Actualización de BulletProof a la versión 1.69.

    • Ampliamos el comando list para que podamos preguntar sobre objetos en concreto.

  • 26/Ene/01: Actualización de BulletProof a la versión 1.54.

    • Permite elegir la IP en la que escuchamos conexiones, no estando vinculado exclusivamente a 127.0.0.1.

      ATENCIÓN: El uso de esta característica supone unos riesgos de seguridad que deben valorarse antes de utilizarla de forma activa.

    • Solucionado un problema con líneas extremadamente largas, que no se descifraban correctamente. Ahora, si al codificar una línea nos sale algo muy largo, BulletProof divide la línea en dos y las manda por separado.

      A la hora de dividir el texto en dos, intenta cortar por un espacio, si es posible.

    • Se añaden los comandos enable y disable.

  • 03/Ene/01: Nuevo gestor de la lista de correo. Archivos de la lista.

  • 02/Ene/01: Actualización de BulletProof a la versión 1.51:

    • Se admiten hasta 10 sesiones simultaneas. Anteriormente sólo se toleraba una sesión simultanea.

    • Corregido un problema con el comando del.

    • Movemos la configuración de cliente.py al fichero config.txt. De esta forma es más sencillo de ejecutar con un sencillo "doble click", sin invocar el programa.

    • Ya no hay fichero cliente.py, sino un precompilado cliente.pyc. Eso es posible porque hemos movido la configuración a un fichero aparte.

  • 13/Dic/00: Actualización para la versión 1.30 de BulletProof.

    • Restauramos la funcionalidad de conectarnos directamente a un servidor IRC, sin emplear SOCKS 4. Útil para clientes sin soporte SOCKS 4.

    • Podemos cambiar los puertos de escucha locales SOCKS 4 y proxy IRC.

    • Podemos utilizar BulletProof dentro de redes que, a su vez, empleen SOCKS 4 para salir a Internet. Ello permite, también, el empleo de BulletProof dentro de estructuras "bouncer" complejas.

  • 23/Nov/00: Primera versión de esta página y primera versión pública de BulletProof: la versión 1.23.

  • 28/Sep/00: Inicio del proyecto BulletProof.



Python Zope ©2000-2006 jcea@jcea.es

Más información sobre los OpenBadges

Donación BitCoin: 19niBN42ac2pqDQFx6GJZxry2JQSFvwAfS