mod_evasive è un altro modulo di Apache in grado di aumentare la sicurezza del sistema proteggendoci da attacchi DOS e D-DOS sulla porta 80.
Gli attacchi di tipo DOS e D-DOS (Denial of Services e Distributed Denial of Services) sono attacchi atti a rendere inaccessibili i sistemi a causa di un intenso traffico dati. Grazie a questo modulo, però, riusciamo a prevenire questo tipo di attacco quando viene rivolto ad Apache in quanto il modulo tiene traccia del numero di connessioni provenienti da un determinato IP e, in caso di superamento della soglia, interviene bloccandole.
Per installare il modulo su Debian/Ubuntu è sufficiente lanciare il comando:

apt-get install libapache2-mod-evasive

Quindi creiamo la directory per i log:

mkdir -p /var/log/apache2/evasive
chown -R www-data:root /var/log/apache2/evasive

Ora creiamo un file di configurazione per il modulo:

/etc/apache2/conf.d/modevasive.conf
<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 5
DOSSiteCount 100
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 600
DOSLogDir "/var/log/apache2/evasive"
</IfModule>

e riavviamo Apache:

/etc/init.d/apache2 restart

Per collaudare il funzionalmento del modulo, c’è un semplice script perl incluso con la documentazione:

# perl /usr/share/doc/libapache2-mod-evasive/examples/test.pl
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 403 Forbidden
HTTP/1.1 200 OK
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
 

mod_security è un modulo di apache che ci aiuta a rendere il sistema più sicuro attraverso un Web Application Firewall.
Il Web Application Firewall (per gli amici WAF) è un filtro che controlla il traffico da e verso il webserver identificando possibili atticchi di alto livello come SQL Injection, Cross-Site scripting e simili.
L’utilizzo di mod_security deve essere però ponderato attentamente in quanto influisce negativamente sulle prestazioni globali del sistema e aumenta i consumi di risorse.
Quasi tutte le maggiori distribuzioni hanno un pacchetto precompilato per mod_security; in qualsiasi caso, trattandosi di un sistema che viene aggiornato con elevata frequenza, è preferibile non usare il pacchetto precompilato ma procedere con la compilazione. Questo perchè può capitare che le ultime regole non siano compatibili con versioni più anziane del modulo.

Installazione del modulo e delle regole
Il sistema si compone di due pacchetti: un pacchetto da compilare con il modulo di apache e un secondo pacchetto con le regole, simile alle definizioni di un antivirus.
Iniziamo con l’installazione dei prerequisiti: in questo caso propongo la sintassi di Debian/Ubuntu.
libapr e libapr-util

apt-get install libapr1 libapr1-dev libaprutil1 libaprutil1-dev

libpcre

apt-get install libpcre3 libpcre3-dev

libxml2

apt-get install libxml2 libxml2-dev

liblua

apt-get install liblua5.1-0 liblua5.1-0-dev

libcurl

apt-get install libcurl4-openssl-dev libcurl3-dbg

le librerie di sviluppo di apache:

apt-get install apache2-dev

i tools per lo sviluppo

apt-get install build-essential

i prerequisiti di Perl

apt-get install liblwp-useragent-determined-perl libgnupg-perl libcrypt-ssleay-perl

Infine è necessario abilitare il module mod_uniqueid

a2enmod unique_id

Dal sito http://www.modsecurity.org/ procediamo al download del modulo (al momento l’ultima versione disponibile è la 2.6.3) e scompattiamo il sorgente:

cd /usr/local/src
wget http://www.modsecurity.org/download/modsecurity-apache_2.6.3.tar.gz
tar zxvf modsecurity-apache_2.6.3.tar.gz
cd modsecurity-apache_2.6.3

Quindi passiamo alla compilazione e all’installazione del modulo:

./configure && make && make mlogc && make install

A questo punto avrete il modulo compilato e già installato nella directory corretta (/usr/lib/apache2/modules/mod_security2.so)

