Archivi tag: apache

Web server benchmarking

Solitamente, prima di mettere in produzione una Web application, si rende necessario testarla in modo approfondito su di un ambiente apposito, in modo da ridurre al minimo eventuali problemi/disservizi riscontrati dagli utenti che intendono utilizzarla.

Tralasciando i veri test che puntano esclusivamente sull’usabilità e sul corretto funzionamento della Web application in quanto tale (oltre, ovviamente, agli aspetti legati alla sicurezza), è indispensabile effettuare delle prove di carico sul server Web che la ospita (o, in alternativa, sull’application server).

In questo post vi mostrerò come effettuare dei test di carico mediante due tool nati per questo scopo, ovvero httperf ed ab (aka Apache Benchmark).

Installiamo dunque gli applicativi menzionati in precedenza. Il primo potete scaricarlo da qui (CentOS x86_64), mentre il secondo si trova all’interno del package httpd, installabile mediante un semplice packet manager (ad esempio yum):

[root@client ~]# yum install httpd

Per installare httperf (dopo averlo scaricato), potete lanciare il comando:

[root@client ~]# rpm -ivh httperf-0.9.0-1.el6.rf.x86_64.rpm

A questo punto possiamo dare inizio ai nostri test. Per prima cosa faremo delle prove sul server lato utente anonimo, ovvero simuleremo il traffico generato da tutti gli utenti che non hanno ancora effettuato il login (sempre che la nostra Web application lo preveda).

[root@client ~]# httperf --server=ipserverweb --uri=/ --num-conn 12000 --num-call 50 --rate 300 --timeout 5

In questo modo stiamo simulando un numero massimo di 12000 connessioni, ciascuna delle quali effettua 50 chiamate HTTP, ogni sencondo vengono effettuate 300 nuove connessioni (fino al tetto massimo di 12000) ed il timeout di ciascuna connessione è pari a 5 secondi.

Secondo questa logica, possono essere effettuati test di carico ancora più consistenti, ad esempio:

[root@client ~]# httperf --server=ipserverweb --uri=/ --num-conn 50000 --num-call 500 --rate 300 --timeout 30

o ancora:

[root@client ~]# httperf --server=ipserverweb --uri=/ --num-conn 100000 --num-call 1000 --rate 500 --timeout 60

I risultati dei suddetti test ci appariranno in un formato simile al seguente:

Total: connections 4996 requests 249800 replies 249800 test-duration
44.835 s

Connection rate: 111.4 conn/s (9.0 ms/conn, <=1022 concurrent connections)
Connection time [ms]: min 65.0 avg 8439.3 max 12570.1 median 8742.5
stddev 1720.6
Connection time [ms]: connect 0.1
Connection length [replies/conn]: 50.000

Request rate: 5571.6 req/s (0.2 ms/req)
Request size [B]: 59.0

Reply rate [replies/s]: min 5557.4 avg 5571.4 max 5585.2 stddev 10.5 (8
samples)
Reply time [ms]: response 168.7 transfer 0.1
Reply size [B]: header 229.0 content 5043.0 footer 0.0 (total 5272.0)
Reply status: 1xx=0 2xx=0 3xx=0 4xx=249800 5xx=0

CPU time [s]: user 0.87 system 43.96 (user 1.9% system 98.0% total 100.0%)
Net I/O: 29005.9 KB/s (237.6*10^6 bps)

Errors: total 7004 client-timo 0 socket-timo 0 connrefused 0 connreset 0
Errors: fd-unavail 7004 addrunavail 0 ftab-full 0 other 0

Le informazioni presenti nel suddetto report sono lapalissiane e possono tornarci di grande aiuto per ciò che concerne il traffico che il nostro server Web è in grado di reggere.

Nel frattempo, durante i suddetti test, è importante tenere sotto controllo due fattori:

1) l’effettiva raggiungibilità del sito (facendo delle prove di connessione mediante un semplice browser);

2) l’utilizzo delle risorse locali (RAM e CPU). A tal proposito vi consiglio di utilizzare uno strumento abbastanza semplice e più evoluto rispetto al comando top, ovvero htop:

[root@client ~]# yum install htop

La schermata che vi apparirà sarà simile alla seguente:

 

