MokaByte 82 - Febbraio 2004 
Apache & Tomcat
Come connettere i due server per realizzare architetture scalabili, sicure performanti
I parte: introduzione allo scenario e primi connettori
di
Giovanni Puliti
Utilizzare Tomcat in connessione con un web server offre molteplici benefici sia per l'archittura complessiva, sia per la gestione della sicurezza e della scalabilità del sistema

Introduzione
Tomcat è probabilmente in questo momento il web container più popolare ed utilizzato su internet. Tomcat oltre ad essere la reference implementation per Servlet e JSP API, è distribuito tramite licenza open source e rappresenta anche un ottimo prodotto, sia per stabilità che per performance (anche se questo ultimo aspetto è spesso dibattuto).
Tomcat viene quindi utilizzato nella maggior parte dei casi come container in grado di eseguire applicazioni web basate su servlet e JSP.
Anche se al suo interno è presente un connettore HTTP (vedremo più avanti cosa sono i connettori) che lo trasforma in un server HTTP a tutti gli effetti, il suo utilizzo più consolidato, specie in scenari di produzione, è quello che lo vede in abbinamento con un server HTTP vero e proprio.
Dato che Apache HTTP Server (che per brevità verrà qui denominato semplicemente Apache) è il server più utilizzato in internet, l'abbinamento di Tomcat con Apache è probabilmente il più diffuso. In questo articolo ci soffermeremo per questo motivo su tale server HTTP, tralasciando altri prodotti.
In questo articolo e nel prossimo vedremo quindi come connettere Apache e Tomcat, tramite alcuni dei connettori più utilizzati. Si vedrà inoltre perché sia necessario realizzare architetture di questo genere, come proteggere l'application server Tomcat in una rete protetta (Militarized Zone o MZ) esponendo nella rete pubblica (DeMilitarized Zone o DMZ) solo il "sacrificabile" server HTTP.
Si vedrà infine come sia possibile pubblicando un solo dominio web associato ad un server HTTP, nascondervi dietro n web container Tomcat, dando vita di fatto ad uno scenario clustered molto affidabile e semplice da realizzare.

 

L'architettura a connettori di Tomcat
Tomcat dalla versione 4.0.x completa e migliora la sua implementazione basata su un modulo centrale al quale è possibile agganciare vari tipi di connettori.
Senza tali connettori il server sarebbe praticamente inutilizzabile dato che non sarebbe possibile comunicare con lui dall'esterno, ovvero non sarebbe quindi possibile eseguire web application basate su pagine JSP o servlet.
I connettori possono essere di tre tipi:

  • Connettori che parlano il protocollo HTTP (mod_http, mod_jk, coyote, mod_proxy) e che consentono di mettere in comunicazione il browser direttamente con Tomcat, senza intermediari. In questo caso le invocazioni per servlet e pagine JSP sono intercettate da Tomcat e rimappate su componenti in grado di eseguire le servlet e le pagine invocate (per chi volesse saperne di più nel server di Jakarta, ma anche in al-tri, tali componenti sono in genere delle servlet in grado di eseguire altre servlet). Si tenga presente che mod_proxy pur essendo un connettore che parla HTTP in gene-re viene utilizzato per realizzare un proxy HTTP fra il server web e Tomcat. Po-trebbe però essere utilizzato per attivare la comunicazione diretta browser-server.
  • Connettori come mod_jk e coyote che parlano il protocollo di invocazione Apache Jakarta Protocol (AJP nelle varie versioni 1.2, 1.3) per web applications. In questo caso Tomcat non è raggiungibile direttamente da un browser ma deve essere abbi-nato ad un server HTTP. In genere tutte le chiamate per servlet e pagine JSP ven-gono associate a determinati URL pattern, che a loro volta sono routati dal server HTTP a Tomcat. Tutte le risorse statiche (pagine HTML, immagini GIF o JPG) sono invece servite direttamente dal server web. Discorso particolare per le immagi-ni e risorse statiche contenute all'interno di una web application. La specifica ed il buon senso indicano di far servire questi elementi dal server Tomcat, ma niente im-pedisce di estrapolarle e metterle sotto il controllo del server HTTP. E' bene ribadi-re che tale soluzione è fortemente sconsigliabile se si desidera mantenere le applica-zioni ed il sito dinamico facili da gestire e mantenere.
  • Connettori di management che in un modo o nell'altro si agganciano al framework Java Management Extention (JMX). Non tratteremo questo genere di connettori, che esulano dall'argomento principale di questo articolo. Essi permettono di gestire Tomcat dall'esterno effettuando tutte le principali operazioni di management.

 

