Torrentflux, OpenBSD e Apache in Jail (chroot)

A pensarci bene, ci sono alcuni servizi di rete che sono da ritenersi “indispensabili”. Per servizi di questa tipologia è necessario poter disporre della massima sicurezza possibile.

A mio parere, sotto questo punto di vista, OpenBSD è sicuramente il sistema operativo adatto per eccellenza.

Ma qual’è, secondo voi, il servizio che più in assoluto è da ritenere critico?

Ovviamente il servizio di “download torrent” :)

Per un servizio come questo quindi è assolutamente d’obbligo utilizzare OpenBSD.

Basta scherzare, facciamo le persone serie.

Per chi non conoscesse torrentflux
Torrentflux è un frontend web per BitTornado scritto in php e come tutti i frontend che eseguono script per la scrittura di files su disco, sono spesso soggetti a pesanti vulnerabilità.

Perchè OpenBSD
Una caratteristica di questo SO è che Apache, il demone http, viene originariamente installato in una gabbia (jail) mediante la nota tecnica di chrooting, cioè di cambio della directory principale.

Questa tecnica di installazione non mira a rendere il server web più sicuro ma solamente a limitare i danni qualora ci fossero delle falle, questo perchè il servizio non è in grado di “vedere” l’intero disco ma solo una piccola parte.

Nello specifico, in OpenBSD, il servizio httpd è installato nella directory “/var/www“. Questa directory, grazie al chrooting diviene per il servizio la directory principale “/”. Poichè non è possibile risalire oltre la root di un filesystem ne consegue che il server web non è in grado di accedere ai file contenuti ad esempio in “/var”.

Installare torrentflux con queste restrizioni non è semplice perchè la gabbia inibisce l’uso di alcuni componenti essenziali come ad esempio python, necessario per eseguire il client BitTornado.

Navigando su Internet ho notato che non ci sono guide che spiegano come rendere possibile l’esecuzione di torrentflux all’interno della gabbia, così ho deciso di scrivere questo breve articolo.

Da Torrentflux a Torrentflux-b4rt
Una versione più avanzata di questo frontend si chiama torrentflux-b4rt. Questa guida può essere applicata tranquillamente a questa versione.

Cosa c’è da fare
La prima cosa che voglio mettere in chiaro è che è necessario dare ad Apache la possibilità di eseguire la shell. Questa è una cosa orrenda dal punto di vista della sicurezza ma non sono riuscito a trovare altre alternative. La spiegazione risiede nel fatto che torrentflux fa uso della funzione execute() di php per la quale pare che la shell sia indispensabile.

Detto questo, tutto quello che dobbiamo fare è rendere disponilibi i file necessari a torrentflux per poter eseguire correttamente il frontend.

Dando uno sguardo alla documentazione rilasciata insieme al software ed al codice sorgente, sono giunto alla conclusione che sono necessari i seguenti eseguibili:

sh;
awk;
du;
grep;
nice;
tar;
zip;
nohup;
python;
php (cli);

Per poter utilizzare questi eseguibili all’interno della gabbia però non è sufficiente copiarli nella cartella /var/www ma è necessario creare alcune directory e copiare alcune librerie.

Procediamo dunque con la creazione delle directory necessarie:

mkdir -p /var/www/bin
mkdir -p /var/www/usr/bin
mkdir -p /var/www/usr/lib
mkdir -p /var/www/usr/local/bin
mkdir -p /var/www/usr/local/lib
mkdir -p /var/www/usr/libexec
mkdir -p /var/www/etc
mkdir -p /var/www/tmp
chmod 777 /var/www/tmp

Le cartelle create possono tranquillamente appartenere al gruppo daemon con utente root, l’importante è che siano accessibili all’utente www (Apache).

A questo punto iniziamo a copiare i files necessari:

cp /bin/sh /var/www/bin/sh
cp /usr/bin/awk /var/www/bin/awk
cp /usr/bin/du /var/www/bin/du
cp /usr/bin/grep /var/www/bin/grep
cp /usr/bin/nice /var/www/bin/nice
cp /usr/bin/tar /var/www/bin/tar
cp /usr/bin/nohup /var/www/bin/nohup