Ora è il turno delle regole CRS base (in questo caso l’ultima versione è la 2.2.3); il sito ufficiale rimanda a SourceForge: scaricate il pacchetto in /usr/local/src, scompattatelo e spostatelo nella direcory corretta con:

tar zxvf modsecurity-crs_2.2.3.tar.gz
mv modsecurity-crs_2.2.3 /etc/apache2/modsecurity-crs

Configurazione
La prima cosa da fare è configurare Apache perchè carichi il modulo. Lavorando su un sistema Debian/Ubuntu, seguo il loro modo di operare creando il file /etc/apache2/mods-available/mod-security.load

/etc/apache2/mods-available/mod-security.load
LoadFile /usr/lib/libxml2.so.2
LoadModule security2_module /usr/lib/apache2/modules/mod_security2.so

Ora attiviamo il modulo con:

a2enmod mod-security

Il file di configurazione base sarà /etc/apache2/conf.d/modsecurity.conf. Partiamo da una solida base, utilizzando la configurazione raccomandata del sorgente scaricato.

cp /usr/local/src/modsecurity-apache_2.6.3/modsecurity.conf-recommended /etc/apache2/conf.d/modsecurity.conf
mv /etc/apache2/modsecurity-crs/modsecurity_crs_10_config.conf.example /etc/apache2/modsecurity-crs/modsecurity_crs_10_config.conf

Con questa configurazione, in realtà, il nostro sistema fa ben poco in quanto si tratta solo di un setup di base del modulo che non blocca nulla e non include alcuna regola specifica. Editiamo il file operando le modifiche qui sotto:

