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.