Come realizzare un server Freenet
(07/02/2002)
(winstonsmith@nym.alias.net)
Copyright (c) 2002 del Progetto Winston Smith.
È garantito il permesso di copiare,
distribuire e/o modificare questo documento
seguendo i termini della GNU Free Documentation
License, Versione 1.1
pubblicata dalla Free Software Foundation;
con le tutte le Sezioni Non Modificabili.
Una copia della licenza è acclusa nel file
COPYING, distribuito insieme a questo documento.
Un server Freenet è un computer, connesso permanentemente ad Internet, che scambia file (chiavi, nella terminologia Freenet) con altri server Freenet e li acquisisce o li fornisce agli utenti che utilizzano un client apposito od un proxy.
Un server Freenet gira due servizi specializzati che ascoltano su due porte TCP fisse; il server non può funzionare dietro un firewall, a meno che il firewall stesso non venga bucato sull'ip e sulle porte del server, o comunque configurato in modo particolare.
Può essere utilizzata una qualunque macchina 486 o superiore dotata di GNU/Linux con almeno 32 mb ram (senza X) ed almeno 512 mb di spazio su disco; CPU pentium, clock maggiori e più ram non infastidiscono certo, ed un pentium 133, 64 Mb di ram e 2 Gb di disco sono una configurazione performante.
Una certa attenzione deve essere posta alla banda che il server Freenet potrà impiegare; infatti i server Freenet scambiano continuamente files tra loro, e questo provoca un consumo di banda non prevedibile a priori.
Nel programma di setup e nel file di configurazione è previsto una limite superiore della banda occupabile; un buon valore di tentativo è metà della banda di cui si dispone.
Ad esempio 16 kbit/sec per un modem analogico, 32 per un ISDN monocanale, 64 per un bicanale, e così via.
Normalmente l'occupazione media di banda è molto minore del valore massimo, ed è comunque opportuno controllarne il consumo effettivo; non esiste un'utility che faccia questo, ed è necessario basarsi su parametri indiretti, come l'evoluzione della dimensione del datastore od un controllo diretto dei pacchetti.
Si noti che non è possibile conoscere a priori i server con cui avvengono le connessioni; il meccanismo di routing e di scoperta dei server è automatico e volutamente non prevedibile e/o tracciabile.
Freenet esiste attualmente in due versioni; la versione 0.3, stabile e non più sviluppata (ultima versione 0.3.9.2) e la versione in sviluppo 0.4, che diverràà 0.5 una volta stabilizzata.
Attualmente la versione 0.3 è l'unica che riesce a conservare contenuti, ma il numero di server sta diminuando rapidamente; conviene quindi usarla solo per progetti che necessitino da subito di una totale stabilità di contenuti.
Probabilmente quando leggerete questo documento la 0.4 sarà abbastanza stabile e popolata di contenuti da poter essere installata direttamente, permettendo di sfruttare le nuove features che possiede rispetto alla 0.3 (autenticazione dei nodi, split files, nodestatus, etc.)
La versione 0.3 è costituita da due servizi; il primo servizio, che è il server vero e proprio, è il processo che gestisce la memorizzazione ed il recupero delle chiavi; questo processo deve girare su una porta fissa e visibile da Internet, che può essere decisa dall'utente, e che è per default la 19114.
Il secondo è un servizio proxy, normalmento configurato sulla porta 8081/TCP, che permette di utilizzare il server via un normale browser web.
L'installazione di ambedue servizi, anche se consigliata, non è indispensabile; il server può infatti girare anche senza proxy.
Per comunicazioni interprocesso, su 127.0.0.1 vengono utilizzate le porte 8082 per il protocollo fcp e 6690 per il protocollo xmlrpc.
La versione 0.4 è fondamentalmente costituita dagli stessi 4 processi suddetti, che girano però su porte diverse per consentire la eventuale coesistenza di 0.3 e 0.4 sullo stesso server; le porte usate, nello stesso ordine, sono 20971, 8888, 8481 e 8082. Sulla porta 8889 si trova poi un proxy che visualizza un'utilissima pagina diagnostica e di status, che permette di monitorare il funzionamento del nodo ed alcune semplici operazioni di amministrazione.
L'installazione di un server freenet richiede, oltre ai più comuni componenti di GNU/Linux, un java runtime environment (jre) e le librerie libgmp e libncurses.
Nel caso si preferisca installare solo software libero, si deve obblgatoriamente usare il jre Kaffe 1.0.6, altrimenti è possibile usare diverse jre o jvm commerciali o free; tra questi il più collaudato è il jre Sun 1.3.1 o superiore.
Il server richiede l'utilizzo di una cache su disco, che può in teoria avere qualunque dimensione; un server che voglia avere utilità per la Freenet deve dedicare assolutamente non meno di 512 Mb, meglio se 1 - 2 Gb.
Il termine con cui si identifica la cache di Freenet è "Datastore"; il datastore nella versione 0.3.x.x di Freenet è una directory che viene creata e gestita direttamente dal server, che la alloca su una path di default oppure sulla path che è indicata nel file di configurazione.
La versione 0.4.x.x e successive allocano invece un unico file di database, che viene gestito direttamente dal server.
Per questo motivo, nel caso di Freenet 0.4, se non si è sicuri della capacità della propria installazione di Linux di gestire file più grandi di 2 Gb, è bene stare leggermente al di sotto di questo valore, scegliendo ad esempio una dimensione di 1.9 Gb.
Per poter superare il limite dei 2 Gb, è necessario che non solo il filesystem che viene utilizzato lo supporti (e, per l'ext2, ormai questo è vero per quasi tutte le distribuzioni) ma anche tutte le altre componenti, incluso ad esempio vfs, utility e libc.
Il server Freenet, come tutti i servizi che devono stare in ascolto su una porta aperta verso internet, sono suscettibili di attacchi di vario tipo, dai classici buffer overrun in avanti.
Vero è che Freenet, essendo scritto in Java, dovrebbe teoricamente beneficiare delle sicurezze dovute al fatto di girare all'interno di una jvm; la lunga serie di problemi di sicurezza che le varie jvm hanno avuto, unita alla "giovinezza" del codice di Freenet, che non è particolarmente testato a livello di sicurezza, consigliano i sistemisti accorti ad eseguire l'installazione in un ambiente chrooted.
Un ambiente chrooted è un sottoinsieme del filesystem, che viene visto dal processo che lo usa come se fosse l'intero filesystem; inquesto modo, anche se un attaccante riuscisse a compromettere il server, ottenendo ad esempio una shell, si ritroverà in un sistema che non contiene tutti i programmi che formano un sistema unix, e non dovrebbe quindi essere in grado di fare ulteriori danni.
Per questo motivo l'installazione spiegata in questo documento è esclusivamente quella in ambiente chrooted; chi volesse eseguire un'installazione normale (a rischio e pericolo suo e dei suoi utenti) potrà comunque facilmente estrarre i pochi passi necessari.
0) Requisiti
------------
Questo documento descrive un possibile metodo per l'installazione
e la messa in linea di un nodo freenet (http://freenet.sourceforge.net)
versione 0.3.x o 0.4.x, con le seguenti caratteristiche:
- esecuzione in ambiente chrooted sotto utente dedicato;
- uso del java runtime environment libero Kaffe (http://www.kaffe.org);
- accesso al gateway web con protocollo sicuro ssl.
Il sistema ospite di riferimento è un sistema GNU/Linux su
architettura Intel i386 con i seguenti requisiti:
- kernel 2.4.x
- glibc 2.2.3 o superiore
- gcc 2.95
- iptables
- libgmp 3.1.1 o superiore
- kaffe 1.0.6
- openssl 0.9.6a
- stunnel 3.22 (http://www.stunnel.org)
Componenti facoltativi:
- daemontools 0.76 (http://cr.yp.to - non libero)
- ucspi-tcp 0.88 (http://cr.yp.to - non libero)
1) Preparazione del sistema
---------------------------
- Creare la directory /fnroot, che costituirà la chroot jail
dentro cui girerà il nodo.
# mkdir /fnroot
- Creare l'utente fnrun, sotto il quale girerà il nodo. Questo
utente non ha bisogno di una shell, ma questa potrebbe essere
necessaria per alcune fasi dell'installazione, per cui
assegnategliene una temporaneamente.
2) Compilazione ed installazione di kaffe
-----------------------------------------
- Compilare ed installare se necessario la libreria gmp
(pacchetti runtime e development)
- Decomprimere l'albero dei sorgenti di kaffe in ~/kaffe-1.0.6
- Editare ~/kaffe-1.0.6/libraries/clib/math/BigInteger.c
come segue:
- return ((jint)mpz_get_si(src));
+ return ((jint)mpz_get_ui(src));
- Configurare con prefix=/kaffe e compilare
$ ./configure --prefix=/kaffe
$ make all
$ /bin/su
# make install
Assicurarsi che kaffe sia stato compilato correttamente con il
supporto gmp, controllare allo scopo l'output di configure
- Spostare l'intero albero /kaffe sotto /fnroot
# mv /kaffe /fnroot
3) Installazione di Freenet
---------------------------
- Decomprimere la distribuzione di freenet in /fnroot
# cd /fnroot
# tar xvfz freenet-0.(3|4).x.x.tar.gz
- La distribuzione di Freenet si trova ora in /fnroot/Freenet
# chown -R root.root /fnroot/Freenet
# chown fnrun /fnroot/Freenet
Questo è necessario affinché l'utente fnrun sia in grado di
creare i file di lavoro dentro /fnroot/Freenet, dopo la prima
esecuzione del nodo freenet è vivamente consigliabile
effettuare un
# chown root /fnroot/Freenet
- Allestire le directory /fnroot/bin, /fnroot/lib, /fnroot/dev,
/fnroot/etc come segue
# mkdir /fnroot/bin
# cd /fnroot/bin
# cp /bin/bash .
# ln -s bash sh
# ln -s ../kaffe/bin/java
# mkdir /fnroot/lib
- Copiare da /lib a /fnroot/lib le opportune librerie in modo che il
contenuto finale risulti:
# ls -l /fnroot/lib
-rwxr-xr-x 1 root root 432647 Dec 25 11:06 ld-linux.so.2
-rwxr-xr-x 1 root root 4783716 Dec 25 11:06 libc.so.6
-rwxr-xr-x 1 root root 72701 Dec 25 11:06 libdl.so.2
-rwxr-xr-x 1 root root 161459 Dec 25 11:07 libgmp.so.3
-rwxr-xr-x 1 root root 561250 Dec 25 11:06 libm.so.6
-rwxr-xr-x 1 root root 282178 Dec 25 11:06 libncurses.so.5
-rwxr-xr-x 1 root root 75894 Dec 25 11:06 libnss_dns.so.2
-rwxr-xr-x 1 root root 238649 Dec 25 11:06 libnss_files.so.2
-rwxr-xr-x 1 root root 295936 Dec 25 11:06 libnss_nis.so.2
-rwxr-xr-x 1 root root 298005 Dec 25 11:06 libnss_nisplus.so.2
-rwxr-xr-x 1 root root 225681 Dec 25 11:06 libresolv.so.2
-rwxr-xr-x 1 root root 14831 Dec 25 16:35 libtermcap.so.2
(alcune di queste librerie potrebbero non essere necessarie).
- Creare i devices null, random, urandom in /fnroot/dev
# mkdir /fnroot/dev
# cd /fnroot/dev
# mknod null c 1 3
# mknod random c 1 8
# mknod urandom c 1 9
- I diritti dovranno essere i seguenti:
# ls -l /fnroot/dev
crw-rw-rw- 1 root root 1, 3 Mar 26 16:05 null
cr--r--r-- 1 root root 1, 8 Mar 26 16:06 random
cr--r--r-- 1 root root 1, 9 Mar 26 16:06 urandom
- Allestire /fnroot/etc
# mkdir /fnroot/etc
# cd /fnroot/etc
# cp /etc/resolv.conf .
# cp /etc/hosts .
# cp /etc/host.conf .
- Creare la directory /fnroot/tmp ed assegnare diritto di scrittura a fnrun
# mkdir /fnroot/tmp
# chown fnrun /fnroot/tmp
4.1) Wrapper per freenet 0.3.x
------------------------------
Compilare il seguente programmino "fnstart.c". Editare a piacere
le costanti DIR, USER, NICE se avete scelto directory radice,
nome utente o livello di nice del processo diversi, rispettivamente.
----- CUT HERE ------
/* fnstart.c
This program is released under the GNU GPL
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#define DIR "/fnroot"
#define USER "fnrun"
#define FNDIR "/Freenet"
#define JAVA "/bin/java"
#define CMD "Freenet.node.Node"
#define NICE 5
main() {
struct passwd *p;
if ((p=getpwnam(USER)) == NULL) {
fprintf(stderr,"Can't find user "USER"\n");
exit(1);
}
if (chroot(DIR) == -1) {
perror("chroot to "DIR" failed");
exit(1);
}
if (setgid(p->pw_gid) == -1) {
perror("setgid failed");
exit(1);
}
if (setuid(p->pw_uid) == -1) {
perror("setuid to "USER" failed");
exit(1);
}
if (chdir(FNDIR) == -1) {
perror("Can't chdir to "FNDIR);
exit(1);
}
if (nice(NICE) == -1) {
perror("nice failed");
exit(1);
}
if (setenv("CLASSPATH",FNDIR"/freenet.jar",1)) {
fprintf(stderr,"Can't set CLASSPATH");
exit(1);
}
execl(JAVA,"java",CMD,NULL);
perror("Can't exec "JAVA);
----- CUT HERE -----
# gcc -o fnstart fnstart.c
# cp fnstart /fnroot/bin
4.2) Wrapper per freenet 0.4.x
------------------------------
Compilare il seguente programmino "fn4start.c". Editare a piacere
le costanti DIR, USER, NICE se avete scelto directory radice,
nome utente o livello di nice del processo diversi, rispettivamente.
----- CUT HERE -----
/* fn4start.c
This program is released under the GNU GPL
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#define DIR "/fnroot"
#define USER "fnrun"
#define FNDIR "/Freenet"
#define JAVA "/bin/java"
#define CMD "freenet.node.Main"
#define NICE 5
main() {
struct passwd *p;
char buf[10];
int fd;
int s;
if ((p=getpwnam(USER)) == NULL) {
fprintf(stderr,"Can't find user "USER"\n");
exit(1);
}
if (chroot(DIR) == -1) {
perror("chroot to "DIR" failed");
exit(1);
}
if (setgid(p->pw_gid) == -1) {
perror("setgid failed");
exit(1);
}
if (setuid(p->pw_uid) == -1) {
perror("setuid to "USER" failed");
exit(1);
}
if (chdir(FNDIR) == -1) {
perror("Can't chdir to "FNDIR);
exit(1);
}
if (nice(NICE) == -1) {
perror("nice failed");
exit(1);
}
if (setenv("CLASSPATH",FNDIR"/lib/freenet.jar:"FNDIR"/lib/freenet-ext.jar",1)) {
fprintf(stderr,"Can't set CLASSPATH");
exit(1);
}
execl(JAVA,"java",CMD,NULL);
perror("Can't exec "JAVA);
----- CUT HERE -----
5) Avvio
--------
- Create i file di configurazione del nodo secondo documentazione.
Per freenet 0.4, dovrete lanciare start-freenet.sh sotto utente fnrun
in modo da creare i file di lavoro con i giusti permessi.
Per evitare di incasinarsi con CLASSPATH e percorsi vari, provate ad
applicare questo diff a start-freenet.sh prima di lanciarlo per la
configurazione. Se la directory radice è /fnroot dovrebbe andare.
----- CUT HERE -----
--- start-freenet.sh Thu Jan 17 20:10:24 2002
+++ ../start-freenet.sh Fri Jan 18 19:22:12 2002
@@ -1,5 +1,7 @@
#!/bin/bash
+export CLASSPATH=lib/freenet.jar:lib/freenet-ext.jar
+
# Check for library files
if test ! -f lib/freenet.jar; then
echo lib/freenet.jar not found. You must run "make jar" before running
@@ -20,8 +22,8 @@
else
./preconfig.sh
fi
- java -cp lib/freenet.jar:lib/freenet-ext.jar freenet.node.Main --config
+ /fnroot/bin/java freenet.node.Main --config
echo "Running Freenet..."
fi
-java -cp lib/freenet.jar:lib/freenet-ext.jar freenet.node.Main $@
+/fnroot/bin/java freenet.node.Main $@
----- CUT HERE -----
- Per avviare il nodo, eseguite fnstart da root
(NON RENDETE fnstart SUID ROOT o una potentissima maledizione
vi colpirà inesorabilmente :) )
# cd /fnroot/bin
# ./fn(4)start
- A questo punto il nodo freenet dovrebbe girare correttamente in
ambiente chrooted (il processo non va in background, tenetelo
presente se lo lanciate da rc.local o simili).
- Ripristinate i diritti di /fnroot/Freenet
# chown root /fnroot/Freenet
6) Esecuzione del nodo attraverso il supervisore dei daemontools
(facoltativo)
----------------------------------------------------------------
- Installare i daemontools secondo istruzioni
- Creare /service/freenet/run come segue
----- CUT HERE -----
#!/bin/sh
cd /fnroot/bin
exec ./fn(4)start
----- CUT HERE -----
7) Tunnelizzazione del gateway via ssl
--------------------------------------
Si tratta di una semplice applicazione di stunnel.
- Installate openssl e stunnel (ad es. in /usr/sbin)
- Create un certificato ssl per il servizio freenet gateway, potete
utilizzare lo script che segue. Se non lo fate, tenete presente
che siccome faremo girare stunnel sotto utente nobody, il
certificato dovrà essere leggibile da quell'utente.
----- CUT HERE -----
#!/bin/sh -e
echo If you want your certificate to expire after x days call this program
echo with "-days x"
export RANDFILE=/dev/random
openssl req $@ \
-new -x509 -nodes -out /etc/ssl/certs/fnet.pem \
-keyout /etc/ssl/certs/fnet.pem
chown root.nogroup /etc/ssl/certs/fnet.pem
chmod 640 /etc/ssl/certs/fnet.pem
----- CUT HERE -----
- Supponiamo che il gateway debba essere accessibile attraverso la
porta 443/tcp (standard https)
- Se utilizzate il superserver inetd
- Create una entry in /etc/services
https 443/tcp
- Inserite in /etc/inetd.conf
https stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/stunnel \
stunnel -p /etc/ssl/certs/fnet.pem -r localhost:<port>
dove <port> è la porta su cui ascolta il gateway web (tipicamente
8081 per freenet 0.3.x e 8888 per 0.4.x)
- Potete utilizzare un tcp server dedicato. Con ucspi-tcp, ad esempio,
/usr/local/ucspi-tcp/bin/tcpserver -g 99 -u 99 0.0.0.0 443 \
/usr/sbin/stunnel -p /etc/ssl/certs/fnet.pem -r localhost:<port>
- Naturalmente è consigliabile bloccare le connessioni sulle porte
normalmente utilizzate dal gateway freenet (tipicamente 8081 per 0.3
e 8888:8889 per 0.4, la 8889 è usata per la diagnostica, potete,
volendo, tunnelizzare anche le connessioni su quella.)
Potete far questo con regole standard di iptables che lascino
passare solo connessioni provenienti da localhost.
Happy freenet-ing. ;)