I connettori HTTP
Prima di passare ad analizzare i connettori AJP, è utile fare una breve considerazione sui connettori per HTTP ed al loro utilizzo.
Quando uno di questi connettori viene abilitato, Tomcat diviene a tutti gli effetti un server HTTP in grado di fornire pagine HTML e risorse statiche direttamente al browser, così co-me di restituire il risultato dell'esecuzione di una servlet o di una pagina JSP.
Questo uso, sebbene molto utile in fase di sviluppo e di test, è fortemente sconsigliabile in uno scenario di produzione per svariati motivi fra cui i principali sono i seguenti:

  1. Il grado di flessibilità e le possibilità di configurazione che si possono ottenere sfrut-tando gli strumenti messi a disposizione da Tomcat sono certamente minori di quanto possa fare ad esempio Apache che di mestiere fa il server HTTP.
  2. Legato al punto precedente c'è da considerare il fatto che utilizzare Tomcat per le ri-sorse statiche è probabilmente un inutile spreco di risorse. Una pagine HTML o una immagine GIF non hanno bisogno di un web container per essere inviate al browser che ne ha fatto richiesta.
  3. Dato che Tomcat funziona come container web, è presumibile che al suo interno si svolga della business logic. Fornisce accesso al client web (browser) a Tomcat signi-fica pubblicare direttamente su internet i servizi di business logic, cosa che può ri-sultare rischiosa ed in alcuni casi sconsigliabile.
  4. Se Tomcat funziona come server HTTP è ovvio che in un modo o nell'altro venga as-sociato ad un indirizzo internet tramite il quale si eseguiranno le applicazioni web. Purtroppo non è possibile associare allo stesso indirizzo internet più server contem-poraneamente (server in cluster). Più precisamente è possibile associare tramite un DNS round robin più server allo stesso nome internet o indirizzo IP, ma in questo caso non è possibile mantenere le cosiddette sticky session: se un client effettua una prima chiamata ad un Tomcat n della batteria di cluster, la comunicazione dovrà proseguire con tale server, per il mantenimento della sessione ovvero per il corretto funzionamento della applicazione.


Figura 1 - Se Tomcat viene utilizzato anche come
server HTTP l'architettura che ne risulta è difficilmente
manutenibile, meno sicura, e non scalabile.


Queste poche ma significative considerazioni dovrebbero far comprendere quanto sia impor-tante l'utilizzo di Tomcat in abbinamento con un server HTTP. Eventualmente ci si potreb-be chiedere quale sia la scelta migliore per il server HTTP: attualmente la scelta che in gene-re si compie è fra due prodotti: Apache Web Server ed Internet Information Server (IIS) di Microsoft.
I connettori per Tomcat forniti da Apache Group sono in grado di funzionare bene con en-trambi i prodotti anche se in passato si erano riscontrati diversi problemi per l'inoltro delle credenziali di autenticazione in HTTPS nel caso di utilizzo di IIS come server web.
Non ci addentreremo oltre in analisi e paragoni fra i due prodotti, limitandoci ad analizzare lo scenario attuale che vede IIS in netta minoranza rispetto ad Apache, come raffigurato nel-la figura 2.


Figura 2
: percentuale di utilizzo dei server web più famosi in questo momento in internet

Tale figura è stata presa da un sito di statistiche ed indagini di mercato, dove era riportata la seguente considerazione che riportiamo qui in forma integrale

In the November 2003 […] Apache has a significant percentage gain this month as register.com,
During 2001 and the first half of 2002 several companies hosting very large numbers of hostnames […] migrated to Microsoft-IIS.
Subsequently these businesses have either failed, significantly changed their business model, or reverted to their previous platform, and Microsoft-IIS share is now in line with its long term presummer 2001 level of around 20%.