/etc/apache2/conf.d/modsecurity.conf
#### Riga da aggiungere all'inizio
<IfModule mod_security2.c>
...
#### Riga da modificare
SecRuleEngine On
...
#### Righe da aggiungere alla fine
Include /etc/apache2/modsecurity-crs/modsecurity_crs_10_config.conf
Include /etc/apache2/modsecurity-crs/base_rules/*.conf
Include /etc/apache2/modsecurity-crs/activated_rules/*.conf
</IfModule>

A questo punto riavviamo Apache e verifichiamo in /var/log/apache2/error_log che il modulo venga caricato correttamente.

Per verificare l’effettiva funzionalità del sito potete creare un file test.php nella home directory del sito con il comando phpinfo. Ad es.

/var/www/test.php
<?php
phpinfo();
?>

e usare un tool di verifica come nikto per fare la scansione di quel sito. Questo è l’output del tools su una installazione standard di Apache senza mod_security:

+ Server: Apache/2.2.16 (Debian)
+ ETag header found on server, inode: 273242, size: 177, mtime: 0x4b5b1f0a49780
+ Apache/2.2.16 appears to be outdated (current is at least Apache/2.2.19). Apache 1.3.42 (final release) and 2.0.64 are also current.
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ Retrieved x-powered-by header: PHP/5.3.3-7+squeeze3
+ OSVDB-3092: /phpmyadmin/changelog.php: phpMyAdmin is for managing MySQL databases, and should be protected or limited to authorized hosts.
+ OSVDB-3092: /test/: This might be interesting...
+ OSVDB-3233: /test.php: PHP is installed, and a test script which runs phpinfo() was found. This gives a lot of system information.
+ OSVDB-3233: /test/info.php: PHP is installed, and a test script which runs phpinfo() was found. This gives a lot of system information.
+ OSVDB-3233: /test/phpinfo.php: PHP is installed, and a test script which runs phpinfo() was found. This gives a lot of system information.
+ OSVDB-3268: /icons/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ OSVDB-3092: /test.php: This might be interesting...
+ /phpmyadmin/: phpMyAdmin directory found
+ 6456 items checked: 0 error(s) and 13 item(s) reported on remote host
+ End Time:           2012-01-05 15:31:00 (425 seconds)
---------------------------------------------------------------------------

Questo è l’output del tool dopo l’abilitazione di mod_security:

---------------------------------------------------------------------------
+ Server: Apache/2.2.16 (Debian)
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Apache/2.2.16 appears to be outdated (current is at least Apache/2.2.19). Apache 1.3.42 (final release) and 2.0.64 are also current.
+ 6456 items checked: 0 error(s) and 1 item(s) reported on remote host
+ End Time:           2012-01-05 15:06:42 (414 seconds)
---------------------------------------------------------------------------

Andare oltre
Già con le sole regole base attive abbiamo visto che il nostro server è molto più sicuro.
Il pacchetto crs comprende però altre regole in grado di aumentare ulterioremente il grado di protezione del nostro server e si trovano in /etc/apache2/mod_security/optional_rules, /etc/apache2/mod_security/experimental_rules e /etc/apache2/mod_security/slr_rules. La nostra configurazione è già pronta per regole aggiuntive e per attivarle è sufficiente creare un link simbolico dei file nella directory /etc/apache2/mod_security/activated_rules e ricaricare la configurazione di Apache.

 

Freeside SelfService è l’interfaccia web per cliente finale che si collega al server freeside in modo da permettere al cliente di poter operare in autonomia sulle configurazioni dei servizi acquistati.
Dato che si tratta di una interfaccia pubblica, gli sviluppatori consigliano di utilizzare un server separato da quello ove risiede Freeside, pertanto in questo howto procederemo alla configurazione di una nuova VM Debian Squeeze.
Partendo da una installazione vanilla, installiamo Apache e mod_perl con:

apt-get install apache2 perl libapache2-mod-perl2 build-essential libexpat1-dev expat

Quindi installiamo i moduli CPAN necessari:

cpan Bundle::CPAN YAML Storable Text::CSV_XS Text::Template Business::CreditCard HTTP::BrowserDetect HTML::Parser Tie::IxHash
cpan HTML::Widgets::SelectLayers Date::Format Number::Format SOAP::Lite

Creiamo l’utente freeside sul server di frontend e assegnamoli una password temporanea:

useradd freeside
passwd freeside

quindi sul server freeside generiamo una chiave rsa per l’utente ed importiamola sul server di frontend:

su - freeside
ssh-keygen
scp .ssh/id_rsa.pub freeside@frontend-server:/home/freeside/.ssh/authorized_keys

A questo punto sul server di frontend possiamo levare la password temporanea per l’utente freeside:

passwd -l freeside

Ora modifichiamo la configurazione di Apache in modo che “giri” con l’utente freeside:

/etc/apache2/envvars
export APACHE_RUN_USER=freeside
export APACHE_RUN_GROUP=freeside

e modifichiamo il virtualhost di apache per poter eseguire i CGI nella directory ove risiederà il selfservice:

 #directory where selfservice .cgi scripts and .html templates are located
 
 AddHandler cgi-script .cgi
 Options +ExecCGI
 

A questo punto siamo pronti per installare freeside selfservice: innanzi tutto copiamo la direcory /freeside-2.3.0/fs_selfservice dal server di backend sul server selfservice:

(su - freeside)
scp /freeside-2.3.0/fs_selfservice freeside@frontend-server:/home/freeside

Spostiamoci sul server frontend selfservice e, come utente amministratore, compiliamo l’interfaccia selfservice:

cd /home/freeside/fs_selfservice/FS-SelfService/
perl Makefile.PL
make install
mkdir /usr/local/freeside; chown freeside /usr/local/freeside
touch /usr/local/freeside/selfservice_socket; chown freeside /usr/local/freeside/selfservice_socket
chmod 600 /usr/local/freeside/selfservice_socket

A questo punto l’installazione è completata. Non ci resta che riavviare apache sul server selfservice:

/etc/init.d/apache2 restart

e, sul server di backend, modificare lo script /etc/init.d/freeside aggiungendo l’ip del nostro server selfservice e riavviare il servizio:

/etc/init.d/freeside restart

Sia ben chiaro che l’interfaccia selfservice è un “ibrido” in quanto deve essere adattata alle esifenze dell’ISP, però rappresenta un punto di partenza interessante per poter lavorare.
Oltretutto questo non è l’unico metodo per comunicare con il server freeside: difatti, volendo, è possibile accedere al server mediante il protocollo XML-RPC per eseguire direttamente le API. Questa possibilità è molto più efficiente, però le comunicazioni non sono criptate, richiede maggiore programmazione e l’apertura della porta 8080 sul server freeside

 

In questo articolo affrontiamo un problemino che si incontra utilizzando più web server dietro ad un load balancer: la generazione delle statistiche.

Ammettiamo una situazione in cui abbiamo quattro web server apache con indirizzo IP 192.168.20.101-102-103-104 dietro ad un load balancer con indirizzo IP pubblico che rigira ai 4 server le richieste HTTP provenienti dalla rete internet. I quattro server leggono il contenuto dei siti web (pagine html, php, immagini…) da un disco condiviso comune con una qualsiasi tecnica (NFS, GlusterFS, MooseFS, iSCSI/OCFS2, ecc.). In questo caso ciascun server genererà i propri log di accesso indipendentemente: come fare per far si che un programma che genera statistiche (in questo caso AWstats) faccia il suo compito a dovere?

Le soluzioni sono principalmente due: la più immediata è condividere la directory con i log di Apache tra i quattro server in modo che tutti scrivano su un unico file di log. Questo, però, può generare facilemente problemi in quanto la situazione più complessa da gestire per un disco condiviso sono le scritture multiple contemporanee su uno stesso file.

La seconda soluzione, quella che adotteremo in questo articolo, è di far salvare i log a ciascun server in una sua directory e creare una nuova macchina che periodicamente copierà i file di log da ciascun server, li aggregherà e genererà le statistiche con awstat per ciascun website.

Partiamo quindi da una nuova installazione linux su cui installeremo AWstats. Su Debian/Ubuntu:

apt-get install awstats

Ora montiamo la directory condivisa con i siti web come fosse un comune web server: questo ci servirà per far si che awstats scriva le pagine con le statistiche all’interno della directory “web/stats” di ciascun virtualhost. Nella mia configurazione (ISPConfig) all’interno della directory /var/www c’è una directory per ogni sito web al cui interno c’è, appunto, una sottodirectory web con le pagine del sito e, ad un livello ancora inferiore, la sottodirectory stats che conterrà le statistiche.
Nel mio caso si tratta di un filesystem di rete NFS (/mnt/www sul server 192.168.20.253), per cui mi è sufficiente aggiungere la seguente riga nel file hosts del server AWstats:

/etc/fstab
192.168.20.253:/mnt/www                /var/www                nfs   rsize=32768,wsize=32768,intr,noatime,_netdev  0 0

Quindi lancio i seguenti comandi per montare il filesystem:

mkdir /var/www
apt-get install nfs-kernel-server nfs-client
mount /var/www

Ora creo una directory per ciascun server in cui salvare i log:

mkdir -p /var/log/httpd-1
mkdir -p /var/log/httpd-2
mkdir -p /var/log/httpd-3
mkdir -p /var/log/httpd-4

A questo punto possibile creare uno script che tramite scp copi i file in locale periodicamente, però l’utilizzo della rete sarebbe molto significativo per cui preferisco usare NFS ed esportare le 4 nuove directory verso i webserver. Per lo stesso motivo evito di esportare la directory con i log dei 4 webserver con NFS: meglio che awstats lavori con i file in locale.
Quindi modifico il file /etc/exports per esportare le quattro directory:

/etc/exports
/var/log/httpd-1	    192.168.20.*(rw,sync,no_root_squash,no_subtree_check)
/var/log/httpd-2      192.168.20.*(rw,sync,no_root_squash,no_subtree_check)
/var/log/httpd-3      192.168.20.*(rw,sync,no_root_squash,no_subtree_check)
/var/log/httpd-4      192.168.20.*(rw,sync,no_root_squash,no_subtree_check)

e lancio il comando per avviare l’esportazione:

exportfs -a

Ora, su ciascun server web, monto la directory esportata dal server AWstats. Modifico il file /etc/fstab:

/etc/fstab
192.168.20.44:/var/log/httpd-1                /var/log/httpd                nfs   rsize=32768,wsize=32768,intr,noatime,_netdev  0 0

In questo caso sono sul server “1″ e quindi monto la directory /var/log/httpd-1; bisogna agire di conseguenza sugli altri server.

mount /var/log/httpd

Ora, sui nostri quattro web server andiamo a modificare la configurazione di apache.
Innanzi tutto creaiamo un alias per la directory awstats-icon aggiungendo le seguenti righe:

/etc/httpd/httpd.conf
Alias /awstats-icon/ "/usr/share/awstats/awstats-icon/"

    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all

E copiamo su ciascun webserver la directory con le icone di awstats in /usr/share/awstats/awstats-icon.
Inoltre dobbiamo modificare la configurazione dei Virtualhost in modo che i log vengano salvati in una diversa directory per ciascun sito. Questa configurazione rispecchia il comportamento di default di ISPConfig.

Ora veniamo allo script che farà il lavoro vero e proprio. I commenti sono autoesplicativi, in qualsiasi caso lo script prende in esame tutte le directory presenti in /var/www assumendo che ciascuna di queste contenga un virtualhost.
La riga di configurazione più importante è echo "LogFile=\"${mergepath} ${logdir}/${dominio}/${filelog} |\"" > $configfile: in questa riga si indica dove sono i file di log relativi al virtualhost. Si usa lo script di awstats “logresolvemerge.pl” per fare il merge di tutti i file di log relativi al giorno precedente: tale script viene lanciato “al volo” e genera il file che sarà utilizzato da awstats in ram.

/usr/local/bin/crea-statistiche.sh
#!/bin/bash

# Variabili da configurare
# ---------------------------
# Directory con i siti web
webdir="/var/www"
# Sottodirectory per l'output dei file di report
reportdir="web/stats"
# Directory con i log
logdir="/var/log/httpd-*"
# Directory con le configurazioni di awstats
awstatsdir="/etc/awstats"
# Path allo script per realizzare il merge dei log
mergepath="/usr/share/doc/awstats/examples/logresolvemerge.pl"
# ---------------------------
# Elaboro il nome del file sul quale generare i log
data=`date +%Y%m%d`
filelog="$(($data - 1))-access.log.gz"

# Eseguo il ciclo per tutte le directory in "webdir"
j="${webdir}/*"
for directory in $j
do
    # Nel caso in cui si tratti effettivamente di una directory
    if [ -d ${direcroty} ]
    then
	# Estraggo il nome dominio dalla path
	dominio=${directory##*/}

	# Genero i file di configurazioni di AWStats
	configfile="${awstatsdir}/awstats.${dominio}.conf"
	echo "LogFile=\"${mergepath} ${logdir}/${dominio}/${filelog} |\"" > $configfile
	echo "SiteDomain=${dominio}" >> $configfile
	echo "LogFormat=1" >> $configfile
	echo "DirIcons=\"/awstats-icon\"" >> $configfile
    fi

    # Eseguo AWStats
    /usr/lib/cgi-bin/awstats.pl -config=$dominio -update
    /usr/lib/cgi-bin/awstats.pl -config=$dominio -output -staticlinks > ${webdir}/${dominio}/${reportdir}/awstats.html