Per capire se ci sono delle dipendenze per gli eseguibili che abbiamo appena copiato è possibile utilizzare il comando ldd aggiungendo come parametro l’eseguibile da verificare. Nel nostro caso grep ha bisogno di portare con se alcune librerie:

ldd /usr/bin/grep

/usr/bin/grep:
Start End Type Open Ref GrpRef Name
00000000 00000000 exe 1 0 0 /usr/bin/grep
073e9000 273f1000 rlib 0 1 0 /usr/lib/libz.so.4.1
0530f000 25343000 rlib 0 1 0 /usr/lib/libc.so.43.0
0da9b000 0da9b000 rtld 0 1 0 /usr/libexec/ld.so

Le librerie potrebbero avere nomi leggermente diversi, questo perchè le prove fatte per la scrittura di questo articolo prevedono l’uso di OpenBSD ver 4.3.
Dopo aver fatto questa verifica possiamo copiare le libreire nelle apposite locazioni:

cp /usr/bin/grep /var/www/usr/bin/grep
cp /usr/lib/libz.so.4.1 /var/www/usr/lib/libz.so.4.1
cp /usr/lib/libc.so.43.0 /var/www/usr/lib/libc.so.43.0
cp /usr/libexec/ld.so /var/www/usr/libexec/ld.so

Proseguiamo con la copia degli altri eseguibili necessari e delle relative librerie (ormai sapete come si fa):

cp /usr/local/bin/idle2.5 /var/www/usr/local/bin/idle2.5
cp /usr/local/bin/php /var/www/usr/local/bin/php
cp /usr/local/bin/zip /var/www/usr/local/bin/zip
cp /usr/local/bin/pydoc2.5 /var/www/usr/local/bin/pydoc2.5
cp /usr/local/bin/python2.5 /var/www/usr/local/bin/python2.5

Adesso creiamo un link simbolico all’eseguibile python2.5 tenendo a mente che il link dovrà essere dinamico altrimenti non funzionerà all’interno della nostra gabbia:

cd /var/www/usr/local/bin
ln -s python2.5 python

Un discorso ancora diverso deve essere fatto per le librerie di python. Usare semplicemente la tecnica descritta in precedenza non è sufficiente. Facendo una ricerca su Internet ho trovato un ineressante articolo che mi ha dato una mano in questo senso. Quando capitano problemi di questo tipo il mio consiglio è quello di verificare la gabbia per vedere se tutto funziona correttamente:

# chroot -u www /var/www /bin/sh
/bin/sh: No controlling tty (open /dev/tty: No such file or directory)
/bin/sh: warning: won’t have full job control

Tralasciate pure l’errore dovuto alla mancanza della cartella /dev.
Comunque sia, dopo alcuni tentativi che vi risparmio sono riuscito ad individuare le libreirie necessarie per l’esecuzione di python:

cp /usr/local/lib/libiconv.so.4.0 /var/www/usr/local/lib/libiconv.so.4.0
cp /usr/local/lib/libintl.so.4.0 /var/www/usr/local/lib/libintl.so.4.0
cp /usr/local/lib/libpython2.5.so.0.0 /var/www/usr/local/lib/libpython2.5.so.0.0
cp /usr/local/lib/libxml2.so.9.7 /var/www/usr/local/lib/libxml2.so.9.7
cp /usr/local/lib/python2.5 /var/www/usr/local/lib/python2.5
cp /usr/lib/libcrypto.so.13.0 /var/www/usr/lib/libcrypto.so.13.0
cp /usr/lib/libm.so.2.3 /var/www/usr/lib/libm.so.2.3
cp /usr/lib/libncurses.so.10.0 /var/www/usr/lib/libncurses.so.10.0
cp /usr/lib/libpanel.so.3.0 /var/www/usr/lib/libpanel.so.3.0
cp /usr/lib/libpthread.so.9.0 /var/www/usr/lib/libpthread.so.9.0
cp /usr/lib/libpython2.5.so.0.0 /var/www/usr/lib/libpython2.5.so.0.0
cp /usr/lib/libssl.so.11.0 /var/www/usr/lib/libssl.so.11.0
cp /usr/lib/libstdc++.so.44.0 /var/www/usr/lib/libstdc++.so.44.0
cp /usr/lib/libutil.so.11.0 /var/www/usr/lib/libutil.so.11.0

