Esta pagina se ve mejor con JavaScript habilitado

Cliente BitTorrent headless en jail FreeBSD.

 ·  🎃 kr0m

Una de las maneras mas rápidas y sencillas de descargar ficheros es mediante BitTorrent, pero hay contenido que solo lo tienen un reducido número de personas y la descarga puede llevar horas o incluso días, en estos casos vale la pena tener un servidor de descargas dedicado exclusivamente a esta tarea, de este modo no será necesario dejar nuestro equipo encendido todo ese tiempo. En este artículo se explicará como instalar un servidor de transmission en modo headless, como configurar un cliente para gestionar las descargas desde nuestro pc y como compartir el contenido descargado mediante ZFS-NFS4.

El artículo se compone de distintas secciones:


Montaje de la jail y configuración del padre:

Para mayor versatibilidad y comodidad vamos a montar el servidor sobre una jail Iocage :

iocage create -r LATEST -n Lomax boot=on
iocage set ip4_addr=“nfe0|192.168.69.7/24” Lomax
iocage list

+-----+---------+-------+--------------+--------------+  
| JID |  NAME   | STATE |   RELEASE    |     IP4      |  
+=====+=========+=======+==============+==============+  
| 10  | Lomax   | up    | 12.2-RELEASE | 192.168.69.7 |  
+-----+---------+-------+--------------+--------------+

Transmission precisa de unos buffers UDP mas altos de lo normal, si no los subimos veremos el siguiente error en el log de messages al arrancar el servicio:

Nov 17 22:10:19 Lomax transmission-daemon[2775]: UDP Failed to set receive buffer: requested 4194304, got 42080 (/wrkdirs/usr/ports/net-p2p/transmission-daemon/work/transmission-3.00/libtransmission/tr-udp.c:97)

FreeBSD por defecto trae los siguientes valores:

sysctl -a|grep kern.ipc.maxsockbuf

kern.ipc.maxsockbuf: 2097152  
sysctl -a|grep net.inet.udp.recvspace
net.inet.udp.recvspace: 42080

Los modificamos mediante el fichero sysctl.conf:

vi /etc/sysctl.conf

kern.ipc.maxsockbuf=5242880  
net.inet.udp.recvspace=4194304

Aplicamos los cambios:

service sysctl restart

Destacar que estamos modificando los parámetros para todas las jails, en la propia jail no es posible hacerlo ya que el kernel es compartido, si lo intentamos obtendremos el siguiente mensaje de error:

service sysctl restart

sysctl: kern.ipc.maxsockbuf=5242880 at line 10: Operation not permitted  
sysctl: net.inet.udp.recvspace=4194304 at line 11: Operation not permitted

Directorio de descargas:

Creamos un dataset con compresión habilitada, este directorio será vinculado en la jail y servirá como directorio de descargas:

zfs create -o compress=lz4 storage/torrents

Accedemos a la jail y asignamos un password a la cuenta de root:

iocage console Lomax
passwd

Creamos el directorio de descargas:

mkdir -p /storage/torrents
exit

Vinculamos el dataset con el directorio de descargas de la jail:

iocage fstab -a Lomax “/storage/torrents /storage/torrents nullfs rw 0 0”
iocage fstab -l Lomax

+-------+---------------------------------------------------------------------------------------------------+  
| INDEX |                                            FSTAB ENTRY                                            |  
+=======+===================================================================================================+  
| 0     | /storage/torrents       /zroot/iocage/jails/Lomax/root/storage/torrents nullfs  rw      0       0 |  
+-------+---------------------------------------------------------------------------------------------------+

Reiniciamos la jail:

iocage stop Lomax
iocage start Lomax


Configuración mínima de la jail:

Accedemos a la jail para instalar el software base y añadir un usuario:

iocage console Lomax

Instalamos algunos programas básicos y Python

pkg update
pkg install vim htop bash screen py37-pip curl

Instalamos mediante pip el paquete requests:

pip install requests

Habilitamos y arrancamos el servicio Ssh:

sysrc sshd_enable="yes"
service sshd start

Creamos un usuario regular con el que operaremos:

adduser

Login group is kr0m. Invite kr0m into other groups? []: wheel  
Shell (sh csh tcsh bash rbash nologin) [sh]: bash

Instalación y configuración de Transmission:

Ahora que ya tenemos nuestro usuario y Ssh habilitado podemos seguir el resto de los pasos desde una consola Ssh:

ssh kr0m@192.168.69.7 -p22
su -l