Non sono in grado di verificare la fonte di tale analisi, ma personalmente non credo che la realtà sia molto diversa da quella qui raffigurata anche se in modo piuttosto pittoresco.

 

Architetture eterogenee
Una volta compreso che Tomcat da solo non basta, viene da chiedersi quali benefici si possano trarre dall'utilizzo in accoppiata con un server HTTP. I due più importanti sono certamente quelli legati alla sicurezza ed alla scalabilità.
Sicurezza perché a questo punto si può mettere tutto l'application server su un host protetto da un firewall in una zona protetta della rete, inaccessibile da client remoti, e rendere pubblico il solo server HTTP: i due comunicano a questo punto tramite protocollo AJP. Tutte le invocazioni per risorse statiche verranno servite dal server HTTP, mentre le richieste per servlet e pagine JSP verranno inoltrate verso Tomcat che le esegue.
Questa suddivisione dei compiti permette di ottimizzare fortemente le risorse del sistema e di bilanciare il carico di lavoro.


Figura 3 - L'utilizzo di un connettore AJP permette di mettere un server HTTP di fronte a
Tomcat: in questo modo lo si può isolare dal resto del mondo, rendendo più sicura l'architettura
complessiva. Il server HTTP inoltre offre maggiori potenzialità di configurazione ed ampliamento

Oltre a questo avere un solo punto di entrata permette (se il connettore lo consente) di realizzare architetture in cluster, dove a fronte di un solo indirizzo internet di entrata si possono associare più server Tomcat in maniera del tutto trasparente e scalabile.
In questo caso subentrano problematiche di mantenimento della sessione e sessioni distribuite, argomento questo piuttosto avanzato e che perciò non verrà qui trattato. Si rimanda eventualmente a [TOM] per maggiori apprendimenti.


Figura 4
- L'utilizzo di un connettore AJP consente di associare ad un solo server HTTP
(quindi un solo indirizzo internet) più server Tomcat, dando vita in modo semplice ad una
configurazione cluster facilmente scalabili e quindi di servire un numero maggiore di clienti

Per connettere Apache e Tomcat sono disponibili diverse alternative:

  • mod_proxy: permette la connessione fra apache e Tomcat tramite una semplice conessione di tipo HTTP proxy. In alcune configurazioni questa soluzione può apparire non performante o eccessivamente semplicistica. La sintassi utilizzata per la configurazione delle due componenti (Apache e Tomcat) è relativamente semplice.
  • mod_jk: questo connettore si basa sul protocollo AJP 1.2 (Apache Jakarta Protocol) o AJP 1.3 ed è stato introdotto come evoluzione del mod_proxy. E' particolarmente seguito e sviluppato dal gruppo di lavoro di Apache- Jakarta.
  • mod_webapp: questo connettore è stato di recente rilasciato dal team di Apache-Jakarta come strumento espressamente pensato per mettere in comunicazione Apache e Tomcat secondo la modalità web application. Utilizza il protocollo WARP, che prendendo spunto dalla famosa velocità warp della astronave Enterprise, doveva nelle intenzioni dei progettisti fornire delle prestazioni nettamente migliori rispetto agli altri connettori. Putroppo per manifestati problemi di stabilità e funzionamento è stato poco adottato a scapito del più moderno e performante Coyote.
  • Coyote rappresenta attualmente il connettore più flessibile e potente per Tomcat 4 e 5. In grado di parlare i protocolli HTTP 1.0 e 1.1, AJP 1.2 e 1.3 è certamente lo strumento ideale per connettere Apache e Tomcat anche in architettura cluster.

 

Configurazione dei server
Per quanto riguarda i nomi dei vari file di configurazione per brevità si fa riferimento sempre ai nomi semplici sottintendendo sia a chi si riferiscono (Apache o Tomcat) sia la loro collocazione.

File di configurazione di Apache
Sono posizionati in genere sotto la directory conf di configurazione. Da notare che questo server HTTP in genere consente una distribuzione dei vari file piuttosto flessibile e distribuita sul sistema. Si consiglia quindi di consultare l'amministratore di sistema per maggiori dettagli.
Il file httd.conf contiene tutte le informazioni di configurazione del server HTTP. A partire dalla versione 2.0x tutto quello che riguarda la configurazione di SSL e quindi di HTTPS, è stato spostato nel file ssl.conf in genere posizionato nella stessa directory.