Spero di non aver dimenticato dipendenze ma in questo periodo non ho tanto tempo da dedicare al blog, se doveste trovare inesattezze provate a scrivere due righe, io provvederò a correggere il testo.

Rimane ancora una cosa da fare: copiare il file resolv.conf altrimenti BitTornado non sarà in grado di risolvere gli indirizzi IP:

cp /etc/resolv.conf /var/www/etc/resolv.conf

Prima di concludere volevo dire che nel presente documento non sono stati considerati tutti i comandi necessari a torrentflux, alcuni li ho volutamente lasciati fuori perchè li reputo pericolosi e di poca utilità (vedi ps usato per mostrare i processi in esecuzione sul server).

Per saperne di più
Chroot (wikipedia)
OpenBSD (FAQ)

OmniFind e Fedora Core 6

Tempo fa ho comprato un hard disk da mezzo tera in un centro commerciale della mia città.
Piano piano l’ho riempito di files di ogni genere: backup, posta, sorgenti, progetti, distribuzioni linux, …

In breve tempo non ero più in grado di trovare facilmente i files che mi servivano.
Così le soluzioni al problema erano due:

- Mettere in ordine l’archivio e darsi un metodo per copiare i files

- Trovare un piccolo crowler a cui richiedere i files quando servono.

Forse non tutti sanno cos’è un crowler. In parole povere si tratta di un software che indicizza le risorse in rete e le rende disponibili ad un motore di ricerca.

Ovviamente ho optato per la seconda opzione.

Durante una delle tante presentazioni sul software alle quali assisto per lavoro, sono venuto a conoscenza di Google Mini, un motore di ricerca per le aziende mantenuto da Google.
Non si tratta di un pacchetto gratuito anche perchè viene venduto insieme all’hardware su cui “gira” il motore di ricerca.

Dopo varie ricerche sono incappato su una soluzione di IBM e Yahoo! Search.

Sto parlando di OmniFind, un crowler scritto in Java e disponibile per Windows e Linux.

Ho deciso di provarlo subito ma purtroppo il supporto per Linux è limitato alla distribuzione di Red Hat Enterprise.

Questo significa che è possibile eseguire OmniFind su altre distribuzioni ma è necessario apportare le dovute modifiche al processo di installazione.

La prima cosa da fare in assoluto è disabilitare Selinux in caso sia attivo nell’ambiente operativo altrimenti l’installazione non si concluderà correttamente. Provvederemo in un secondo momento a riabilitarlo.
Chi non avesse impostato Selinux all’avvio del SO può tranquillamente ignorare i comandi che seguono.
Fedora Core mette a disposizione un semplice modo per disabilitare temporaneamente Selinux:

setenforce 0

Per verificare che il comando abbia sortito l’effetto desiderato, procediamo con una verifica:

cat /selinux/enforce

Il comando precedente dovrà restituire 0.

A questo punto è utile creare un utente di sistema con il quale eseguiremo il programma (non è consigliabile eseguire il crowler con le credenziali di root anche perchè non c’è ne la necessità):

groupadd omnifind
useradd -g omnifind omnifind
passwd omnifind

Una volta definita la password per l’utente omnifind procediamo oltre.

OmniFind utilizza una propria Java Virtual Machine, di conseguenza non è necessario installare Java sul SO. Tuttavia il crowler fa uso di librerie condivise, in particolare è necessario disporre di libstc++. Un semplice comando yum list dovrebbe essere sufficiente per fare un controllo. Per installare le librerie possiamo impartire il seguente comando:

yum install compat-libstdc++*

