BOB (Basic Open Bridge) es una implementación en I2P que permite a cualquier aplicación en cualquier lenguaje realizar conexiones “streaming” para y desde una instancia de I2P. Se trata de una implementación interesante que permite la integración de aplicaciones existentes en el mundo de I2P así como el establecimiento de túneles seguros que permiten a dos o más máquinas comunicarse con una instancia de I2P, salvando un poco las distancias, tiene un comportamiento similar al que tiene SOCAT para establecer conexiones, dado que las espera por un túnel de entrada y posteriormente las enruta a un túnel de salida que dirige hacia la máquina donde se encuentra en ejecución I2P. Antes de BOB existía una implementación que llevaba a cabo funciones similares, esta es SAM, sin embargo en su primera versión cada cliente podía enviar datos sobre a un único Destination a la vez, esto quiere decir, que si un cliente enviaba datos a un socket (cuyo punto final era Destination) tenia que esperar a que dichos datos fueran recibidos correctamente por el Destination antes de poder enviar más información a otro Destination, lo que al final se resume en bajo rendimiento y posiblemente cuellos de botella, por este motivo su uso se encuentra depreciado y se recomienda utilizar SAM v2/v3.
BOB cuenta con canales de datos separados, lo que indica que un cliente y/o un Destination pueden enviar y recibir paquetes de datos de forma concurrente sin esperar a que el otro extremo de la conexión confirme su recepción, todas las peticiones se llevan a cabo en paralelo.
Ahora bien, para que BOB pueda ser manejado por cualquier aplicación, escrita en cualquier lenguaje, cuenta con un conjunto de comandos que permiten iniciar/detener túneles de entrada/salida, así como la administración de los mismos, estos comandos se ingresan desde consola y son correctamente tratados por el interprete de BOB, en realidad es un listado muy corto, pero permiten realizar todas las tareas necesarias para crear un puente con BOB e I2P.
Una de las principales ventajas de este enfoque, es que permite a cualquier aplicación (incluso aquellas que se encuentran en Internet) acceder a una máquina remota utilizando I2P por medio. A continuación se detalla el uso de BOB, sus comandos y los conceptos básicos para comprender como utilizarlo.
Conceptos Básicos de BOB
En primer lugar, es necesario entender que BOB por si mismo no es útil, dado que no se trata de una aplicación stand-alone o una aplicación web, es simplemente una interfaz de aplicación que permite que dos máquinas se comuniquen entre ellas por medio de sus aplicaciones. Normalmente para utilizar BOB, se debe iniciar primero ya sea desde Java utilizando el JAR localizado en <I2P_DIR>/lib/BOB.jar simplemente con ejecutar el método “main” de la clase BOB de la siguiente forma (Es necesario que I2P este arrancado):
net.i2p.BOB.BOB bob = new net.i2p.BOB.BOB(); bob.main(null); |
Sin embargo se recomienda utilizar la consola administrativa de I2P. La página para iniciar y detener BOB es:
http://127.0.0.1:7657/configclients |
Desde allí se puede administrar el arranque automático o manual de BOB de acuerdo a las necesidades de cada usuario.
Para comprobar que se encuentra levantado, es necesario utilizar una aplicación que “conecte” con el puerto que inicia BOB, por ejemplo Telnet o Netcat suelen ser una buena opción:
Netcat >nc localhost 2827 BOB 00.00.0F OK |
Telnet >telnet localhost 2827 Trying 127.0.0.1… Connected to localhost. Escape character is ‘^]’. BOB 00.00.0F OK |
Cualquiera de los comandos anteriores da el mismo resultado.
NOTA: El puerto 2827 es el valor por defecto utilizado por I2P para iniciar BOB, sin embargo estos valores pueden ser modificados después de que se genere el fichero de configuración de BOB localizado en <USER_DIR>/.i2p/bob.config. Cuando se inicia BOB por primera vez, este fichero es creado y los valores por defecto son establecidos, es posible cambiar estos valores si se desea. El valor por defecto de este fichero es el siguiente:
#/home/adastra/.i2p/bob.config #Thu Nov 01 21:27:19 GMT 2011 BOB.CFG.VER=1 i2cp.tcp.port=7654 BOB.host=localhost inbound.lengthVariance=0 i2cp.messageReliability=none BOB.port=2827 outbound.length=1 inbound.length=1 outbound.lengthVariance=0 i2cp.tcp.host=localhost |
Utilizando BOB
Para comprender correctamente el uso de BOB es importante conocer cuales son las opciones que se encuentran disponibles en el interprete de comandos y posteriormente realizar ejemplos concretos ilustrativos de la creación de túneles y su posterior consumo.
Opciones del interprete BOB
Se puede conocer el uso de cada una de las opciones disponibles en BOB una vez se ha conectado con el interprete utilizando el comando “help” de la siguiente forma:
>netcat localhost 2827 BOB 00.00.0F OK help OK COMMANDS: help clear getdest getkeys getnick inhost inport list lookup newkeys option outhost outport quiet quit setkeys setnick show showprops start status stop verify visit zap |
El significado de cada una de estas opciones se detalla a continuación:
NOTA: En BOB un “nickname” es equivalente a un túnel.
clear: Elimina el nickname establecido actualmente en la sesión. getdest: Retorna el Destination asociado al nickname establecido. getkeys: Retorna el par de claves (Publica/Privada) del nickname establecido getnick <tunel_name>: Consulta y establece el nickname en la sesión actual. Este valor se encuentra almacenado en la base de datos interna de BOB. inhost <hostname|IP>: Se trata del túnel “inbound” que puede ser un hostname o una dirección IP para el nickname actual. inport <number>: Se trata del puerto del túnel “inbound” que debe ser un puerto valido y disponible para el nickname actual. list: Lista todos los túneles almacenados en BOB (nicknames) lookup: Realiza una búsqueda de una dirección i2p, retorna el Destination (dirección en BASE64). newkeys: Genera un nuevo par de claves (Pública/Privada) para el nickname actual. option <key=value>: Se trata de un mapa de opciones I2CP que utilizará BOB outhost <hostname|IP>: Se trata del túnel “outbound” que puede ser un hostname o una dirección IP para el nickname actual. outport <number>: Se trata del puerto del túnel “outbound” que debe ser un puerto valido y disponible para el nickname actual. quiet <true|false>: Esta opción activa a desactiva la característica que tiene BOB de enviar el Destination del emisor del paquete. setkeys <BASE64 Keys>: Establece un par de claves para el nickname actual setnickname <nickname>: Crea un nuevo nickname y lo establece en la sesión actual show: Enseña el estado actual del nickname establecido en la sesión showprops: Enseña las propiedades del nickname actual. start: Inicia el actual nickame (túnel) status <nickname>: Enseña el estatus del nickname establecido por parámetro. stop: Detiene el nickname actual. verify <BASE64 Destination>: Verifica si un Destination determinado es valido. visit: Se encarga de volcar toda la información del hilo actual al fichero wrapper.log zap: Detiene BOB junto con todos sus túneles. quit: Salir del interprete. |
El uso de algunos de estos comandos, se indica a continuación:
Listar los túneles disponibles
list DATA NICKNAME: mouth STARTING: false RUNNING: false STOPPING: false KEYS: true QUIET: false INPORT: not_set INHOST: localhost OUTPORT: 601 OUTHOST: 127.0.0.1DATA NICKNAME: ear STARTING: false RUNNING: false STOPPING: false KEYS: true QUIET: true INPORT: 31331 INHOST: 127.0.0.1 OUTPORT: not_set OUTHOST: localhost |
Obteniendo y estableciendo un NickName
getnick adastra OK Nickname set to adastra |
Lookup I2P Site
lookup eepsites.i2p OK DHoGpNRACpcGnhB1l14ZRQFjnQtNvItX7~bZylgVaD2DnaYpqB7GoBcf5gJmjhXYRi3-UlOnrkEtQB4fICotgM0XLG8LHyNQVkj6rAnGSWBwX3zZaTWr~K6Up80AMDa8nN3D04coXQiL8Jn4~pcN2-7pxIL-Ox-J3aB8f3KthVxcuR27h1fJGR~BFqf~4ZdC7rGItokOb0qocU4gMNI-HWgmhUv-ucFc9m~Jh-BvM2nd~KGs7EQMtRxLgVJcj7G0j9chyN37l7mB5X~vYIueORENcKgo3OTjTAE9oHiVSZz7v11VVH3OynUp65QdtVXLCrqsqr4nJoFnApUcX5uYY4h~24dthZfHv1TjzWOuy1DFJH5mmT81HGQhtQI8g52CbnRgm4ItKQNq8AYPkJI2habi4ibUqBnmYk6g0p9mx1MsmpMmbQP6jemiZPpcVhAEjqJO-IyPyy0pDvg6O4fIgmstwdQS~qq~Sts20BWikhsXifQL87wnXtiN9e-PluyNAAAA |
Verificando un Destination
verify DHoGpNRACpcGnhB1l14ZRQFjnQtNvItX7~bZylgVaD2DnaYpqB7GoBcf5gJmjhXYRi3-UlOnrkEtQB4fICotgM0XLG8LHyNQVkj6rAnGSWBwX3zZaTWr~K6Up80AMDa8nN3D04coXQiL8Jn4~pcN2-7pxIL-Ox-J3aB8f3KthVxcuR27h1fJGR~BFqf~4ZdC7rGItokOb0qocU4gMNI-HWgmhUv-ucFc9m~Jh-BvM2nd~KGs7EQMtRxLgVJcj7G0j9chyN37l7mB5X~vYIueORENcKgo3OTjTAE9oHiVSZz7v11VVH3OynUp65QdtVXLCrqsqr4nJoFnApUcX5uYY4h~24dthZfHv1TjzWOuy1DFJH5mmT81HGQhtQI8g52CbnRgm4ItKQNq8AYPkJI2habi4ibUqBnmYk6g0p9mx1MsmpMmbQP6jemiZPpcVhAEjqJO-IyPyy0pDvg6O4fIgmstwdQS~qq~Sts20BWikhsXifQL87wnXtiN9e-PluyNAAAA OK |
Obteniendo el Destination del NickName actual
getdest OK 8ZNfTy6Vwvs2mk2JpxqvCKIRrABhndyyrhS-~5O5vFO4j~VuD1YdzmcA~bAbn9XJeqC31fU8RaSjiL7UgWel-VQLSr7GcHiKbGZPdXFOwfnNNCi1gvwTHc877u15oc5AKgD0wCRh2B2ZJeNd~of0TZ6-6XuHWYjlggGkyqGJNsI753TLlbP5wOwzgad5g7gJRSRmWN7xxLArKXPoT3EMb-AosMezNnT4QRpJi29MEctr~XZ0cQg967-bqWFV7hoE9mbzyrhi-6sPtnJot2dQH38WKnbRsT-AfpHGkdVXgWreydHAVw9Kis6E9WFoILpiP5XerRIQ4FxYkQ0je22ZATS7t-Is1Z6qsD0Q5YJOabNJu544QJM4eux2Ngp5v1girddXncA~8Z1OhMSHAVFoY2D6m1JTUCSHhb0bQmcjkO3OBLg5cx2sI~bfZJak2Xt1xEWA8Ufpmvdm6E8nMo1Tk48nmPDM8A~LwkJwT2DsQm4zWz1f22-tzy0rLb9901g4AAAA |
Ahora que se han indicado cuales son las opciones disponibles en BOB, se procede a indicar algunos ejemplos de su uso, donde el Destination contendrá varios servicios que un cliente podrá consumir de forma anónima, si se fija con detenimiento, este es un enfoque bastante similar al concepto de los Hidden Services en TOR.
BOB con Destination SOCAT
El comando SOCAT utilizado para recibir las peticiones
>socat TCP4-LISTEN:601 TCP4:www.google.com:80 |
En primera instancia se inicia el túnel BOB que enrute a los clientes a SOCAT, los comandos utilizados son los siguientes
>nc localhost 2827 BOB 00.00.0F OK setnick adastra OK Nickname set to adastra newkeys OK 8ZNfTy6Vwvs2mk2JpxqvCKIRrABhndyyrhS-~5O5vFO4j~VuD1YdzmcA~bAbn9XJeqC31fU8RaSjiL7UgWel-VQLSr7GcHiKbGZPdXFOwfnNNCi1gvwTHc877u15oc5AKgD0wCRh2B2ZJeNd~of0TZ6-6XuHWYjlggGkyqGJNsI753TLlbP5wOwzgad5g7gJRSRmWN7xxLArKXPoT3EMb-AosMezNnT4QRpJi29MEctr~XZ0cQg967-bqWFV7hoE9mbzyrhi-6sPtnJot2dQH38WKnbRsT-AfpHGkdVXgWreydHAVw9Kis6E9WFoILpiP5XerRIQ4FxYkQ0je22ZATS7t-Is1Z6qsD0Q5YJOabNJu544QJM4eux2Ngp5v1girddXncA~8Z1OhMSHAVFoY2D6m1JTUCSHhb0bQmcjkO3OBLg5cx2sI~bfZJak2Xt1xEWA8Ufpmvdm6E8nMo1Tk48nmPDM8A~LwkJwT2DsQm4zWz1f22-tzy0rLb9901g4AAAA quiet true OK Quiet set outhost 127.0.0.1 OK outhost set outport 601 OK outbound port set start OK tunnel starting |
Como puede apreciarse se han establecido todas las propiedades necesarias para que el Destination “adastra” envié todas las peticiones a la máquina local en el puerto 601. Este túnel se almacena en la base de datos de BOB y aunque se cierre la sesión de Netcat que ha creado el túnel, este permanecerá abierto hasta que sea detenido de forma explicita.
Ahora se inicia el túnel “inbound” para recibir las peticiones por parte de otras instancias de I2P, en este caso se utiliza la misma máquina, pero este enfoque funciona correctamente en un entorno LAN o incluso en Internet.
setnick client_adastra OK Nickname set to client_adastra newkeys OK NvYczzcZAkXsFSvwaK-UkG0TB4bu9DHtR4W96asAjLl4iBd-MWzM7nTrpXPfpovlDNouqHf7jqZpvH5HArcLjvwOJEzwyaSze5BLJMkRWIJHGrFyieRUhmXT44Egy~ZjI-05NkdEpHIT5s4XT-7K2zixMiNOnkd8WX2H-Ywmuxl7J1UIMDccf5ppAE~gbPl6svgL4O2~IHnUm4LLhNRoFQkocMcY0IZ4HQ45Er0FbwfXBx3luYTeCXBEFqVLuPawvci9N0ZLFxateydXPgT4VwMwOwF25fs9iSXFmOEaIvC2Elp9eAM8l~Xl1iKMaoSNxAO2DMK9uFA2Le5lcL5o9WINZ210zI9128bg~VDy3BiAduVo8a8feYUzKNsgCF7GKS1uErH-M7ptGg8Y4SlbjukA47-Ox5-ISjQbIuilFXxK47kZC2bzFJh4vrAvH8yYv9QaSN3u9G9Nt5H1uWNZwHLcGM90tIuhXmYYwbT2snUttXXgSTt27z49XW2ePlyqAAAA inhost 127.0.0.1 OK inhost set inport 1025 OK inbound port set quiet true OK Quiet set start OK tunnel starting quit OK Bye! |
Con esto es suficiente para establecer el túnel inbound, que en este caso concreto recibirá peticiones por el puerto 1025. También es importante notar que aunque la sesión de NetCat se ha cerrado, estos túneles aun están funcionando. Ahora, se puede probar su correcto funcionamiento, realizando una conexión por el puerto 1025 y posteriormente, enviando el Destination correspondiente al túnel outbound creado anteriormente, el cual se encargará de conectar con el servicio SOCAT iniciado en el puerto 601.
>telnet 127.0.0.1 1025 Trying 127.0.0.1… Connected to 127.0.0.1. Escape character is ‘^]’. 8ZNfTy6Vwvs2mk2JpxqvCKIRrABhndyyrhS-~5O5vFO4j~VuD1YdzmcA~bAbn9XJeqC31fU8RaSjiL7UgWel-VQLSr7GcHiKbGZPdXFOwfnNNCi1gvwTHc877u15oc5AKgD0wCRh2B2ZJeNd~of0TZ6-6XuHWYjlggGkyqGJNsI753TLlbP5wOwzgad5g7gJRSRmWN7xxLArKXPoT3EMb-AosMezNnT4QRpJi29MEctr~XZ0cQg967-bqWFV7hoE9mbzyrhi-6sPtnJot2dQH38WKnbRsT-AfpHGkdVXgWreydHAVw9Kis6E9WFoILpiP5XerRIQ4FxYkQ0je22ZATS7t-Is1Z6qsD0Q5YJOabNJu544QJM4eux2Ngp5v1girddXncA~8Z1OhMSHAVFoY2D6m1JTUCSHhb0bQmcjkO3OBLg5cx2sI~bfZJak2Xt1xEWA8Ufpmvdm6E8nMo1Tk48nmPDM8A~LwkJwT2DsQm4zWz1f22-tzy0rLb9901g4AAAA GET / HTTP/1.1HTTP/1.1 302 Found Location: http://www.google.es/ Cache-Control: private Content-Type: text/html; charset=UTF-8 Set-Cookie: PREF=ID=5171767cd5214b8d:FF=0:TM=1323566173:LM=1323566173:S=cZFgIcvPGe_45F2g; expires=Tue, 10-Dec-2013 01:16:13 GMT; path=/; domain=.google.com Date: Sun, 11 Dec 2011 01:16:13 GMT Server: gws Content-Length: 218 X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN<HTML><HEAD><meta http-equiv=»content-type» content=»text/html;charset=utf-8″> <TITLE>302 Moved</TITLE></HEAD><BODY> <H1>302 Moved</H1> The document has moved <A HREF=»http://www.google.es/»>here</A>. </BODY></HTML> |
Como puede apreciarse, el puerto 601 de SOCAT ha recibido una petición por medio de I2P, la cual posteriormente ha sido enrutada hacia http://www.google.com:80
En este ejemplo se ha utilizado Socat, pero aplica exactamente igual para cualquier otro relay como un proxy o un NetCat.
NOTA: En los ejemplos anteriores se ha establecido la propiedad “quiet” a “true” esto debido a que por defecto, BOB envía el destination entrante a la aplicación destino, dado que en este caso se trata de aplicaciones interactivas que esperan comandos validos, la recepción de un texto en Base64 no es una entrada adecuada, por este motivo, establecer esta opción a “true” evita que BOB envié información adicional a la aplicación que recibe los datos en el otro lado.