Instalamos transmission:

pkg install transmission

Podemos ver los parámetros de configuración que se permiten en el rc.conf en el siguiente fichero:

cat /usr/local/etc/rc.d/transmission

En nuestro caso tan solo debemos modificar el directorio de descargas:

sysrc transmission_download_dir=/storage/torrents

En cuanto a las flags tendremos que consultar el man:

man transmission-daemon

En mi caso debo permitir el acceso a las direcciones ip de la propia jail y de mi pc, además del filtrado ip asignamos un usuario y password:

sysrc transmission_flags="-a 192.168.69.4,192.168.69.7 -t -u kr0m -v PASSWORD"

NOTA: Nunca debemos hacer un restart del servicio, parece no recargar la configuración, así que haremos un stop/start.

El resto de parámetros de configuración los modificaremos en el fichero settings.json, parando el servicio previamente:

service transmission stop
vi /usr/local/etc/transmission/home/settings.json
service transmission start

Solo tocamos los parámetros que no podamos modificar por los dos métodos descritos anteriormente, si no respetamos esta norma transmission nos sobreescribirá la configuración.

Cambiamos los permisos del directorio de descargas:

chown -R transmission:transmission /storage/torrents/

Habilitamos y arrancamos el servicio:

sysrc transmission_enable=YES
service transmission start

Comprobamos que haya arrancado con los parámetros correctos:

ps auxwww|grep trans

transmission 89161  0.4  0.3 41292 12172  -  SsJ  12:59   0:00.07 /usr/local/bin/transmission-daemon -g /usr/local/etc/transmission/home -w /storage/torrents -x /var/run/transmission/daemon.pid -a 192.168.69.4,192.168.69.7 -t -u kr0m -v PASSWORD

Instalación, configuración y gestión del cliente:

Instalamos Transmission en el pc para poder gestionar las descargas de forma remota:

pkg install transmission

Comprobamos que tanto el filtro ip como el usuario/password funcionen:

transmission-remote 192.168.69.7 –auth kr0m:PASSWORD -l

ID   Done       Have  ETA           Up    Down  Ratio  Status       Name  
Sum:                None               0.0     0.0

Añadir un torrent es tan sencillo como indicarle la URL del mismo:

También podemos pasarle un enlace magnet:

transmission-remote 192.168.69.7 –auth kr0m:PASSWORD -a “magnet:?xt=urn:btih:E1718B4288E1CD1C200AE8219E81D85EB1D9F0E8&dn=Lynda+-+Learning+Debian+Linux+%5BAhLaN%5D&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969%2Fannounce&tr=udp%3A%2F%2F9.rarbg.to%3A2710%2Fannounce&tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.uw0.xyz%3A6969%2Fannounce&tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.tiny-vps.com%3A6969%2Fannounce&tr=udp%3A%2F%2Fopen.demonii.si%3A1337%2Fannounc4&tr=udp%3A%2F%2Fexplodie.org%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce&tr=udp%3A%2F%2Ftracker.kamigami.org%3A2710%2Fannounce&tr=udp%3A%2F%2Fretracker.akado-ural.ru%3A80%2Fannounce&tr=udp%3A%2F%2Fopentor.org%3A2710%2Fannounce&tr=udp%3A%2F%2Ftracker.lelux.fi%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.zer0day.to%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969%2Fannounce&tr=udp%3A%2F%2Fcoppersurfer.tk%3A6969%2Fannounce”

Comprobamos el estado de las descargas:

transmission-remote 192.168.69.7 –auth kr0m:PASSWORD -l

    ID   Done       Have  ETA           Up    Down  Ratio  Status       Name  
     1     0%       None  Unknown      0.0     0.0   None  Idle         debian-10.6.0-arm64-xfce-CD-1.iso  
     2    n/a       None  Unknown      0.0     0.0   None  Idle         Lynda+-+Learning+Debian+Linux+[AhLaN]  
Sum:                None               0.0     0.0

Para eliminar un torrent debemos pasarle el ID del torrent a eliminar y el parámetro -r:

transmission-remote 192.168.69.7 –auth kr0m:PASSWORD -t 1 -r

Se pueden eliminar múltiples torrents con un solo comando:

transmission-remote 192.168.69.7 –auth kr0m:PASSWORD -t 1,2 -r

Para operar con Transmission de una forma mas sencilla podemos crear el siguiente alias:

vi .bashrc

alias tsm="transmission-remote 192.168.69.7 --auth kr0m:PASSWORD"