Adesso è possibile procedere con l’installazione di OmniFind seguendo le istruzioni incluse nel manuale del software. Prima di procedere però sostituiamo l’utente omnifind all’utente root.

su omnifind
./setuplinux_i586.bin -console

Il comando precedente prevede una installazione per la riga di comando. Chi volesse procedere in ambiente X può omettere il parametro -console.
Nel caso in cui l’installazione non andasse a buon fine, verificare che l’utente omnifind abbia i permessi di scrittura nella cartella prescelta per l’installazione.

Utilizzando i parametri di default, la directory di installazione dovrebbe essere: /opt/ibm/OmniFindYahooEdition, di conseguenza questa sarà la directory a cui faremo riferimento nei comandi successivi.

Qualora l’applicativo funzionasse alla fine dell’installazione, ritenetevi persone molto fortunate, nel mio caso infatti sono stati necessari altri passaggi.

Nel caso in cui l’esecuzione del programma non vada a buon fine, procediamo con alcune verifiche.
In primo luogo verifichiamo che tutte le librerie siano collegate correttamente:

ldd /opt/ibm/OmniFindYahooEdition/stellent.linux32/tsmanager

L’output dovrebbe essere simile al seguente:

linux-gate.so.1 => (0×00110000)
libpthread.so.0 => /lib/libpthread.so.0 (0x491c2000)
libACE.so.5.5.1 => /opt/…/stellent.linux32/libACE.so.5.5.1 (0×00125000)
libboost_date_time-gcc-mt-1_33_1.so.1.33.1 => /opt/…/stellent.linux32/libboost_date_time-gcc-mt-1_33_1.so.1.33.1 (0x0029b000)
libboost_filesystem-gcc-mt-1_33_1.so.1.33.1 => /opt/…/stellent.linux32/libboost_filesystem-gcc-mt-1_33_1.so.1.33.1 (0x002a9000)
libboost_program_options-gcc-mt-1_33_1.so.1.33.1 => /opt/…/stellent.linux32/libboost_program_options-gcc-mt-1_33_1.so.1.33.1 (0x002b9000)
libboost_regex-gcc-mt-1_33_1.so.1.33.1 => /opt/…/stellent.linux32/libboost_regex-gcc-mt-1_33_1.so.1.33.1 (0x002fd000)
libboost_serialization-gcc-mt-1_33_1.so.1.33.1 => /opt/…/stellent.linux32/libboost_serialization-gcc-mt-1_33_1.so.1.33.1 (0x0038f000)
libboost_signals-gcc-mt-1_33_1.so.1.33.1 => /opt/…/stellent.linux32/libboost_signals-gcc-mt-1_33_1.so.1.33.1 (0×00408000)
libdl.so.2 => /lib/libdl.so.2 (0x4cfdb000)
libts_utils.so => /opt/…/stellent.linux32/libts_utils.so (0x0041a000)
libts_logging_facility.so => /opt/…/stellent.linux32/libts_logging_facility.so (0×00431000)
libts_components.so => /opt/…/stellent.linux32/libts_components.so (0×00451000)
libts_soap_ext.so => /opt/…/stellent.linux32/libts_soap_ext.so (0×00461000)
libts_soap_ts_server.so => /opt/…/stellent.linux32/libts_soap_ts_server.so (0x004c9000)
libts_soap_ta_server.so => /opt/…/stellent.linux32/libts_soap_ta_server.so (0x0052f000)
libts_soap_ts_client.so => /opt/…/stellent.linux32/libts_soap_ts_client.so (0x0059e000)
libts_soap_std.so => /opt/…/stellent.linux32/libts_soap_std.so (0×00604000)
libts_soap_tss.so => /opt/…/stellent.linux32/libts_soap_tss.so (0×00687000)
libts_soap_ta_client.so => /opt/…/stellent.linux32/libts_soap_ta_client.so (0x006ea000)
libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0×00758000)
libm.so.6 => /lib/libm.so.6 (0x4cfe1000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x4d149000)
libc.so.6 => /lib/libc.so.6 (0x4ce99000)
/lib/ld-linux.so.2 (0x4ce7c000)
librt.so.1 => /lib/librt.so.1 (0x4447d000)