done
 

E’ da qualche giorno che sto sbattendo la testa su un setup di NFS.

L’idea è quella di creare un server NFS (in realtà sono due macchine ridondate tramite DRBD/HeartBeat) che esporta la directory /var/www con tutti i siti web, verso quattro server Apache dietro ad un load balancer.
Questo setup mi serve come termine di paragone per testare la velocità e l’affidabilità di NFS rispetto ad una situazione in cui la partizione con i dati viene esportata sui web server tramite iSCSI e gestita attraverso il filesystem cluster OCFS2: questo setup garantiva performance estremamente importanti, però risulta un po’ complesso nella gestione dei guasti in quanto i quattro server web parlano tra loro per sincronizzare le operazioni sul disco condiviso e ho rilevato situazioni in cui l’intero cluster si trova in uno stato di incoerenza a causa di un solo nodo con problemi.

So per certo che le prestazioni di NFS non saranno paragonabili a quelle di OCFS2, però voglio capire quanto ciò va ad incidere nel caso di un semplice web server e quanto (e se) migliora la stabilità del sistema.

Una volta ultimata la configurazione di default, ecco sorgere il primo problema: Apache diventa instabile. Sarà un caso che a me sia successo subito, però vi giuro che è così.

Inizio a googleare in giro e scopro che esistono due funzionalità di apache attive di default che servono a migliorare le performance, che però sono incompatibili con NFS. Quindi agisco sul file di configurazione di apache per disattivarle:

EnableSendfile Off
EnableMMAP Off

Ok, ora Apache sembra stabile… ma è presto per cantar vittoria.
Mentre mi sto gustando un buon caffè, arriva la telefonata di un Geek a cui ho chiesto di aiutarmi nel testare il sistema che mi fa notare un problema di “sincronismo” tra i server. Rimango basito perchè non c’è alcun sincronismo, tutti i server pescano dallo stesso filesystem. Però il problema evidentemente c’è: quando effettuo una modifica ad un file su un server, passano 5-10 secondi perchè il demone apache sugli altri server se ne accorga. E’ come se apache avesse una sorta di cache interna…

Inizialmente tendo a pensare ad un problema legato ad apache, visto che ero appena stato scottato dalle due direttive che lo bloccavano. Ma qui il problema è diverso e, evidentemente, in una situazione simile con il filesystem ocfs2 tale problema non si presenta… quindi non c’è alcuna cache in apache, è evidente. Difatti faccio la prova a leggere il file direttamente da filesystem e il problema è analogo: quindi è NFS che fa cache.

Let’s google un altro po’ e trovo due impostazioni che possono creare questo tipo di problema una: su server NFS (no_wdelay) e una su client (noac). La prima, nel caso di un export sincrono, diabilita il wdealy attivo di default che serve per ritardare l’ack di completa scrittura in modo da verificare se esistono altre scritture in coda per eseguirle tutte assieme e migliorare le preformance; la seconda serve per disabilitare qualsiasi tipo di cache sul client in modo da costringerlo ogni volta ad accedere al server NFS.