Ahora consultar los torrents es tan sencillo como esto:

tsm -l

    ID   Done       Have  ETA           Up    Down  Ratio  Status       Name  
     1    n/a       None  Unknown      0.0     0.0   None  Idle         Lynda+-+Learning+Debian+Linux+[AhLaN]  
     3    54%   398.4 MB  1 min        0.0  11717.0    0.0  Downloading  debian-10.6.0-arm64-xfce-CD-1.iso  
Sum:            462.2 MB               0.0  15387.0

Acceso NFS:

Una de las ventajas de servir el contenido descargado por NFS es que si se trata de un fichero multimedia podremos realizar el streaming directamente desde el servidor sin tener que copiar el fichero a nuestro equipo.

El acceso por NFS se realizará desde el padre de la jail, habilitamos el servicio de NFS4 y lo arrancamos:

sysrc nfs_server_enable="yes"
sysrc nfsv4_server_enable="yes"
sysrc nfsuserd_enable="yes"
service nfsd start

Compartimos el directorio restringiendo el acceso por ip:

zfs set sharenfs="-mapall=root,-network=192.168.69.4/32" storage/torrents

NOTA: Con la opción mapall=root hacemos que los accesos al NFS se hagan con el usuario root, todos los accesos desde los clientes tienen los permisos de root del servidor remoto, si no lo configurasemos deberíamos de tener los mismos usuarios con los mismos UIDs/GIDs tanto en el servidor NFS como en todos los clientes a los que les demos acceso.

Mi primera idea fué mapearlo al usuario transmission y no a root, pero como compartimos desde el padre el usuario transmission no existe y NFS4 ya no permite mapear por UID :

uid/gid numbers are no longer used in the NFSv4 protocol


Firewall:

Configuramos las reglas de firewall para que solo nuestro pc tenga acceso al NFS y al servicio de configuración RPC de Transmission, para que las reglas queden mas claras indico a continuación la correspondencia de las direcciones ip:

  • Pc: 192.168.69.4
  • Padre: 192.168.69.2
  • jail: 192.168.69.7
vi /etc/ipfw.rules
# Torrent NFS access:
# NFS access:
# NFS: Port tcp/udp 111
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.2 111 in via $wanif
$cmd 00805 allow tcp from 192.168.69.2 111 to 192.168.69.4 out via $wanif
$cmd 00805 allow udp from 192.168.69.4 to 192.168.69.2 111 in via $wanif
$cmd 00805 allow udp from 192.168.69.2 111 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.2 111 in via $wanif
$cmd 00805 deny udp from any to 192.168.69.2 111 in via $wanif

# NFS: Port tcp/udp 950
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.2 950 in via $wanif
$cmd 00805 allow tcp from 192.168.69.2 950 to 192.168.69.4 out via $wanif
$cmd 00805 allow udp from 192.168.69.4 to 192.168.69.2 950 in via $wanif
$cmd 00805 allow udp from 192.168.69.2 950 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.2 950 in via $wanif
$cmd 00805 deny udp from any to 192.168.69.2 950 in via $wanif

# NFS: Port tcp/udp 2049
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.2 2049 in via $wanif
$cmd 00805 allow tcp from 192.168.69.2 2049 to 192.168.69.4 out via $wanif
$cmd 00805 allow udp from 192.168.69.4 to 192.168.69.2 2049 in via $wanif
$cmd 00805 allow udp from 192.168.69.2 2049 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.2 2049 in via $wanif
$cmd 00805 deny udp from any to 192.168.69.2 2049 in via $wanif

# NFS: Port tcp/udp 882
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.2 882 in via $wanif
$cmd 00805 allow tcp from 192.168.69.2 882 to 192.168.69.4 out via $wanif
$cmd 00805 allow udp from 192.168.69.4 to 192.168.69.2 882 in via $wanif
$cmd 00805 allow udp from 192.168.69.2 882 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.2 882 in via $wanif
$cmd 00805 deny udp from any to 192.168.69.2 882 in via $wanif

# Transmission Lomax RPC:
$cmd 00805 allow tcp from 192.168.69.4 to 192.168.69.7 9091 in via $wanif
$cmd 00805 allow tcp from 192.168.69.7 9091 to 192.168.69.4 out via $wanif
$cmd 00805 deny tcp from any to 192.168.69.7 9091 in via $wanif

# All other Lomax traffic
$cmd 00805 allow all from any to 192.168.69.7 any in via $wanif
$cmd 00805 allow all from 192.168.69.7 any to any out via $wanif