Nel caso in cui qualche libreria dovesse mancare, verifichiamo che selinux sia disabilitato e che libstc++ sia installato sul SO; quindi seguiamo le istruzioni riportate nel manuale per reinstallare OmniFind.

Se il servizio iptables è in uso da Linux, verifichiamo che la porta definita per contattare OmniFind sia accessibile. Di seguito le impostazioni da aggiungere al file /etc/sysconfig/iptables per abilitare i client a contattare il servizio sulla porta di default proposta dall’installazione (inserire prima del COMMIT):

-A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport 8080 -j ACCEPT

Se anche in questo caso l’applicativo non parte, assicuriamoci che nel file /etc/hosts sia indicata la voce localhost:

::1 mycomputer.mydomain mycomputer localhost.localdomain localhost
127.0.0.1 localhost.localdomain localhost

Se il problema persiste, scrivete due righe sul problema, tenteremo insieme una soluzione.

Una volta che il servizio “parte” senza problemi, è necessario modificare le policy di selinux.
Chi avesse impostato selinux in modalità permissive può trovare tutte le modifiche da apportare dando uno sguardo ai log di sistema:

cat /var/log/messages | grep audit

chi avesse impostato Selinux in modalità enforced dovrà invece procedere per tentativi successivi.
In pratica si tratta di abilitare l’utente omnifind alla esecuzione delle librerie java. Evidenziamo di seguito i comandi impratiti da console per una singola libreria:

semanage fcontext -a -t textrel_shlib_t
/opt/ibm/OmniFindYahooEdition/_jvm/jre/bin/headless/LIBRERIA.so
restorecon /opt/ibm/OmniFindYahooEdition/_jvm/jre/bin/headless/LIBRERIA.so

Dove LIBRERIA è il nome del file inibito da Selinux.

A questo punto possiamo ripristinare selinux:

setenforce 1

Fare partire il servizio all’avvio:
Di seguito riportiamo una possibile soluzione per chi volesse far partire il crowler all’avvio di Linux:

cat > /etc/rc.d/init.d/omnifind <<EOF
#!/bin/sh
#
# chkconfig: – 99 31
# description: Starts and stops the Omnifind daemon \
#

# Source function library.
if [ -f /etc/init.d/functions ] ; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
else
exit 0
fi

# Avoid using root’s TMPDIR
unset TMPDIR

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0

RETVAL=0

start() {
   KIND=”Omnifind”
   echo -n $”Starting $KIND service: “
   su -c /opt/ibm/OmniFindYahooEdition/bin/startup.sh omnifind
   RETVAL=$?
   echo
   return $RETVAL
}

stop() {
   KIND=”Omnifind”
   echo -n $”Shutting down $KIND services: “
   su -c /opt/ibm/OmniFindYahooEdition/bin/shutdown.sh omnifind
   RETVAL=$?
   echo
   return $RETVAL
}

restart() {
   stop
   start
}

case “$1″ in
start)
   start
   ;;
stop)
   stop
   ;;
restart)
   restart
   ;;
*)
   echo $”Usage: $0 {start|stop|restart}”
   exit 1
esac

exit $?
EOF

Il precedente comando consente di gestire Omnifind tramite chkconfig.
Per installare lo script è sufficiente impartire i seguenti comandi:

chmod 755 /etc/rc.d/init.d/omnifind
chkconfig –add omnifind
chkconfig –level 345 omnifind on

Considerazioni finali:
Secondo me OmniFind è un tool utile per le piccole aziende, almeno nella sua versione free.
Da tenere in considerazione che questa versione non gestisce la segregazione dei dati a nessun livello, di conseguenza, chi riesce a contattare il motore di ricerca, può ottenere tutti i dati indicizzati, senza discriminazioni.
E’ molto comodo da usare e riesce a tracciare il contenuto di: file PDF, files Word, files Compressi e siti web interni ed esterni alla rete locale.

Per saperne di più:
OmniFind Home Page
Cos’è un crowler