In sostanza, alla fine, il mio export è:

/var/www      	192.168.50.*(rw,sync,no_root_squash,no_wdelay)

Mentre il mountpoint in fstab è:

192.168.50.253:/var/www		/var/www            	nfs   rsize=32768,wsize=32768,intr,noac,noatime,_netdev	0 0

Ora resta da vedere la velocità di NFS nell’utilizzo quotidiano in una situazione in cui sono state disabilitate tutte le funzionalità di cache del sistema: dopo qualche prova diciamo che la differenza di prestazioni senza cache è notevole e, in caso di siti particolarmente visitati, il carico di lavoro sul server NFS aumenta a livelli tali per cui non è possibile mantenere un simile livello di “online”; anche una taratura “di fino” sulla cache non aiuta più di tanto a migliorare le prestazioni.
In sostanza, abbiamo dimostrato che NFS senza cache è inutilizzabile per gli scopi prefissi, al pari di qualsiasi altro filesystem “server” come GlusterFS (vedi il paragone tra OCFS2 e GlusterFS di questo articolo).

Sia ben chiaro: non esiste LA soluzione, esistono diverse soluzioni con caratteristiche diverse che di volta in volta si adattano meglio o peggio alle esigenze. Nel caso in cui si ospitasserro solamente siti che non operano scritture su disco, la soluzione di NFS con cache è sicuramente la più semplice da implementare offrendo contemporaneamente un ottimo livello di velocità; nel caso di siti che scrivono dinamicamente e in cui si ha la necessità di accedere immediatamente ai file (ad esempio un worpress con il plugin nextgen gallery), bisognerebbe disabilitare la cache e quindi questa soluzione non è adatta: meglio “tornare” alla più complessa iSCSI/OCFS2.