Reiniciamos el servicio ipfw:

service ipfw restart


Acceso NFS cliente:

Desde mi pc podemos ver los recursos servidos por NFS:

showmount -e 192.168.69.2

Exports list on 192.168.69.2:  
/storage/torrents                  192.168.69.4

Montamos el recurso /storage/torrents:

mkdir -p /nfs/torrents
mount 192.168.69.2:/storage/torrents /nfs/torrents

Podemos automatizar el proceso mediante un sencillo script pero tendremos que concederle algunos permisos a nuestro usuario:

visudo

kr0m ALL=(ALL) NOPASSWD: /sbin/mount 192.168.69.2\:/storage/torrents /nfs/torrents  
kr0m ALL=(ALL) NOPASSWD: /sbin/umount /nfs/torrents

El script lo generaremos desde nuestro usuario kr0m:

vi nfs.sh

#!/usr/local/bin/bash
mount|grep '192.168.69.2:/storage/torrents'
if [ $? -eq 1 ]; then
  echo -e "-- Mounting NFS: /nfs/torrents"
  sudo /sbin/mount 192.168.69.2:/storage/torrents /nfs/torrents
else
  echo -e "-- Umouning NFS: /nfs/torrents"
  sudo /sbin/umount /nfs/torrents 
fi

Asignamos los permisos necesarios:

chmod 700 nfs.sh


Script descargas:

Transmission es capaz de ejecutar un script cada vez que finaliza una descarga, nuestro script enviará un Telegram con el nombre del torrent recién descargado y lo eliminará de la lista de torrents:

vi /usr/local/etc/transmission/home/notifyTorrentDownload.sh

#!/usr/local/bin/bash
function sendTelegram {
  message=${@:1}
  /usr/local/bin/curl -s -X POST https://api.telegram.org/botAPI_KEY/sendMessage -d chat_id=CHAT_ID -d text="$message"
}

tsm='/usr/local/bin/transmission-remote 192.168.69.7 --auth kr0m:PASSWORD'

DOWNLOADED=$($tsm -l | /usr/bin/awk '$2 == "100%" {print $10" "$11" "$12" "$13" "$14" "$15" "$16" "$17" "$18" "$19" "$20}')
IFS_ORI=$IFS
IFS=$'\n'
for TORRENT in $DOWNLOADED; do
	/bin/echo "TORRENT: $TORRENT"
  msg="Downloaded: $TORRENT"
  sendTelegram $msg
done

IFS=$IFS_ORI
DOWNLOADED_IDS=$($tsm -l | /usr/bin/awk '$2 == "100%" {print $1}')
for ID in $DOWNLOADED_IDS; do
	/bin/echo "ID: $ID"
  $tsm -t $ID -r
done

Asignamos los permisos necesarios y cambiamos el propietario del script:

chmod 700 /usr/local/etc/transmission/home/notifyTorrentDownload.sh
chown transmission:transmission /usr/local/etc/transmission/home/notifyTorrentDownload.sh

Paramos el servicio:

service transmission stop

Modificamos la configuración para que tenga en cuenta el script:

vi /usr/local/etc/transmission/home/settings.json

"script-torrent-done-enabled": true,  
"script-torrent-done-filename": "/usr/local/etc/transmission/home/notifyTorrentDownload.sh",

Arrancamos el servicio:

service transmission start

Cuando un torrent finalice recibiremos una notificación vía Telegram similar a la siguiente:


Debug:

Paramos el servicio:

service transmission stop

Arrancamos el servicio en foreground como root:

/usr/local/bin/transmission-daemon -g /usr/local/etc/transmission/home -f –log-debug

Cuando terminemos tendremos que rectificar algunos permisos de ficheros generados mientras el proceso estaba corriendo como root:

chown transmission:wheel /var/run/transmission/daemon.pid
chown -R transmission:transmission /storage/torrents/

Arrancamos de forma regular el servicio:

service transmission start

Transmission escribe sus logs en /var/log/messages, así que comprobamos en este fichero que no aparezca ningún error:

tail -f /var/log/messages

También es posible ejecutar comandos con el usuario transmission pero para ello tendremos que cambiar la shell temporalmente, ejecutar el comando y revertir el cambio:

chsh -s /usr/local/bin/bash transmission
su transmission -c “/usr/local/etc/transmission/home/notifyTorrentDownload.sh”
chsh -s /usr/sbin/nologin transmission

Si te ha gustado el artículo puedes invitarme a un RedBull aquí