htop.png

Terminati i test lato utente anonimo, iniziamo con quelli lato utente loggato (che sicuramente stresseranno maggiormente la nostra macchina). Infatti, durante questi test verranno processate le chiamate server side (PHP, Jsp, ASP, C# et similia, a seconda della tecnologia utilizzata per implementare la Web application), allocando grosse quantità di RAM (e parte della swap) e facendo lavorare intensamente la (oppure le) CPU.

Come già accennato in precedenza, è possibile effettuare dei test lato utente loggato utilizzando un tool messo a disposizione dell’Apache Software Foundation, ovvero Apache Benchmark (ab). Nella fattispecie, la flag da utilizzare è -C ed usa come argomento il contenuto dell’authentication cookie rilasciato dalla nostra applicazione Web (potete utilizzare questo add-on di Mozilla Firefox in grado di leggere il contenuto del cookie in questione).

Ecco un esempio:

[root@client ~]# ab -n 2 -C "contenuto dell'authentication cookie" http://sitodatestare/

Con la flag -n sto indicando il numero di connessioni che devono essere simulate. Inoltre, i vari campi che compongono l’auth cookie devono essere intervallati da un ; mentre il valore di ciascun campo deve essere preceduto da un =. Ad esempio:

[root@client ~]# ab -n 2 -C "has_js=1; pri_num=3" http://sitodatestare/

Come avrete facilmente intuito, nell’esempio viene effettuato un test molto blando. Passiamo adesso ad alcune prove più impegnative (in termini di carico), utilizzando la flag -c che ha il compito di simulare le connessioni contemporanee:

[root@client ~]# ab -n 20 -c 10 -C "contenuto dell'authentication cookie" http://sitodatestare/

e ancora:

[root@client ~]# ab -n 210 -c 200 -C "contenuto dell'authentication cookie" http://sitodatestare/

e così via.

Il report generato avrà il seguente formato:

Benchmarking *.*.com (be patient)
Completed 100 requests
Completed 200 requests
Finished 210 requests

Server Software:        Apache/2.2.3
Server Hostname:        *.*.com
Server Port:            80

Document Path:          /
Document Length:        36020 bytes

Concurrency Level:      210
Time taken for tests:   89.815037 seconds
Complete requests:      210
Failed requests:        15
   (Connect: 0, Length: 15, Exceptions: 0)
Write errors:           0
Non-2xx responses:      15
Total transferred:      7129290 bytes
HTML transferred:       7030005 bytes
Requests per second:    2.34 [#/sec] (mean)
Time per request:       89815.039 [ms] (mean)
Time per request:       427.691 [ms] (mean, across all concurrent requests)
Transfer rate:          77.51 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.3      1       2
Processing:  1748 54696 18359.3  58915   89812
Waiting:     1747 54695 18359.3  58914   89811
Total:       1748 54697 18359.2  58916   89814

Percentage of the requests served within a certain time (ms)
  50%  58916
  66%  64830
  75%  69917
  80%  71274
  90%  76405
  95%  77879
  98%  79840
  99%  80893
 100%  89814 (longest request)

Questo è quanto, buon benchmarking.

Varnish + httpd su CentOS 5: logging del vero IP sorgente

Per ottimizzare i tempi di risposta dei server Web possono essere utilizzati degli accelleratori http (i quali svolgono principalmente operazioni di caching). Uno di questi prende il nome di varnish, software open source piuttosto diffuso ed altamente performante.

cache, varnish, httpd, apache, centos 5, http accelerator, caching, logging, source IP

Ora, poichè dal punto di vista legislativo è necessario che vengano loggati gli IP sorgenti delle richieste http, è indispensabile che il demone httpd sia in grado di individuarli e registrarli correttamente. Con una configurazione standard del suddetto demone ciò non è possibile, in quanto l’IP sorgente sarà sempre e comunque quello del server varnish che gli ha inoltrato la richiesta.

Per aggirare tale problematica occorre operare sulla configurazione di varnish e di httpd.

Per prima cosa, modifichiamo il file /etc/varnishd/defaul.vcl aggiungendo la seguente entry:

sub vcl_recv {
if (req.http.x-forwarded-for) {
    set req.http.X-Forwarded-For =
    req.http.X-Forwarded-For ", " client.ip;
  } else {
    set req.http.X-Forwarded-For = client.ip;
  }
}

In questo modo il campo http.X-Forwarded-For presente nell’header http verrà popolato con il vero IP sorgente della richiesta.

A questo punto dobbiamo semplicemente dire al demone httpd come interpretare le informazioni ricevute da varnish:

[root@bqweb1 varnish]# nano /etc/httpd/conf/httpd.conf

LogFormat "%{X-Forwarded-For}i %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" varnishcombined

e come CustomLog utilizzeremo la seguente direttiva:

CustomLog logs/access_log varnishcombined

Riavviamo sia varnish che httpd ed il gioco è fatto.

Alla prossima.

Swatch, Apache e base rate fallacy a palla

In questo post vi ho mostrato una possibile configurazione di swatch per ciò che concerne il monitoraggio delle richieste inoltrate ad un server Web. 

apache, swatch, regex, pattern, log, HTTP error code

Ovviamente tale configurazione è molto simile a quella che attualmente gira sui miei server, ragion per cui ho avuto modo di testarla in modo massiccio. Un effetto colletarale che mi è saltato all’occhio quasi immediatamente riguardava i falsi positivi, ovvero pattern del tutto innocui che swatch mi segnalava come errori HTTP.

Mi spiego meglio. Data una entry del file di log simile alla seguente:

192.168.x.x - jumbo [30/Jul/2012:16:03:20 +0200] "GET /prova.php HTTP/1.1" 200 4036 "https://www.pincopallo.it/prova.php" "Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20100101 Firefox/14.0.1"

essa mi veniva segnalata come HTTP Forbidden (errore 403) per via del 4036.

Il file di log contenente il giusto codice di errore dovrebbe avere una forma simile alla seguente:

79.55.x.x - jumbo [30/Jul/2012:21:28:53 +0200] "GET /prova.php HTTP/1.1" 403 773 "-" "Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0"

Ovvero il codice di errore è sempre preceduto e seguito da uno spazio vuoto.

Alla luce di tali considerazioni le regex da settare su swatch diventano le seguenti:

#HTTP Forbidden
watchfor  / 403 /
     echo
     mail addresses=vostro.indirizzo@email.it,subject=SWATCH HOME: Access Forbidden

#HTTP Not Found
watchfor  / 404 /
     echo
     mail addresses=vostro.indirizzo@email.it,subject=SWATCH HOME: Not Found

#HTTP Internal Server Error
watchfor  / 500 /
     echo
     mail addresses=vostro.indirizzo@email.it,subject=SWATCH HOME: Internal Server Error

#HTTP OK
watchfor  / 200 /
     echo
     mail addresses=vostro.indirizzo@email.it,subject=SWATCH HOME: Hit OK

Quindi, poichè i pattern da matchare devono essere contenuti all’interno dei due slash (/), è bastato aggiungere uno spazio prima e dopo del codice di errore.

Enjoy.

Apache, swatch e favicon inesistente

Premessa: i browser di ultima generazione che tantano di connettersi ad un sito (non presente nella loro cache) vanno automaticamente alla ricerca della famigerata favicon (ovvero quell’iconcina che appare a fianco della barra degli indirizzi – benedetto Web 2.0).

swatch, log, apache, favicon, http 404, not found, log monitoring

Fatto: se il sito non contiene la suddetta iconcina, il Web server (Apache nella fattispecie), genererà un bell’errore HTTP 404 (not found).

Problema: se il file di log del Web server è monitorato mediante un’apposita applicazione (leggasi swatch), che intercetta gli errori HTTP 404, il povero sistemista che legge gli alert (leggasi il sottoscritto), si ritroverà con un kg di mail praticamente inutili.

Soluzione: fare in modo che swatch ignori completamente le entry del file di log di Apache che contencono la keyword favicon.

In particolare, tali entry avranno la seguente forma:

79.5.*.* - - [29/May/2012:13:57:45 +0200] "GET /favicon.ico HTTP/1.1" 404 628 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.4) Gecko/20100101 Firefox/10.0.4"

indi per cui, nel file di configurazione di swatch basterà aggiungere la seguente direttiva (in testa):

#Favicon
ignore /favicon/

Niente di più facile.

Per rendere la modifica operativa occorre killare tutti i processi attivi di swatch (sudo killall -w swatch) e successivamente avviare nuovamente tale applicativo.

Alla prossima.

Swatch: configurazione per il monitoraggio dei server Web

Di seguito riporto la configurazione del mio Swatch, in grado di tenere sotto controllo ciò che accade sul server Web (Apache) che attualmente ho in gestione:

ignore /nagios-plugins/

#HTTP Forbidden
watchfor  /403/
     echo
     mail addresses=vostro.indirizzo@email.it,subject=SWATCH HOME: Access Forbidden

#HTTP Not Found
watchfor  /404/
     echo
     mail addresses=vostro.indirizzo@email.it,subject=SWATCH HOME: Not Found

#HTTP Internal Server Error
watchfor  /500/
     echo
     mail addresses=vostro.indirizzo@email.it,subject=SWATCH HOME: Internal Server Error

#HTTP OK
watchfor  /200/
     echo
     mail addresses=vostro.indirizzo@email.it,subject=SWATCH HOME: Hit OK

apache_display.png

Poichè sul server è presente anche nagios che ogni tanto effettua dei check sull’HTTPS, ho dovuto utilizzare la entry ignore /nagios-plugins/, evitando così di ricevere un’email ad ogni controllo.

Inoltre, sul server Web è presente l’autentica .htaccess, quindi ho messo sotto monitoraggio anche le hit andate a buon fine, in modo da poter verificare quale utente ha effettuato l’accesso alle aree riservate. Ciò è stato possibile anche grazie al fatto che sul server non vi è una grande mole di richieste. In caso contrario avrei certamente evitato una configurazione del genere, pena il rischio di beccarmi un ban sullo smarthost.

Infine, non ho ritenuto opportuno controllare gli errori HTTP 401 (Unauthorized), in quanto tale funzione è svolta egregiamente da fail2ban.

A presto.

Eclipse Galileo ed il plugin Axis2 code generator

Stamattina ho provato ad installare il plugin Axis2 code generator 1.6.1 sul mio Eclipse Galileo. Peccato che ad installazione completata, accedendo al wizard di eclipse non era presente alcuna voce Axis 2. Cercando un po’ sul Web ho trovato questo 3d:

http://stackoverflow.com/questions/8075585/not-able-to-see-axis2-plugin-for-eclipse

in cui si afferma che sia la versione 1.6.1 che la versione 1.4.* sono bacate e quindi funzionano male (o non funzionano del tutto).

axis2.jpg

Proprio per tale motivo ho scaricato la versione 1.7.0 del plugin in questione, direttamente da questo link:

https://builds.apache.org/job/Axis2/lastStableBuild/org.apache.axis2$axis2.eclipse.codegen.plugin/artifact/org.apache.axis2/axis2.eclipse.codegen.plugin/1.7.0-SNAPSHOT/axis2.eclipse.codegen.plugin-1.7.0-SNAPSHOT.jar

Copiate il *.jar all’interno della directory dropin, riavviate eclipse e tutto funzionerà alla perfezione.

A presto.

PS: la 1.7.0 è una nightly release (versione di test), quindi se qualcosa non dovesse funzionare alla perfezione non preoccupatevi più di tanto.

Apache2: disabilitare il directory listing

Uno dei tuning fondamentali per rendere sicuro il nostro Web server Apache consiste nel disabilitare il directory listing. Infatti, non è raro imbattersi in dei siti su cui è possibile visualizzare il contenuto delle directory in essi contenute, quali images, doc e compagnia bella (i termini Google hacking e la dork intitle:Index of vi dicono qualcosa?).

apache.jpg

 

Bene, per prima cosa è necessario aprire in lettura il file default (default-ssl se il vostro server utilizza il protocollo criptato https) che si trova nella dir /etc/apache2/sites-available:

nightfly@nightbox:/etc/apache2/sites-available$ sudo nano default

Adesso, nella sezione riportata di seguito rimuoviamo l’opzione Indexes:

      <Directory /var/www/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

In questo modo, tale sezione deventerà:

     <Directory /var/www/>
                Options FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
     </Directory>

Riavviamo Apache per rendere effettive le nuove impostazioni lanciando il comando:

nightfly@nightbox:/etc/apache2/sites-available$ sudo service apache2 restart

ed il gioco è fatto.

A presto.

Apache mod_rewrite sui link generati da sarg

Recentemente ho avuto a che fare con uno scenario piuttosto complesso, in cui gli utenti della LAN riescono a navigare sul Web grazie all’intermediazione di un proxy, nella fattispecie di Squid.

Ora, per facilitare la vita ai net admin, esiste un tool particolare che si integra alla perfezione con Squid e permette di analizzare il traffico generato da ciascun utente, in modo da poter osservare eventuali comportamenti ambigui e monitorare le loro attività sul Web. Tale software prende il nome di sarg, acronimo di Squid Analysis Report Generator.

Fin qui tutto chiaro, peccato però che i vari utenti si autentichino al proxy sfruttando NTLM e che il proxy identifichi gli spazi presenti negli username con la notazione ASCII, ovvero con %20. Quindi, nel momento in cui clicco su un link generato da sarg, del tipo:

nome%20cognome

il server apache che mi risponde interpreta il %20 come uno spazio, ragion per cui anzichè provare ad aprirmi il link:

http://proxy.dominio.com/sarg/nome%20cognome

cercherà di visualizzare il link

http://proxy.dominio.com/sarg/nome cognome

rispondendomi picche. Come fare dunque per risolvere tale problematica? Semplice, sfruttando il mod_rewrite messo a disposizione da Apache.

In particolare, tale feature consente di modificare al volo le URL richieste dall’utente, permettendo la sostituzione del %20 con un backslash, il carattere di escape , il quale serve proprio ad indicare al Web server che il %20 va interpretato in modo letterale e non come uno spazio.

Ma passiamo ai fatti. Per prima cosa identifichiamo la directory in cui è installato sarg, che per la distro CentoOS 5.0 è /var/www/sarg.

Posizioniamoci ora nella directory relativa al file di configurazione di apache, ovvero /etc/httpd/conf ed apriamo tale file di configurazione (httpd.conf) in scrittura:

[root@proxy conf]# vi httpd.conf

Verifichiamo che sia presente la direttiva:

LoadModule rewrite_module modules/mod_rewrite.so

e che non sia commentata.

Adesso inseriamo le seguenti direttive per la directory in cui si trova sarg:

<Directory "/var/www/sarg">

Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all

</Directory>

In realtà, quello che ci interessa è abilitare l’ovverride per la directory di sarg, in modo da consentire il corretto funzionamento del mod_rewrite.

Posizioniamoci adesso nella dir relativa a sarg e creiamo il file .htaccess:

[root@proxyint sarg]# vi .htaccess

e successivamente inseriamo all’interno del file le seguenti direttive:

RewriteEngine On

RewriteRule ([^ ]+) ([^ ]+) ([^ ]+) (.+) http://proxy.dominio.com/sarg/$1%20$2%20$3%20$4 [R=301,L]

RewriteRule ([^ ]+) ([^ ]+) (.+) http://proxy.dominio.com/sarg/$1%20$2%20$3 [R=301,L]

RewriteRule ([^ ]+) (.+) http://proxy.dominio.com/sarg/$1%20$2 [R=301,L]

Adesso verifichiamo che il mod_rewrite funzioni correttamente. Per fare ciò creiamo una directory all’interno di /var/www/sarg e chiamiamola pro%20va:

[root@proxyint sarg]# mkdir pro%20va

Infine, proviamo ad accedere a tale directory mediante il nostro browser, digitando nella barra degli indirizzi la seguente URL:

http://proxy.dominio.com/sarg/pro%20va

Se il server Web vi risponde con un errore 404 (page not found), vuol dire che il mod_rewrite non sta funzionando. Viceversa, se la directory pro%20va è vuota ed il browser vi risponde con la pagina Index of /sarg/pro%20va, vuol dire che tutto sta funzionando alla perfezione (noterete anche la presenza nella URL del backslash codificato in ASCII, ovvero %25).

Da questo momento in poi, ogni volta che proverete ad accedere alle statistiche generate da sarg, verrete correttamente reindirizzati alla pagina che state cercando.

A presto.