File di configurazione di Tomcat
In questo caso le cose sono più semplici, dato che in genere tutti i file relativi a Tomcat si trovano sotto la dir di installazione del server. Quelli di configurazione stanno sotto la directory conf.
Il file server.xml consente di configurare la maggior parte dei parametri operativi di Tomcat, compresi quelli relativi ai connettori. Invece web.xml presente anche all'interno di tutte web application, permette di specificare tutti i parametri di default per le web application, nel caso in cui la singola web application non ne abbia uno al suo interno. Da notare che per quanto riguarda la sicurezza, in questo file si possono specificare ruoli e livello di autenticazione necessari per accedere alle risorse della applicazione.
Il file tomcat-users.xml permette di specificare ruoli, utenti e password per quelle applicazioni che abbiano specificato come sistema di autenticazione quello basato su uid e password (vedi [TomcatACL])
Il connettore mod_proxy
Questo connettore non è ormai più quasi utilizzato, ma data la sua semplicità ed adattabilità può essere utilizzato in modo semplice e veloce in scenari particolari.
In questo caso la comunicazione fra Apache e Tomcat avviene tramite il protocollo HTTP/HTTPS, e quindi Apache inoltrerà le chiamate a Tomcat tramite i relativi connettori integrati in Tomcat (che a sua volta si chiamano HTTP e HTTPS Connector). Le ripercussioni di questo fatto ricadono principalmente sulle prestazioni che sulla carta potrebbero essere minori rispetto a quanto ottenibile con un connettore differente.
Per prima cosa si analizzerà come realizzare una connessione tramite il mod_proxy fra Apa-che e Tomcat per il protocollo HTTP. In questo caso tutte le chiamate del browser verranno rivolte direttamente ad Apache con il protocollo HTTP, ed Apache provvederà ad inoltrare tali chiamate verso Tomcat.
Per poter predisporre questo meccanismo si deve per prima cosa caricare in memoria l'opportuno modulo; se si utilizza la versione 1.3.x di Apache nel file http.conf si dovrà scrivere

LoadModule proxy_module {path-to-modules}/mod_proxy.so

Dato che con la versione 2.0xx l'architettura è stata modificata completamente, se si utilizza la nuova versione del server HTTP la direttiva precedente diventa

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so

In particolare il mod_proxy_connect è necessario per mettere in comunicazione il proxy con il sottoprotocollo SSL (quindi HTTPS), mentre mod_proxy_http per inoltrare richieste in HTTP.
Si supponga adesso di voler accedere alle web application di Tomcat (in esecuzione sul server host2.mydomain.com) non direttamente ma tramite Apache. Tali web app rispondono ad esempio per le pagine JSP all'url

http://host1.mydomain.com:8080/simple

Collegandosi con tale indirizzo si contatta direttamente Tomcat. Per permettere ad Apache di intercettare tutte le chiamate a tale web application e di ridirigerle, si deve aggiungere la definizione di un proxy tramite la seguente direttiva inserita nel file di configurazione di Apache httpd.conf:

ProxyPass /simple http://host1.mydomain.com:8080/simple/

A questo punto, dopo aver fatto ripartire Apache, collegandosi con l'indirizzo

http://www.mydomain.com:80/simple/

si potrà invocare direttamente la web application di Tomcat tramite il proxy effettuato da Apache.
Dopo la redirezione, a seconda di come è strutturata la web application (in particolare a seconda della presenza o meno di file index.htm), il browser potrebbe visualizzare nella location bar l'indirizzo servito da Tomcat, ovvero una cosa del tipo

http://host1.mydomain.com:8080/simple/index.htm

Questo è chiaramente un problema perché l'intenzione era quella di "nascondere" Tomcat dietro ad Apache, e si vuole che gli utenti si colleghino direttamente con il server Java.
Il perché di questo comportamento è dovuto al fatto che la gestione delle pagine di indice, come ad esempio index.htm, viene effettuata dal server spedendo la risposta HTTP 402 detta anche "redirect": il server sta dicendo al browser di ricollegarsi immediatamente con la nuova URL specificata. La nuova URL è, ovviamente, quella di Tomcat, che non sa di essere 'proxato', e quindi compare sul browser. Per risolvere questo problema si deve aggiungere ad httpd.conf una nuova direttiva:

ProxyPassReverse /simple http://host1.mydomain.com:8080/simple/

Questa direttiva istruisce Apache a filtrare eventuali risposte di tipo 'redirect', mascherandole con la propria URL. Se ora si prova nuovamente il collegamento, si potrà notare che la URL visualizzata dal navigatore è corretta. Ma non è tutto finito: se si prova ad indagare sulle informazioni passate da Apache a Tomcat (ad esempio utilizzando l'applicazione snoop fornita fra gli esempi alla installazione di Tomcat) si potrà osservare che i valori di Server name e Server Port (che danno i valori restituiti dai metodi HttpServletRequest.getServerName() e HttpServletRequest.getServerPort()) sono rispettivamente host1.mydomain.com e per la porta 8080.
Anche in questo caso questo potrebbe essere un comportamento non desiderato: di nuovo sono venute alla luce informazioni sulla presenza di Tomcat che vorremmo nascondere se si utilizza Apache e Tomcat sulla macchine diverse.
Alcune applicazioni potrebbero legittimamente costruire dei link partendo da queste informazioni, portando il vostro navigatore a collegarsi direttamente con l'host dov'e' installato Tomcat, oppure portando ad un errore se tale host è inaccessibile perché nascosto dietro un firewall. Ecco come risolvere il problema: si modifichi il server.xml nella definizione del connettore http della porta 8080 come segue, aggiungendo gli attributi proxyName e proxyPort:

<Connector className="org.apache.catalina.connector.http.HttpConnector"
           port="8080"
           proxyName="www.mydomain.com"
           proxyPort="80"/>

dove www.mydomain.com è il nome dell'host dove gira Apache.
Teoricamente, se l'host dove è in esecuzione Tomcat è accessibile da Internet, è ancora possibile un collegamento diretto (ma bisogna sapere che esiste e su quale porta si trova): per completare l'opera si può utilizzare un sistema di sicurezza del sistema operativo come tcpwrappers per consentire l'accesso alla porta 8080 solo a partire dall'host su cui è installato Apache.
Si tenga presente che per maggior pulizia dei file sarebbe sempre bene operare con virtual host, invece che definire i parametri a livello globale per tutto Apache.

 

La configurazione di Apache per SSL
La configurazione tramite virtual host viene presentata qui di seguito relativamente al protocollo HTTPS. Per HTTP appena visto le cose sono sostanzialmente simili.
Quanto verrà qui detto vale sostanzialmente anche se si usa il connettore Coyote, per cui si faccia riferimento a questa sezione con i dovuti adattamenti quando si parlerà nel prossimo articolo di tale connettore.
Per quanto riguarda l'uso di connessioni crittografate (Secure Socket Layer) l'approccio a proxy è piuttosto simile. In Tomcat la sola cosa da fare è attivare il connettore HTTPS, (di solito sulla porta 8443), tramite alcune direttive in XML inserite nel file server.xml di Tomcat (normalmente alla installazione tali direttive sono già presenti anche se commentate); ecco cosa deve essere inserito

<!-- Define an SSL HTTP/1.1 Connector on port 8443 -->
<Connector className="org.apache.catalina.connector.http.HttpConnector"
port="8443" minProcessors="5" maxProcessors="75"
enableLookups="true"
acceptCount="10" debug="0" scheme="https" secure="true">
<Factory className="org.apache.catalina.net.SSLServerSocketFactory"
clientAuth="false" protocol="TLS"/>
</Connector>

Come accennato in precedenza la configurazione SSL di Apache 2.0xx deve essere fatta tramite un file separato (normalmente ssl.conf) e non in httpd.conf, che invece deve contenere una direttiva di inclusione a tale file, come ad esempio

Include conf/ssl.conf

In ssl.conf a questo punto dovranno essere definite tutte le informazioni del proxy HTTPS in modo da inoltrare le chiamate dirette ad Apache verso Tomcat. Tale file è piuttosto complesso, e per una maggiore analisi delle sue parti si rimanda alla sezione dedicata alla connessione tramite connettore mod_jk.
Il supporto per SSL si può attivare mediante il caricamento di un modulo apposito, con le solite istruzioni:

LoadModule ssl_module modules/libssl.so
AddModule mod_ssl.c

Dato che si deve attivare un socket per SSL nel file di configurazione deve essere presente un'opportuna direttiva Listen che ne specifica la porta: ad esempio, se si vuole utilizzare la porta 443, quella di default, si dovrà scrivere

Listen 443

Per maggiore pulizia del file di configurazione a questo punto si può procedere a definire un virtual host, anche il tutto dovrebbe continuare a funzionare anche senza. Di seguito è riportata la definizione di un virtual host con le principali direttive utilizzate per lo scopo in esame.

<VirtualHost www.mydomain.it:443>

DocumentRoot "/var/apache2/htdocs"
ServerName mokahosting.mokabyte.it:443
ServerAdmin you@your.address
ErrorLog logs/error_log
TransferLog logs/access_log

# Enable/Disable SSL for this virtual host.
SSLEngine on

# SSL Cipher Suite:
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+.....

# Server Certificate:
SSLCertificateFile /etc/apache/conf/ssl.crt/server.crt

# Server Private Key:
SSLCertificateKeyFile /etc/apache/conf/ssl.key/server.key

# Certificate Authority (CA):
SSLCACertificatePath /etc/apache/conf/ssl.crt
SSLCACertificateFile /etc/apache/conf/ssl.crt/ca.crt

# Client Authentication (Type):
SSLVerifyClient require
SSLVerifyDepth 10

# SSL Engine Options:
SSLOptions +FakeBasicAuth +ExportCertData +CompatEnvVars +StrictRequire

# Definisce il proxy verso Tomcat
ProxyPass /x509 https://host2.mokabyte.it:9443/x509
ProxyPassReverse /x509 https://host2.mokabyte.it:9443/x509

</VirtualHost>

La direttiva DocumentRoot al solito specifica la locazione dei documenti da pubblicare, mentre

SSLEngine on

attiva il supporto crittografico. La direttiva SSLCipherSuite stabilisce la lista di algoritmi crittografici da utilizzare in ordine decrescente di preferenza. Le direttive SSLCertificateFile e SSLCertificateKeyFile puntano rispettivamente al file che contiene il certificato digitale del server e a file che contiene la chiave digitale di detto certificato. Particolarmente importante la direttiva ExportCertData che permette di inoltrare le informazioni sulla autenticazione da Apache verso Tomcat.
Se si vogliono creare in casa i certificati digitali senza doverli richiedere da una Certification Authority (CA) riconosciuta, esiste un programma di utilità che viene rilasciato nella stessa installazione di Apache. A tal proposito per maggiori approfondimenti si rimanda al documento riportato in bibliografia [makecerts].
Infine le direttive ProxyPass e ProxyPassReverse definiscono la connessione verso Tomcat: si noti l'analogia al caso precedente anche se in questo caso la connessione viene effettuata tramite il protocollo HTTPS con il connettore opportuno di Tomcat.

 

Conclusione
Per questo mese ci fermiamo qui. Si sono visti alcuni aspetti importanti da un punto di vista teorico e pratico. Il connettore HTTP-Proxy è ormai poco utilizzato per cui la parte veramente interessante arriverà il mese prossimo quando parleremo di mod_jk e coyote i due connettori attualmente più utilizzati, i quali fra le altre cose permettono di attaccare più Tomcat allo stesso web server in modo da realizzare architetture cluster.

 

Bibliografia e risorse
[TOM] - Jakarta Tomcat tradotto dalla redazione di MokaByte
[javasecurity] "Java Security (II ed.)" di Scott Oaks Ed. O'Reilly , ISBN: 0596001576. Disponibile anche in edizione italiana
[TomcatACL] - "La sicurezza nella servlet API" di Giovanni Puliti, MokaByte 78 - Ottobre 2003, www.mokabyte.it/2003/10
[jserv]: http://jakarta.apache.org/tomcat/tomcat-3.3-doc/tomcat-apache-howto.html
[coyote] http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/coyote.html
[webapp] http://jakarta.apache.org/tomcat/tomcat-4.1-doc/config/webapp.html

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it