Apache

Indice

Introduzione
Per cominciare
Host virtuali basati sull'indirizzo IP
Host virtuali basati sul nome
Cominciamo la configurazione
PASSO 1: Dichiarare i nuovi domini
PASSO 2: Predisporre gli spazi WEB
PASSO 3: Configuriamo Apache
PASSO 4: Creiamo le home page
PASSO 5: Verifica degli host virtuali
Esperimenti interessanti
WEB dinamico e programmi CGI
SUEXEC - Ovvero del braccio destro del demonio
ScriptAlias - Definire la/le directory dei CGI
ScriptAliasMatch - Un nome, un CGI
Home page personali
Proviamo il SUEXEC
Ritocchi finali
http.conf in tutta la sua gloria
Conclusioni
Bibliografia

Errori di Apache

Introduzione

Apache è un potente WEB server multipiattaforma. Le statistiche dicono che è il più utilizzato al mondo, e tutto lascia prevedere che lo sarà ancora per qualche anno.

Apache è disponibile nel sito ufficiale www.apache.org, insieme ai sorgenti e a tutta la documentazione. Tutte le distribuzioni di GNU/Linux lo includono come pacchetto, tipicamente già compilato e configurato: è sufficiente una installazione base del sistema operativo, ed anche l'utilizzatore più sprovveduto si ritrova con un WEB server installato (magari a sua insaputa...).

Le cose vanno diversamente quando si desidera configurare Apache per uso di produzione: diventa allora difficile orientarsi tra la miriade delle sue opzioni di configurazione, e la documentazione ufficiale non aiuta il neofita. In particolare in questo articolo vogliamo configurare Apache per supportare la multiutenza e raggiungere i seguenti obiettivi: gestire vari domini WEB; isolare i programmi CGI dei vari siti tra di loro; dotare gli utenti ciascuno della propria home page.

Queste note sono il frutto di alcuni mesi di lavoro passati a spulciare nella documentazione del programma e a fare prove su varie distribuzioni GNU/Linux, principalmente Red Hat 6.2 e Red Hat 7.1, che includono la versione 1.3 di Apache. I suggerimenti e le soluzioni che descrivo si applicano ovviamente anche ad altre distribuzioni, che potranno differire al più per la scelta dei path di installazione e per il diverso packaging dei vari componenti (modulo base, moduli supplementari, ecc.).

Non ho certo intenzione di scrivere un tutorial per Apache o un ennesimo manuale. Si tratta semplicemente della descrizione di esperienze che possono interessare gli iniziati che, una volta eseguita con successo l'installazione base di Apache, desiderano approfondirne alcune funzionalità avanzate.

Non ci inoltreremo qui nelle procedure di ricompilazione del sorgente del programma, nè faremo altre cose più tediose e "difficili": ci limiteremo a modificare il file di configurazione di Apache ed eventualmente interverremo su qualche altro file di sistema usando pratiche consuete di configurazione. Riporremo la nostra fiducia nel rivenditore della distribuzione, che di solito ha cura di rendere disponibile sul suo sito WEB l'ultima versione di Apache corretta rispetto ai bug e ai problemi di sicurezza. Non ci interessa invece installare l'ultimissima versione, poiché ci concentreremo sugli aspetti generali della gestione del server.

Ultima annotazione prima di cominciare: teoricamente il system administrator e il WEB administrator sono due ruoli distinti. In realtà l'intreccio di competenze è tale che le due figure finiscono per coincidere. E' molto probabile che la configurazione del WEB server coinvolga parecchi settaggi del sistema, della posta elettronica, del DBMS, dei permessi e degli utenti, sicchè separare le due figure diventa davvero difficile. Perciò qui userò i due termini indifferentemente.

Per cominciare

Assicuriamoci innanzitutto che Apache sia installato ed in esecuzione. E' interessante nonché divertente per il sistemista conoscere alcuni modi alternativi per fare ciò:

1. Ordine e disciplina - Seguire la via maestra
GNU/Linux segue le convenzioni System V per l'inizializzazione del sistema. Quindi dovrebbe essere disponibile un piccolo script di shell che si incarica di avviare, fermare e verificare lo stato del server. Lo script esegue una di queste funzioni a seconda che sia stato invocato con il parametro
start, stop oppure status; esiste poi anche il parametro restart che ha l'ovvio significato. Sulla distribuzione Red Hat 6.2 il comando è

    # /etc/rc.d/init.d/httpd status
    httpd (pid 9702 9701 9698) is running...

mentre per la Red Hat 7.1 il path differisce leggermente:

    # /etc/init.d/httpd status
    httpd (pid 9702 9701 9698) is running...

L'output conseguente dovrebbe confortarci sul fatto che Apache sia regolarmente in esecuzione. Il messaggio esatto dipende da come è stato scritto questo script, che invito ad andare a vedere.

2. Il Riduzionista - In Unix è tutta una questione di file e di processi
Sappiamo che Unix, GNU/Linux e gli altri sistemi operativi affini sono concepiti con la filosofia del meccano: pochi strumenti, ma buoni. File e processi sono il fondamento del sistema, il resto è il sale e il pepe. Il sistemista-riduzionista non si fida degli script automatici, ma vuole andare all'origine delle cose, e va a guardare direttamente i processi in esecuzione:

    # ps ax | grep httpd
    9698 ?        S      0:00 /usr/sbin/httpd parametri vari
    9701 ?        S      0:00 /usr/sbin/httpd parametri vari
    9702 ?        S      0:00 /usr/sbin/httpd parametri vari
    9706 pts/2    S      0:00 grep httpd

Il sistemista-riduzionista è previdente: sa che sulla sua macchina oberata di lavoro sono in esecuzione centinaia di processi, per cui inserisce un sano grep che seleziona solo le righe che contengono la stringa httpd. Guardacaso, queste righe sono proprio quelle relative ai processi di Apache.

3. L'hacker che c'è in noi - Emerge il lato oscuro
Ragioniamo: se un server di rete fornisce servizi in rete, il modo migliore per verificarne il funzionamento è provare direttamente questi servizi. Apriamo allora il nostro browser WEB preferito e puntiamolo sull'URL
http://localhost. Il bravo sistemista/hacker con tendenze riduzioniste usa Telnet come browser WEB:

    # telnet localhost 80
    Trying 127.0.0.1...
    Connected to localhost.localdomain.
    Escape character is '^]'.
    GET / HTTP/1.0  qui premi ENTER due volte

    HTTP/1.1 200 OK
    Date: Mon, 10 Dec 2001 21:50:38 GMT
    Server: Apache/1.3.19 (Unix)  (Red-Hat/Linux)
    Last-Modified: Sat, 11 Aug 2001 19:58:38 GMT
    ETag: "49183-20e-3b758e6e"
    Accept-Ranges: bytes
    Content-Length: 526
    Connection: close
    Content-Type: text/html

    <HTML>
    la pagina HTML che non ci interessa
    </HTML>
    Connection closed by foreign host.

    #

Come al solito, solo il comando evidenziato in grassetto deve essere impartito a tastiera, il resto sono le risposte del sistema. Notiamo che il comando GET deve essere scritto proprio in lettere maiuscole, e che occorre premere due volte il tasto ENTER prima che il server risponda: la riga vuota è il modo in cui il client (cioè il nostro Telnet) spiega al server che ha concluso la sua domanda. Infatti, vedremo che il client ha la possibilità di specificare vari altri parametri su altrettante righe.

Come è facile immaginare, il comando GET serve per richiedere un documento; a seguire bisogna specificare la parte di path file dell'URL del documento, essendo per convenzione / la richiesta della home page, o pagina default, o pagina indice del sito. Con lungimiranza, il protocollo HTTP richiede anche di specificare esplicitamente il protocollo e la versione.

Trucco
Se il terminale che usi non supporta lo scrolling, sarà difficile riuscire a leggere le prime righe, che sono le più interessanti. Rimedi possibili: usare script; richiedere una pagina deliberatamente errata al posto di /, ad esempio /xxx; infine, usare un comando come questo:
    # (echo -ne "GET / HTTP/1.0\n\n"; sleep 2)  \
    > | telnet localhost 80 | head -20

In questo modo appariranno solo le prime 20 righe del dialogo con il server, indipendentemente dalla effettiva lunghezza della risposta. Usando lo stesso principio si può andare ad esplorare in giro i vari server, e verificare di persona quali sono i server più usati: interessante, vero?

A questo punto dovremmo avere la certezza che l'installazione di base di Apache è a posto. Per ora Apache ritorna la pagina di default predefinita dalla distribuzione, ma questo ci va bene perché stiamo per cambiare un po' tutto...

Host virtuali basati sull'indirizzo IP

Di base il server Apache risponde ad un unico indirizzo IP e ad un unico dominio, cioè gestisce un solo sito WEB del tipo www.azienda.it o una cosa del genere. Gli ISP hanno invece la necessità di gestire parecchi domini. Le aziende più avanzate informaticamente sul fronte Internet possono voler creare siti WEB distinti per le diverse aree funzionali, come support.azienda.it, oppure desiderano ospitare siti WEB delle ditte affiliate. Con il protocollo HTTP versione 1.0 era necessario dotare ogni sito WEB di un indirizzo IP distinto, anche se poi questo indirizzo si riferiva alla stessa macchina fisica. In questo consiste il meccanismo di host virtuale basato sull'indirizzo IP.

Le cose funzionavano (e possono funzionare tuttora) così: se un navigatore si collegava all'URL www.azienda.it, il browser risolveva il nome in un certo numero IP 11.22.33.44, ed è a questo server che il browser inviava la richiesta; quando il navigatore si collegava a support.azienda.it, il browser risolveva il nome in un indirizzo IP diverso 55.66.77.88 al quale rispondeva magari la stessa macchina, ma lì il server poteva discriminare il sito WEB richiesto in base all'indirizzo IP.

Host virtuali basati sul nome

Per ridurre lo spreco di preziosi indirizzi IP e tutte le inevitabili complicazioni tecniche, burocratiche e di costi, il protocollo HTTP versione 1.1 ha aggiunto la funzionalità di host virtuale basato sul nome. Il meccanismo è abbastanza semplice: il browser segue la stessa trafila di prima, ma nella richiesta della pagina specifica anche per esteso il nome del dominio richiesto. Il server WEB, anche se dotato di un solo indirizzo IP, ha così modo di riconoscere quale sito WEB tra quelli ospitati è stato effettivamente richiesto. In questo consiste il meccanismo di host virtuale basato sul nome. E' ovvio che questo sistema richiede la collaborazione del browser per funzionare. Comunque, tutti i browser moderni supportano HTTP 1.1, tanto che il meccanismo degli host virtuali è ampiamente utilizzato. Forse tutto questo discorso suona un po' ingarbugliato, ma vedremo subito degli esempi molto concreti che dovrebbero chiarire bene come vanno le cose.

Cominciamo la configurazione

Dunque, Apache include il supporto per gli host virtuali basati sul nome di dominio, previsti dal protocollo HTTP versione 1.1. Questo ci permette di ospitare sulla nostra macchina un numero arbitrario di siti WEB distinti utilizzando sempre un solo indirizzo IP. Le specifiche tecniche dell'implementazione che andremo a fare sono le seguenti:

The "Casa" ISP Specs
IP Address: 127.0.0.1
WEB Sites: Domain DocumentRoot
localhost.localdomain /home/httpd/html
www.tizio.casa /home/tizio/public_html
www.caio.casa /home/caio/public_html

L'indirizzo IP non è scelto a caso: si tratta dell'indirizzo di loop-back previsto per scopi di test e disponibile su ogni macchina. Altro aspetto positivo di questa scelta: non servono schede di rete e non serve essere connessi ad Internet.

PASSO 1: Dichiarare i nuovi domini

Per quanto riguarda i domini gestiti, sono ovviamente nomi di fantasia che possiamo inserire nell'elenco degli host name del file /etc/hosts, che andiamo subito a modificare in modo che appaia cos&igrave:

    127.0.0.1       localhost.localdomain localhost
    127.0.0.1       www.tizio.casa
    127.0.0.1       www.caio.casa

In genere la prima riga è già predisposta, mentre le altre due sono quelle appena aggiunte. A questo punto i processi che avvieremo saranno in grado di risolvere i nuovi nomi di dominio.

PASSO 2: predisporre gli spazi WEB

La strategia che seguiremo comporta la creazione di un normale account per ciascun dominio gestito. Vogliamo insomma che ogni dominio sia gestibile da un utente distinto, che vi può accedere in Telnet o FTP come di consueto. Nella home directory, ciascun utente sarà libero di gestire il suo sito in totale libertà.
Per creare l'utente Tizio facciamo questo:

    # useradd tizio -g users
    
    # passwd tizio
    Changing password for user tizio
    New UNIX password: ******
    Retype new UNIX password: ******
    passwd: all authentication tokens updated successfully
    
    # chmod u=rwx,g=,o=x  /home/tizio
    
    # mkdir /home/tizio/public_html
    
    # chown tizio:users /home/tizio/public_html
    
    # chmod u=rwx,g=,o=x /home/tizio/public_html

Per i più pigri, spiego a parole quello che abbiamo fatto: il nuovo utente possiede una normale home directory posta in /home/tizio; dentro a questa directory questo signore potrà lavorare normalmente come un qualsiasi utente. In più abbiamo creato una sotto-directory di nome public_html che conterrà la parte pubblica del sito WEB del sig. Tizio. In altri termini, andremo a configurare Apache in modo che gli URL del tipo http://www.tizio.casa/x vengano tradotti nel pathfile /home/tizio/public_html/x.

Ci sono però due aspetti molto importanti da considerare:

Permessi di /home/tizio
UID:
tizio
GID:
users
others:
r w x - - - - - x

Conviene spendere due parole sul significato di quanto fatto riguardo ai permessi di accesso, perché l'argomento è un po' delicato, essendo coinvolti i problemi di sicurezza e riservatezza. Fintanto che il server WEB è al servizio di un'unica azienda, la separazione degli spazi di lavoro semplifica la gestione e riduce le interferenze. Tuttavia se il server deve essere reso disponibile ad altri soggetti sui quali non si ha pieno controllo, allora le cose vanno studiate più attentamente.

Spieghiamo innanzitutto cosa intendiamo con il termine identità di un processo. Ogni processo ha varie caratteristiche: ad esempio una è il PID (process identifier), il numero univoco che identifica il processo nel sistema. Altre due caratteristiche molto importanti sono l'UID e il GID del processo, cioè il numero dell'utente e il numero del gruppo che contraddistinguono il processo. Sono questi valori che il kernel esamina prima di dare il permesso a un processo di accedere ad una risorsa, come un file o un device. Richiamiamo brevemente i criteri seguiti dal kernel per decidere se autorizzare o meno una certa operazione richiesta da un processo su di un file:

  1. L'UID del processo è uguale all'UID del file.
    In questo caso si applicano i tre flag dei permessi di utente del file. Se la combinazione dei flag non permette di eseguire l'operazione richiesta dal processo (lettura, scrittura, esecuzione), l'operazione viene negata indipendentemente da tutti gli altri flag di gruppo e others.
  2. Gli UID del processo e del file differiscono, ma i GID sono uguali.
    In tal caso si applicano i tre flag dei permessi di gruppo del file. Anche qui, se la combinazione dei flag non permette di eseguire l'operazione richiesta dal processo, l'operazione viene negata indipendentemente da tutti gli altri flag di others.
  3. L'UID e il GID del processo non corrispondono a quelli del file.
    In tal caso si applicano i tre flag dei permessi di others.

Ricordo che Apache gira con l'identità UID:GID = nobody:nobody su Red Hat 6.2, e con l'identità apache:apache su Red Hat 7.1. Questi parametri vengono impostati nella configurazione predefinita con le direttive User e Group nel file di configurazione httpd.conf.

La conseguenza di tutto questo discorso è che Apache potrà entrare nelle directory degli utenti Tizio e Caio grazie al permesso o+x; inoltre Apache potrà leggere tutti e soli i file accessibili ad "other". Viceversa, gli altri utenti del sistema, i cui processi operano con GID = users, si scontrano con il secondo criterio di validazione, e non possono entrare nella directory.

ATTENZIONE!
Il modello di sicurezza per i permessi dei file e delle directory non è l'unico possibile, ma forse è il più semplice da applicare e da gestire. Lascia tuttavia qualche perplessità il dover rendere accessibile a "other" la propria home directory.

Esiste almeno un'altra soluzione che si basa sulla creazione di un gruppo per ciascun utente, paradigma scelto per default dalla distribuzione Red Hat. Le home directory degli utenti vanno poi rese attraversabili dal proprio gruppo. L'utente del server (nobody oppure apache) deve poi essere inserito nel gruppo di ciascun utente. Questa, in estrema sintesi, la ricetta alternativa.

PASSO 3: Configuriamo Apache

E finalmente arriviamo alla configurazione di Apache. Il file di configurazione è httpd.conf, che nella distribuzione Red Hat 6.2 e 7.1 si trova in /etc/httpd/conf/httpd.conf. Raccomando a questo punto di fare una bella copia del file prima che ci mettiamo su le manacce: è utile avere come riferimento un file di configurazione che sappiamo essere funzionante.

Al termine del file httpd.conf c'è la sezione destinata agli host virtuali. Assicuriamoci che sia presente la direttiva
     NameVirtualHost 127.0.0.1:80

che attiva la funzionalità degli host virtuali basati sul nome sulla solita porta 80 del nostro server. Creiamo il virtual host per il dominio www.tizio.casa:

     <VirtualHost 127.0.0.1:80>
         ServerName www.tizio.casa
         DocumentRoot /home/tizio/public_html
         ServerAdmin tizio@localhost
         CustomLog logs/www.tizio.casa-access_log common
         ErrorLog logs/www.tizio.casa-error_log
     </VirtualHost>

Per gli altri domini virtuali creiamo altrettanti utenti e altre sezioni VirtualHost similari, facendo attenzione a modificare di conseguenza il dominio, il path e l'indirizzo di posta, evidenziati in grassetto nell'esempio. Come ServerAdmin ho indicato in realtà l'utente tizio invece che il vero WEB administrator: di solito i problemi legati a un sito WEB sono locali a quel sito (pagine mancanti, CGI non funzionanti, ecc.) piuttosto che responsabilità del WEB administrator.

PASSO 4: Creiamo le home page

Questa è la parte facile e rilassante:
    # su - tizio
    $ echo "<html><body><h1>Benvenuti in www.tizio.casa</body></html>"
                  > public_html/index.html
    $ [CTRL-D]
    # su - caio
    $ echo "<html><body><h1>Benvenuti in www.caio.casa</body></html>"
                  > public_html/index.html
    $ [CTRL-D]
...e così via per gli altri dominii.

PASSO 5: Verifica degli host virtuali

Non ci resta che riavviare Apache. Il comando da dare su Red Hat 6.2 è

    # /etc/rc.d/init.d/httpd restart

mentre su Red Hat 7.1 è

    # /etc/init.d/httpd restart

Se qualcosa è andato storto, c'è sempre il log file in /var/log/httpd. Mentre si fanno queste prove consiglio di tenere sempre aperta una finestra dedicata alla visualizzazione dei messaggi di log tramite il comando tail -f /var/log/httpd/*.

Se è tutto ok, puntiamo il WEB browser sull'URL http://www.tizio.casa e poi su http://www.caio.casa. Ecco quello che io ho ottenuto:

    $ (echo -ne "GET / HTTP/1.1\nHost: www.tizio.casa\n\n"
    > sleep 2) | telnet localhost 80
    Trying 127.0.0.1...
    Connected to localhost.localdomain.
    Escape character is '^]'.
    HTTP/1.1 200 OK
    Date: Wed, 11 Dec 2001 21:33:20 GMT
    Server: Apache/1.3.19 (Unix)  (Red-Hat/Linux)
    Last-Modified: Mon, 10 Dec 2001 07:55:23 GMT
    ETag: "fa7b-43-3c146a6b"
    Accept-Ranges: bytes
    Content-Length: 67
    Content-Type: text/html

    <html><body>Benvenuto in www.tizio.casa</body></html>
    Connection closed by foreign host.

Esperimenti interessanti

Prova questo comando:

    # (echo -ne "GET / HTTP/1.0\n\n"; sleep 2)  \
    > | telnet localhost 80 | head -20

esso dovrebbe ritornare il primo virtual host (che al momento dovrebbe essere quello del sig. Tizio). Possiamo provare anche ad aggiungere il virtual host localhost.localdomain come primo virtual host e ripetere la prova.

Adesso sfruttiamo il protocollo HTTP v. 1.1 per ritornare gli altri virtual host. Per il sig. Caio si tratta di aggiungere la riga Host: www.caio.casa nella nostra interrogazione:

    # (echo -ne "GET / HTTP/1.0\nHost: www.caio.casa\n\n"; sleep 2)  \
    > | telnet localhost 80 | head -20

Le stesse prove si possono fare anche da un browser WEB "normale", ma si perde tutto il gusto...

Con questo abbiamo concluso il nostro tour sul meccanismo dei domini virtuali. In una situazione reale avremo che i domini www.tizio.casa e www.caio.casa saranno registrati su un qualche DNS (e non nel nostro file /etc/hosts), e l'indirizzo IP da assegnare ai VirtualHost sarà l'indirizzo pubblico assegnato alla nostra macchina (e non l'indirizzo di loopback 127.0.0.1).

WEB dinamico e programmi CGI

Il WEB sarebbe ben poca cosa senza la possibilità di generare dinamicamente le pagine richieste e senza quella di interagire con il client remoto. Il protocollo HTTP da una parte, e le tecnologie CGI e SSI di Apache dall'altra sono gli strumenti che forniscono queste possibilità. Apache viene corredato anche con vari interpreti incorporati, come ad esempio PERL, che permettono una esecuzione molto efficiente di codice di scripting incorporato all'interno delle pagine WEB.

Spendiamo due parole per chiarire cos'è un programma CGI: si tratta appunto di un programma, realizzabile con un qualsiasi linguaggio di programmazione o di scripting, che può essere invocato come una pagina WEB o come gestore di un form HTML; il WEB server, anziché ritornare al client il file del programma, lo esegue. L'output generato da questo programma è poi quello che il server restituirà al client, sia esso una pagina HTML, un'immagine GIF o qualsiasi altro tipo di informazione. Le specifiche dell'interfaccia CGI dicono anche come il programma CGI possa ricevere input dal client, chiudendo quindi il cerchio. Rimandiamo al prossimo articolo la discussione dettagliata della tecnologia CGI, delle possibilità che essa offre, e dei possibili utilizzi pratici.

Tuttavia, nuove possibilità significano nuovi problemi per l'amministratore del sistema. Cerchiamo di capire meglio il problema introducendo l'importantissima questione della identità dei processi CGI.

Abbiamo detto che il server Apache è un processo avviato con l'identità UID:GID = nobody:nobody nella distribuzione Linux Red Hat 6.2, oppure con l'identità UID:GID = apache:apache nella distribuzione Linux Red Hat 7.1. Con altre distribuzioni di GNU/Linux questa identità può cambiare, ma resta il fatto che Apache funziona con questa unica identità. L'identità del processo impone anche i limiti per quanto riguarda l'accesso alle risorse del sistema:

I programmi CGI avviati da Apache ereditano l'identità di processo di quest'ultimo anche quando appartengono ad utenti diversi. Lo stesso discorso vale per gli interpreti incorporati. Quindi, ad esempio, le funzioni per gestire i file richiedono di impostare opportunamente i permessi e la proprietà della directory dove il file risiede, oltre che i permessi e la proprietà del file stesso. Non è possibile creare file in directory non accessibili al server, né è possibile leggere file non leggibili per il server.

Supponiamo ora che i programmi CGI prodotti dal sig. Tizio e dal sig. Caio abbiano necessità di svolgere varie funzioni: esattamente come qualsiasi altro programma, avranno bisogno di leggere e scrivere file, accedere a un DB e altre cose del genere. Purtroppo, siccome essi verranno eseguiti con la stessa identità, saremo costretti ad assegnare diritti di accesso in comune a tutti i CGI. Per essere più espliciti: a livello di CGI gli utenti Tizio e Caio potranno pasticciare liberamente sugli stessi file. Il sig. Tizio non potrà leggere o scrivere un suo file riservato senza che questo non sia leggibile anche al sig. Caio. Il Sig. Tizio vorrà accedere a un DBMS riservato specificando una password, ma se usa un linguaggio di scripting il suo programma deve necessariamente essere leggibile ai programmi CGI degli altri utenti, che potranno così carpirgli facilmente la password. Il sig. Tizio non potrà leggere o scrivere file nella propria home directory (al di fuori di public_html) senza dover pericolosamente rilassare i diritti di accesso al suo account. In altri termini, abbiamo un sistema multiutente che, a livello del server WEB, diventa monoutente...

Pensiamo invece a quanto sarebbe logicamente bello e praticamente utile se i programmi CGI di un utente fossero eseguiti con l'identità dell'utente stesso: il programma avrebbe pieno accesso al suo account e potrebbe leggere e scrivere file; i CGI non sarebbero leggibili nè copiabili dagli altri utenti, anche quando si trattasse di script; l'autenticazione al DBMS potrebbe essere automatica perchè basata sulla identità del processo; ecc. Tutte queste possibilità offrono agli utenti molte opportunità di sfruttare in modo creativo le tecnologie del WEB.

Esiste anche un rovescio della medaglia: l'esecuzione di programmi CGI qualora siano realizzati come script richiede più tempo per l'avviamento rispetto agli stessi programmi eseguiti dagli interpreti incorporati in Apache. Del resto, se un sito WEB comporta realmente un grande flusso di traffico, forse vale la pena di dedicare ad esso un server completo, per cui l'obiezione è valida solo in parte.

SUEXEC - Ovvero del braccio destro del Demonio

La documentazione di Apache è estremamente prudente in proposito: SUEXEC è uno strumento potente, ma altrettanto potentemente insidioso per la sicurezza dalle intrusioni. L'esperienza del passato ha lasciato alcune vittime, ma gli sviluppatori di Apache hanno studiato contromosse altrettanto diaboliche. Rimando perciò a questa fonte per la discussione della questione. Noi sfideremo intrepidi il rischio, ansiosi di esplorare le nuove dimensioni che si dischiuderanno.

Il famigerato SUEXEC di Apache non è altro che un programmino di una decina di KB che si occupa di avviare i CGI per conto di Apache, conferendo però al processo così avviato l'identità del suo proprietario. Quindi, ad esempio, i CGI del sig. Tizio verranno eseguiti con l'identità UID:GID = tizio:users. Il SUEXEC si preoccupa di garantire che il processo avviato sia legittimo. La tabellina qui sotto riassume le identità dei vari processi nel caso di un programma CGI mio.cgi avviato per conto del sig. Tizio:

ProcessoUIDGID
httpdnobody (RH6.2)
apache (RH7.1)
nobody (RH6.2)
apache (RH7.1)
suexecrootnobody (RH6.2)
apache (RH7.1)
mio.cgitiziousers

La distribuzione Red Hat viene con il programma suexec già pronto, ma disattivato. Inoltre, il programma prevede, tra gli infiniti controlli, che il CGI avviato si trovi dentro alla directory /home/httpd (o in altra directory prevista dalla distribuzione), sicché non è adatto alla nostra situazione.

Se la tua distribuzione non include il programma /usr/sbin/suexec (è infatti questo il nome al secolo dell'innominabile), allora dovrai proprio procedere alla compilazione dei sorgenti di tutto Apache, oltre che scaricare la patch SUEXEC dal sito ufficiale. In questo caso seguire scrupolosamente le indicazioni fornite, eccetto che il pathfile della directory dei CGI dovrà essere /home. Buon lavoro e buona fortuna. Ci rivediamo al prossimo paragrafo sugli ScriptAlias.

Se invece sei un pigro, troverai più veloce ed indolore la ricetta che segue, valida per le distribuzioni Red Hat 6.2 e 7.1.

suexec è abilitato per eseguire i CGI solo nella directory /home/httpd/ (RH6.2) o nella dir. /var/www (RH7.1): per abilitare il meccanismo nelle dir. degli utenti /home è necessario ricompilare il programma suexec cambiando opportunamente la configurazione hard-coded. Poiché ci secca di intraprendere questo lungo e impervio cammino, scegliamo una scorciatoia sporca: andremo a cambiare il codice del programma con un editor binario! Io ho usato l'editor del potente Midnight Commander:

Per la RH6.2 e RH7.1 è sufficiente attivare il bit SUID del programma suexec, e magari restringere il set di permessi inutilmente ampi che la distribuzione attribuisce al file. Per la RH6.2:

    # chown  root:nobody  /usr/sbin/suexec
    # chmod  u=xs,g=x,o=  /usr/sbin/suexec
mentre per la RH7.1 cambia solo il nome del gruppo proprietario:
    # chown  root:apache  /usr/sbin/suexec
    # chmod  u=xs,g=x,o=  /usr/sbin/suexec
Adesso il suexec è a posto: controlla che l'identità e i permessi del file suexec appaiano così nella RH6.2:
    # ls -l /usr/sbin/suexec
    ---s--x---  1 root  nobody    9488 Aug 12 14:19 /usr/sbin/suexec
mentre nella RH7.1 dovrebbero apparire così:
    # ls -l /usr/sbin/suexec
    ---s--x---  1 root  apache   10976 Aug 12 13:05 /usr/sbin/suexec

Se non corrispondono, agire con chown e chmod opportunamente.

Non rimane che riavviare Apache. Nel log file /var/log/httpd/access_log dovrebbe apparire:
    [notice] caught SIGTERM, shutting down
    [notice] Apache/1.3.19 (Unix)  (Red-Hat/Linux) configured
             -- resuming normal operations
    [notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)

La riga che ci interessa è l'ultima, e ci rassicura sul fatto che Apache abbia digerito il nostro suexec!

ScriptAlias - Definire la/le directory dei CGI

Il nome di questa direttiva di Apache è fuorviante, perché lascia pensare che riguardi solo gli script. In realtà si tratta di una regola di matching che permette ad Apache di stabilire se un certo file va considerato come documento o come programma CGI. Nel primo caso Apache tenterà di riconoscerne il tipo e lo restituirà al client che lo ha richiesto. Nel secondo caso Apache lancerà il programma come CGI; siccome abbiamo appena attivato il supporto SUEXEC, il programma assumerà l'identità del proprietario. Esiste anche ScriptAliasMatch, che permette di utilizzare anche espressioni regolari: ne vedremo degli esempi.

Le direttive ScriptAlias e ScriptAliasMatch possono apparire nella configurazione globale del server, e anche nelle sezioni dei VirtualHost. La scelta più tradizionale prevede di collocare i CGI nella directory /cgi-bin della root directory del sito. In tal caso come direttiva globale metteremo
    ScriptAlias /cgi-bin/  /home/httpd/cgi-bin/
Dato che abbiamo già fatto la configurazione degli host virtuali, nelle sezioni dei VirtualHost metteremo qualcosa come
    <VirtualHost 127.0.0.1:80>
        ServerName www.tizio.casa
        User tizio
        Group users
        DocumentRoot /home/tizio/public_html
        ServerAdmin tizio@localhost
        ScriptAlias /cgi-bin/ /home/tizio/public_html/cgi-bin/
        CustomLog logs/www.tizio.casa-access_log common
        ErrorLog logs/www.tizio.casa-error_log
    </VirtualHost>

Le direttive User e Group dicono al programma suexec quale dovrebbe essere l'identità del programma CGI: suexec esegue poi un controllo stringente sulla proprietà del file e sui suoi diritti di accesso prima di autorizzarne l'esecuzione con l'identità stabilita.
La direttiva
ScriptAlias dichiara dove si trova la directory dei CGI, e mappa gli URL del tipo http://www.tizio.casa/cgi-bin/xxx nel pathfile /home/tizio/public_html/cgi-bin/xxx.

ScriptAliasMatch - Un nome, un CGI

Più potente la direttiva ScriptAliasMatch: diventa possibile utilizzare espressioni regolari per identificare i programmi CGI. Per fare un esempio, possiamo istruire Apache a riconoscere come programma CGI ogni file il cui nome termina con la stringa ".cgi". A questo scopo basta una direttiva globale come questa:
    ScriptAliasMatch /(.*)\.cgi  /home/httpd/html/$1.cgi
Per i VirtualHost aggiungeremo invece:
    <VirtualHost 127.0.0.1:80>
        ServerName www.tizio.casa
        User tizio
        Group users
        DocumentRoot /home/tizio/public_html
        ServerAdmin tizio@localhost
        ScriptAlias /cgi-bin/ /home/tizio/public_html/cgi-bin/
        ScriptAliasMatch /(.*)\.cgi  /home/tizio/public_html/$1.cgi
        CustomLog logs/www.tizio.casa-access_log common
        ErrorLog logs/www.tizio.casa-error_log
    </VirtualHost>

Questa volta la direttiva ScriptAliasMatch mappa URL del tipo http://www.tizio.casa/x/y/z.cgi nel pathfile /home/tizio/public_html/x/y/z.cgi, ed istruisce anche Apache sul fatto che questo file sia un CGI da eseguire.

Home page personali

Avrai visto qualche volta un URL del tipo

        www.qualcosa.org/~tizio

dove tizio è un qualche individuo che rende disponibile la sua home page pur senza disporre di un dominio registrato. Il carattere tilde viene utilizzato per convenzione a questo scopo. Sulle tastiere italiane si ottiene la tilde premendo ALT+126 (su Windows) o, in alternativa, indicando nell'URL la sequenza %7e. Nel primo caso, 126 è il codice ASCII della tilde espresso nella base decimale; nel secondo caso è lo stesso numero espresso nella base esadecimale e nella convenzione della codifica degli URL.

Comunque sia, è pratica comune consentire agli utenti dei sistemi Unix (e quindi anche GNU/Linux) di predisporre la propria home page. Per attivare il meccanismo della tilde in Apache bisogna inserire questa direttiva nella parte globale della configurazione:

    UserDir public_html

il cui significato è il seguente: mappa gli URL della forma http://localhost.localdomain/~utente nel pathfile /home/utente/public_html. Si possono abilitare anche i CGI nel solito modo:

    ScriptAliasMatch /~(.*)/(.*)\.cgi  /home/$1/public_html/$2.cgi

Il pattern (.*) esegue il match col nome dell'utente, che viene sostituito in $1; di conseguenza la stringa (.*) deve eseguire il match con tutto ciò che resta, che viene sostituito in $2. Il risultato di queste due sostituzioni fornisce ad Apache il pathfile assoluto del CGI nel file system. Quindi, ad esempio, l'URL

        http://localhost.localdomain/~tizio/x/y/z.cgi

produce gli assegnamenti $1=tizio, $2=x/y/z e quindi in definitiva Apache invoca il CGI

        /home/tizio/public_html/x/y/z.cgi

Proviamo il SUEXEC

Finalmente, siamo giunti alla conclusione. Sinceramente non credo sia cosa sana tentare tutte le pratiche configuratorie viste fin qua e ridursi solo ora a provare le cose. Più probabile che tu abbia fatto le tue prove un po' alla volta modificando progressivamente il file preconfezionato.

Comunque sia andata, adesso bisogna proprio verificare il funzionamento di SUEXEC. A questo scopo conviene loggarsi come utente, per esempio il sig. Tizio, in modo che tutti i file e le directory create abbiano automaticamente l'identità giusta e facciano contento SUEXEC, che così non si lamenterà. Crea uno script di test come questo:
    #!/bin/bash
    echo "Content-Type: text/plain"
    echo ""
    echo "Identita':"
    id
chiamalo /home/tizio/public_html/test.cgi e rendilo eseguibile:
    $ chmod  u=rwx,go=  test.cgi

Eseguilo localmente per vedere se funziona (./test.cgi), quindi prova l'URL http://www.tizio.casa/test.cgi. Se hai configurato le home page degli utenti puoi provare anche http://localhost/~tizio/test.cgi. Sul browser dovrebbe apparire l'id tizio/users, prova provata che il nostro programmino test.cgi è stato eseguito con l'identità del suo proprietario. Ecco quello che vedo io:

    $ (echo -ne "GET /test.cgi HTTP/1.0\nHost: www.tizio.casa\n\n"
    > sleep 2) | telnet localhost 80
    Trying 127.0.0.1...
    Connected to localhost.localdomain.
    Escape character is '^]'.
    HTTP/1.1 200 OK
    Date: Tue, 11 Dec 2001 21:15:53 GMT
    Server: Apache/1.3.19 (Unix)  (Red-Hat/Linux)
    Connection: close
    Content-Type: text/plain

    Identita':
    uid=506(tizio) gid=100(users) groups=100(users)
    Connection closed by foreign host.

La cosa importante sono le due paroline evidenziate in grassetto, tizio e user: è per vederle comparire che abbiamo fatto tutta questa trafila del SUEXEC. Congratulazioni, obiettivo centrato!

Se invece, come è probabile, salta fuori qualcos'altro, allora non resta che ripercorrere tutti i passi della configurazione fatta fin qui, tenendo sempre aperta una bella finestra con tail -f dei file di log come abbiamo visto. Alcuni suggerimenti diagnostici:

Netscape mostra sempre lo stesso risultato comunque io agisca.
Bisogna premere il bottone Reload del browser mentre si tiene premuto il tasto SHIFT, altrimenti Netscape restituisce quello che ha nella cache.
Il browser risponde "Not Found" e sul log file appare "unable to stat".
Apache ha risolto l'URL nel pathfile, come viene specificato nel log; sfortunatamente, tale file non esiste, oppure i permessi delle directory non permettono ad Apache (che in questa fase ha ancora l'identità standard) di attraversare una o più delle directory del pathfile. Controlla il corretto pathfile. Controlla i permessi della directory home di tizio.
Il browser mostra che lo script ha identità diversa da tizio/users.
Non sta funzionando SUEXEC. Controlla nel log file se all'avvio di Apache compare il messaggio esplicito della attivazione del SUEXEC. Controlla la presenza delle direttive User e Group nella sezione VirtualHost del dominio www.tizio.casa.
Il browser mostra il sorgente dello script.
Controlla la direttiva ScriptAliasMatch nella sezione VirtualHost del dominio www.tizio.casa.

Infine, confronta il tuo file di configurazione con quello che riporto qui più avanti.

Ritocchi finali

Rimane ora solo da disabilitare gli interpreti (ad esempio PERL o PHP, se sono installati) incorporati in Apache. E' facile, basta commentare tutte le righe di http.conf che si riferiscono a questi linguaggi. Potremo sempre usare il PHP e il PERL nei nostri CGI, ma nelle loro versioni stand-alone consuete.

La direttiva globale

    DirectoryIndex index.html index.htm index.shtml index.cgi

istruisce il server su quale pagina ritornare quando il client esegue una GET / o comunque un'altra directory, senza specificare un file preciso all'interno di questa directory. In questi casi, Apache tenta di ritornare i file specificati, nell'ordine. Le prime voci sono quelle consuete, mentre l'ultima l'ho aggiunta per l'occasione. Per inciso, se nessuno di questi file esiste, Apache ritorna l'elenco dei file della directory se è presente la direttiva Option Indexes, altrimenti dà un bel "Forbidden".

httpd.conf in tutta la sua gloria

Giunti alla conclusione di questo lungo cammino, ecco come appare il mio httpd.conf. Raccomando, prima di procedere ad uno sbrigativo copia-e-incolla, di fare una copia del vostro attuale file di configurazione, e per due buoni motivi: 1) contiene molti utili commenti, qui omessi; 2) funziona.

Alcuni moduli opzionali li ho commentati, ma si possono re-inserire secondo necessità. La loro omissione velocizza parecchio l'avvio, e riduce il consumo di memoria.

Ho lasciato commentate anche alcune funzionalità che hanno valore di commento per le personalizzazioni successive. Anche qui, vedere la documentazione di Apache per il significato delle varie direttive.


####### httpd.conf: INIZIO

ServerType standalone
ServerRoot "/etc/httpd"
LockFile /var/lock/httpd.lock
PidFile /var/run/httpd.pid
#ScoreBoardFile /var/run/httpd.scoreboard
Timeout 300
KeepAlive On
MaxKeepAliveRequests 10
KeepAliveTimeout 60
MinSpareServers 2
MaxSpareServers 10
# Pochi processi --> risparmio memoria; riavvii + veloci
StartServers 2
MaxClients 10
MaxRequestsPerChild 100

# Carico solo quello che mi serve:
#LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule env_module         modules/mod_env.so
LoadModule config_log_module  modules/mod_log_config.so
#LoadModule agent_log_module   modules/mod_log_agent.so
LoadModule referer_log_module modules/mod_log_referer.so
LoadModule mime_module        modules/mod_mime.so
#LoadModule negotiation_module modules/mod_negotiation.so
#LoadModule status_module      modules/mod_status.so
#LoadModule info_module        modules/mod_info.so
#LoadModule includes_module    modules/mod_include.so
LoadModule autoindex_module   modules/mod_autoindex.so
LoadModule dir_module         modules/mod_dir.so
LoadModule cgi_module         modules/mod_cgi.so
#LoadModule asis_module        modules/mod_asis.so
#LoadModule imap_module        modules/mod_imap.so
#LoadModule action_module      modules/mod_actions.so
LoadModule userdir_module     modules/mod_userdir.so
LoadModule alias_module       modules/mod_alias.so
#LoadModule rewrite_module     modules/mod_rewrite.so
LoadModule access_module      modules/mod_access.so
LoadModule auth_module        modules/mod_auth.so
#LoadModule anon_auth_module   modules/mod_auth_anon.so
#LoadModule db_auth_module     modules/mod_auth_db.so
#LoadModule digest_module      modules/mod_digest.so
#LoadModule proxy_module       modules/libproxy.so
#LoadModule expires_module     modules/mod_expires.so
#LoadModule headers_module     modules/mod_headers.so
#LoadModule usertrack_module   modules/mod_usertrack.so
LoadModule setenvif_module    modules/mod_setenvif.so

ClearModuleList
#AddModule mod_vhost_alias.c
AddModule mod_env.c
AddModule mod_log_config.c
#AddModule mod_log_agent.c
AddModule mod_log_referer.c
AddModule mod_mime.c
#AddModule mod_negotiation.c
#AddModule mod_status.c
#AddModule mod_info.c
#AddModule mod_include.c
AddModule mod_autoindex.c
AddModule mod_dir.c
AddModule mod_cgi.c
#AddModule mod_asis.c
#AddModule mod_imap.c
#AddModule mod_actions.c
AddModule mod_userdir.c
AddModule mod_alias.c
#AddModule mod_rewrite.c
AddModule mod_access.c
AddModule mod_auth.c
#AddModule mod_auth_anon.c
#AddModule mod_auth_db.c
#AddModule mod_digest.c
#AddModule mod_proxy.c
#AddModule mod_expires.c
#AddModule mod_headers.c
#AddModule mod_usertrack.c
AddModule mod_so.c
AddModule mod_setenvif.c

Listen 80

####### Red Hat 6.2:
User nobody
Group nobody
####### Red Hat 7.1:
#User apache
#Group apache

ServerAdmin root@localhost

# Permessi globali:
<Directory />
    Options IncludesNOEXEC Indexes SymLinksIfOwnerMatch
    AllowOverride None
</Directory>

UserDir public_html

# Permessi di base per le dir. degli utenti:
<Directory "/home/*/public_html">
    AllowOverride All
    Options Includes Indexes SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
</Directory>

ScriptAliasMatch /~(.*)/(.*)\.cgi  /home/$1/public_html/$2.cgi
ScriptAliasMatch /~(.*)/cgi-bin/(.*)  /home/$1/public_html/$2

<Directory /home/*/public_html/cgi-bin>
        AllowOverride All
        Options ExecCGI
</Directory>

DirectoryIndex index.html index.htm index.shtml index.cgi _index

AccessFileName .htaccess

<Files ~ "^\.ht">
    Order allow,deny
    Deny from all
</Files>

UseCanonicalName On

TypesConfig /etc/mime.types

DefaultType text/plain

HostnameLookups Off

ErrorLog /var/log/httpd/error_log

LogLevel warn

#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
#LogFormat "%{Referer}i -> %U" referer
#LogFormat "%{User-agent}i" agent
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\"" mioformatolog

CustomLog /var/log/httpd/access_log mioformatolog

ServerSignature On

Alias /icons/ "/home/httpd/icons/"

<Directory "/home/httpd/icons">
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

IndexOptions FancyIndexing

AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip

AddIconByType (TXT,/icons/text.gif) text/*
AddIconByType (IMG,/icons/image2.gif) image/*
AddIconByType (SND,/icons/sound2.gif) audio/*
AddIconByType (VID,/icons/movie.gif) video/*

AddIcon /icons/binary.gif .bin .exe
AddIcon /icons/binhex.gif .hqx
AddIcon /icons/tar.gif .tar
AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
AddIcon /icons/a.gif .ps .ai .eps
AddIcon /icons/layout.gif .html .shtml .htm .pdf
AddIcon /icons/text.gif .txt
AddIcon /icons/c.gif .c
AddIcon /icons/p.gif .pl .py
AddIcon /icons/f.gif .for
AddIcon /icons/dvi.gif .dvi
AddIcon /icons/uuencoded.gif .uu
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
AddIcon /icons/tex.gif .tex
AddIcon /icons/bomb.gif core

AddIcon /icons/back.gif ..
AddIcon /icons/hand.right.gif README
AddIcon /icons/folder.gif ^^DIRECTORY^^
AddIcon /icons/blank.gif ^^BLANKICON^^

DefaultIcon /icons/unknown.gif

ReadmeName README
HeaderName HEADER

IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t

AddEncoding x-compress Z
AddEncoding x-gzip gz tgz

AddLanguage en .en
AddLanguage fr .fr
AddLanguage de .de
AddLanguage da .da
AddLanguage el .el
AddLanguage it .it

# v. mod_negotiation
#LanguagePriority it en fr de

AddType text/html .shtml
AddHandler server-parsed .shtml

AddHandler imap-file map

BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0

NameVirtualHost 127.0.0.1:80

<VirtualHost 127.0.0.1:80>
    ServerName localhost.localdomain
    DocumentRoot /home/httpd/html
    ServerAdmin root@casa.lan
    ErrorLog logs/localhost.localdomain-error_log
    CustomLog logs/localhost.localdomain-access_log common
</VirtualHost>

<VirtualHost 127.0.0.1:80>
    ServerName www.tizio.casa
    User tizio
    Group users
    DocumentRoot /home/tizio/public_html
    ServerAdmin root@casa.lan
    ErrorLog logs/www.tizio.casa-error_log
    CustomLog logs/www.tizio.casa-access_log common
    ScriptAlias /cgi-bin /home/tizio/public_html/cgi-bin
    ScriptAliasMatch /(.*)\.cgi  /home/tizio/public_html/$1.cgi
</VirtualHost>

<VirtualHost 127.0.0.1:80>
    ServerName www.caio.casa
    User caio
    Group users
    DocumentRoot /home/caio/public_html
    ServerAdmin root@casa.lan
    ErrorLog logs/www.caio.casa-error_log
    CustomLog logs/www.caio.casa-access_log common
    ScriptAlias /cgi-bin /home/caio/public_html/cgi-bin
    ScriptAliasMatch /(.*)\.cgi  /home/caio/public_html/$1.cgi
</VirtualHost>

#### httpd.conf: FINE!

Conclusioni

Abbiamo visto come in ambiente multiutente si possono creare siti WEB per domini virtuali, abbiamo collocato questi siti in spazi isolati del sistema, abbiamo visto come ciascun soggetto possa creare i propri programmi CGI che girano con la propria identità. Ogni utente può creare file e gestire dati nello spazio della propria home directory, senza interferenze con gli altri utenti.

Bibliografia

Apache 1.3 User's Guide - La documentazione ufficiale di Apache; http://www.apache.org/doc.
RFC 2616 - Specifiche del protocollo HTTP versione 1.1; http://www.rfc-editor.org/.

APACHE : Configuriamo Apache

In questa lezione impareremo a configurare Apache; questa parte è importantissima, perché da una corretta configurazione dipende il corretto funzionamento di Apache.

Apriamo il file httpd

Andiamo alla riga 230:

Port 80

In questa opzione viene definita la porta che apache utilizzerà per il protocolo http. Lasciamo 80, che è la porta di default dei webserver.

Andiamo alla riga 257:

ServerAdmin tuonome@dominio.it

In questa opzione viene definita l’e-mail dell’amministratore del server.

Andiamo alla riga 255:

ServerName www.tuonome.it

In questa opzione possiamo inserire il nome del domionio, se abbiamo configurato i DNs, l’indirizzo IP del server, oppure il classico 127.0.0.1, se stiamo lavorando in locale. Questo passo è importantissimo, perché indica l’indirizzo con cui verrà raggiunto il nostro server.

Andiamo alla riga 263:

DocumentRoot "C:/Inetpub/wwwroot"

In questa opzione viene indicata la cartella dove sono inserito tutti i file del nostro sito web, la classica wwwroot.


Introduzione:
Apache, il cui sviluppo (ricordiamo che il team è formato da volontari, noti come l'Apache Group) è arrivato alla versione 1.3.12, è nato come rimpiazzo per il webserver httpd 1.3 sviluppato dal NCSA (National Center for Supercomputing Applications), inglobandone le carrateristiche, risolvendone i problemi ed implementando nuove features.
Come sopra accennato, Apache è un webserver per il protocollo HTTP, designato per poter girare come un processo standalone, senza ciò chiedere l'appoggio ad altre applicazioni o direttamente all'utente. Per poter fare ciò, Apache, una volta che sia stato avviato, crea dei sottoprocessi (comunemente e meglio detti "children processes") per poter gestire le richieste: questi processi, comunque, non potranno mai interferire con il processo maggiore, ma può succedere l'opposto: mandando un segnale di stop a questo, anche i children saranno terminati.
Un tipico albero dei processi di Apace potrebbe essere qualcosa di simile a:

USER PID %CPU %MEM SIZE RSS TTY STAT START TIME COMMAND
root 203 0.01 1.01 4952 720 ? S 17.20 0.03 /usr/sbin/apache
user 212 0.00 2.03 5012 1456 ? S 17.20 0.00 \_ /usr/sbin/apache
user 213 0.00 2.02 5008 1424 ? S 17.20 0.00 \_ /usr/sbin/apache
user 214 0.00 0.00 4976 0 ? SW 17.20 0.00 \_ (apache)
user 216 0.00 0.00 4976 0 ? SW 17.20 0.00 \_ (apache)
user 473 0.00 1.06 4976 1072 ? S 18.05 0.00 \_ /usr/sbin/apache
user 477 0.00 1.07 4976 1076 ? S 18.05 0.00 \_ /usr/sbin/apache
user 478 0.00 2.04 5012 1544 ? S 18.05 0.00 \_ /usr/sbin/apache


Ricordiamo inoltre che Apache è distribuito come free software, per esplicito desiderio del team che lo sviluppa: questi, infatti, ritengono che strumenti di questo genere debbano essere accessibili a tutti, e che le software house debbano guadagnarci solo producendo addons o simili di valore, o magari personalizzati per alcune categorie di utenti. Inoltre, lasciando il software in mano di chiunque nonchè completo di sorgenti, è possibile che costoro contribuiscano, sia tramite feedback sia tramite vere e proprie patch, a migliorare il prodotto finale. Date le loro premesse, come dare loro torto?

Vediamo brevemente alcune tra le moltissime modifiche introdotte nella versione 1.3 rispetto alla 1.2:

Ovviamente non è tutto qui; quelle qui riportate sono le modifiche "umanamente intelleggibili", ossia quelle che un utente medio capisce senza troppi problemi. Per chi voglia approfondire l'argomento, consiglio la pagina "new_features_1_3.html" presente nella documentazione di Apache stesso.

Per coloro che non l'abbiano ancora fatto, ricordo che l'argomento è stato precedentemente affrontato nella guida ai CGI nonchè in un articolo a parte per quanto riguarda l'installazione su piattaforma Win32. Inoltre, moltissima documentazione la potete trovare nei vostri hard-disk dopo avere installato Apache sulle vostre macchine o ancora alla pagina http://www.apache.org, sito ufficiale del progetto Apache. Per chi intenda installare o comunque approfondire le proprie conoscienze su Apache in relazione a sistemi Windows, ricordo la pagina "windows.html" presente nel manuale HTML che vi verrà installato a supporto del server.

Porte:
Iniziamo con la porta su cui mettere in listening il webserver (non nel caso in cui esso sia chiamato da inet): il numero specificabile per la porta varia da un range da 0 a 65535, di cui le prime 1024 sono riservate per determinati protocolli; la porta riservata per il protocollo http è comunque, di efault, la 80. Per chi volesse saperne di più sulle porte ed il relativo protocollo associato, maggiori informazioni possono essere trovate nel file /etc/services (sistemi Unix). Un'altra particolarità della porta 80 ed in generale delle porte al di sotto della 1024 è che sono "di sistema", nel senso che i normali utenti non possono farne uso. Quindi, è necessario che apache sia fatto partire dall'utente root nel caso si utilizzi la porta 80 (che è comunque consigliato); in seguito, prima di essere pronto ad accettare le richieste, l'esecuzione di Apache sarà "spostata" all'utente definito poco oltre nel file httpd.conf (lo vedremo in seguito): in questo modo, tutti i processi children saranno su porte il cui numero è maggiore di 1024.

Utenti:
Abbiamo parlato poco sopra degli utenti con i privilegi dei quali Apache è fatto girare: la direttiva che ci interessa è "User". Per utilizzare tale direttiva, è necessario che l'utente che ha avviato Apache SIA root. Il nome dell'utente può essere specificato come il nome a caratteri (ad esempio, nome_utente) oppure tramite il suo ID numerico preceduto dal simbolo # (ad esempio, # 1002). Questo utente non dovrebbe avere troppi provilegi sul sistema, come ad esempio la possibilità di leggere importanti file di sistema, lanciare eseguibili che non hanno a che fare con httpd e simili. La cosa migliore da fare è quella di creare un nuovo utente ad hoc per l'esecuzione di Apache, visto che anche scegliere l'utente "nobody" può non essere la scelta migliore. Ovviamente, inoltre, è fortemente sconsigliato specificare "root" nella direttiva "User". Il perchè mi sembra chiarissimo. Assieme ad "User", inoltre, dovrete specificare anche un nome di gruppo per la direttiva "Group": se avete creato un nuovo utente (supponiamo "prova") per far girare Apache, potrete inserire "prova" anche per il gruppo, a meno che abbiate la necessità di utilizzare un Group differente.

Directory:
Vediamo qui le directory che interesseranno Apache: parleremo qui sia delle directory di configurazione sia di quelle utilizzate per contenere le pagine che daranno forma ad uno o più siti web.
Scorrendo il file httpd.conf, ci imbatteremo presto nella direttiva "ServerRoot": in questa directory saranno contenuti i file di configurazione di Apache, gli errori ed i log, se non specificato differentemente. Evitate che tale directory sia visibile dal web, piuttosto scegliete una directory come /etc/apache oppure /var/log/apache. Bisognerà anche fare attenzione ai permessi da dare a questa directory: i file che essa contiene, infatti, sono alquanto importanti e possono modificare radicalmente il comportamento del server: evitate quindi che altri utenti al di fuori dell'amministratore possano leggere e scrivere al suo interno. Inoltre, per lo stesso discorso, fate lo stesso anche con le directory ed i file di log.
Passiamo poi alla direttiva "DocumentRoot": in questa directory saranno presenti i documenti visualizzabili dal web, in poche parole il sito principale associato al webserver. Per essere ancora più chiaro, se il nome del vostro host è "www.server.it", se un utente digiterà dal browser l'indirizzo "www.server.it" appariranno proprio le pagine presenti in "DocumentRoot".
Poco sotto a DocumentRoot c'è la direttiva "DirectoryIndex": a cosa serve è presto detto. Provate a digitare nel browser l'indirizzo di un qualsiasi server e notate che non inserite alcun nome del file che abbia estensione html, eppure il 90% dei file visibili in rete sono in html! Se questo accade, è grazie alla direttiva "DirectoryIndex": specificando ad esempio "index.html" come valore della direttiva, saremo sicuri che, se in una directory è presente un file chiamato "index.html", Apache farà in modo che non sia necessario digitare nomedirectory/index.html perchè sia visualizzato tale file, ma solamente nomedirectory. Facciamo un esempio: sul server "www.server.com" è presente una directory chiamata, ad esempio, prova, nella quale è presente un file chiamato index.html: per vedere tale file, non sarà necessario digitare "www.server.com/prova/index.html" ma soltanto "www.server.com/prova". Avrete capito così perchè quando si chiama dal browser qualcosa come "www.html.it" non è mai necessario inserire anche "index.html": in fondo, anche www.html.it è una directory su un server! Un'ultima cosa relativa a DirectoryIndex è il fatto di poter indicare diversi nomi di pagine, non solo index.html: i più significativi possono essere "index.shtml", "index.htm" ecc, l'importante è che questi siano separati da spazi.
Veniamo ora alla directory UserDir, impostata di default su /home/*/public_html. Già quel "public_html" dovrebbe avervi fatto capire qualcosa: infatti, i file presenti nella directory /home/nomeutente/public_html sono visualizzati quando, dopo il nome di dominio, sia specificato anche ~nomeutente: se ad esempio sulla macchina "www.server.com" è presente un utente "test", la cui home directory è "/home/test" contenente una sottodirectory chiamata "public_html", se dal browser sarà digitato "www.server.com/~test" appariranno proprio i file presenti nella directory "/home/test/public_html".
Ovviamente, ogni utente deve avere un account sulla macchina. E avete capito così per sommi capi anche come funzionano le comunità virtuali su internet.


Avvio su Unix:
L'avvio di Apache puù essere fatto in due modi: al boot della macchina oppure tramite il demone inetd ogni volta che ci sia la richiesta di una connessione HTTP. La seconda possibilità è comunque poco raccomandata, in quanto è sempre meglio avere il server attivo e pronto a ricevere le richieste.
Quindi ipotizzeremo qui che Apache sia avviato al boot della macchina e terminato al suo spegnimento: se parliamo di un server web, capirete che tra i due momenti passerà molto tempo (visto l'uptime di questi tipi di macchine), e quindi Apache resterà attivo per tutto il tempo durante il quale la macchina è accesa e, ovviamente, connessa in rete, locale o remota che sia.
L'avvio al boot è determinato da un semplice script presente in /etc/init.d : il nome dello script è, fantasiosamente, apache! Leggendolo, molti si potebbero spaventare: sapendo scremare tutto quanto è superfluo ai nostri scopi, possiamo ridurci a considerare solo le chiamate che ci interessano, senza curarci di cosa effettivamente avviene per ognuna.
La prima è "start": come apparirà chiaro, con questa chiamata Apache viene attivato, in modo che si crei il processo padre che sarà seguito dai processi children per gestire le chiamate. La chiamata start è quella che viene fatta al boot della macchina e, per accertarcene, sarà sufficiente controllare che, al boot, appaia una riga simile a:
Starting web server: apache.
Se ciò avviene, possiamo stare sicuri che Apache sia già in ascolto sulla porta 80 del server ma, se proprio vogliamo essere pignoli, possiamo controllare tra la lista dei processi se appare (e deve apparire) anche Apache con i suoi processi children. Per la prova del nove, se l'avete già configurato anche sommariamente, potete digitare dal browser l'indirizzo "http://localhost" per controllare che Apache vi risponda.

Riavvio e stop su Unix:
Il riavvio ha un ruolo alquanto importante: supponete di avere una macchina impiegata a tempo pieno come server, e di effettuare alcune modifiche alla configurazione dell'Apache che gira su di essa; cosa fareste per rendere attive le modifiche?
Coloro che, ricordando che Apache viene avviato all'avvio e pensando che sia necessario riavviare la macchina perchè le modifiche abbiano effetto si sbagliano: come esiste la chiamata "start", esiste anche la chiamata "restart", solo che questa deve essere data a mano tramite il comando:

/etc/init.d/apache restart

Ma a cosa serve il riavvio di Apache?
Ipotizzate di gestire un server e che decidiate di includere il supporto per lo scripting PHP: dovrete fare in modo che apache riconosca questi tipi di script, caricando l'apposito modulo (libphp3.so).
Come fare è presto detto: nel file httpd.conf, basterà decommentare la linea:

#LoadModule php3_module /usr/lib/apache/1.3/libphp3.so

Ricordiamo però che, essendo questa una modifica in run-time, Apache non potrà attuare la modifica a meno che sia riavviato. E la chiamata restart serve proprio a questo: se dovessimo riavviare il server completamente (senza dubbio anche questa soluzione funzionerebbe), rischieremmo un downtime del server troppo lungo: non stiamo parlando solamente di Apache, ma di tutte le funzioni a cui il server è preposto: servizi FTP, POP, SMTP ecc.
Con la chiamata restart, invece, andremo a riavviare solamente Apache, limitando il downtime al solo server HTTP, e tra l'altro il downtime risulterà molto più breve di un reboot della macchina, sull'ordine di una decina di secondi.
Capirete quindi l'utilità della chiamata restart.

L'ultima chiamata è stop: sarà senza dubbio chiaro che tramite stop fermeremo Apache del tutto.
La chiamata di stop può essere fatta in due modi: il primo è in automatico, allo spegnimento della macchina, quando cioè init manderà un SIGTERM a tutti i procesi attivi; per Apache, dovremmo veder comparire qualcosa del tipo:

Stopping web server: apache.

Se per qualche motivo abbiate bisogno di fermare apache a mano, ad esempio in caso di problemi non risolvibili all'istante, oppure di upgrade del pacchetto stesso (magari con un altro server in clustering per tenere attive le richieste!), la procedura sarà sempre la solita: basterà lanciare:

/etc/init.d/apache stop

e sarete sicuri che apache dopo pochi istanti smetterà di girare.

Avvio, riavvio e stop su NT:
Per questa breve sezione ci baseremo fortemente su NT, visto che far girare un webserver su un sistema win9x è impresa ardua, mancando a questo molte delle caratteristiche proprie di NT.

I modi per avviare Apache sono due:

Per avviare Apache come un servizio, è prima becessario che questo sia effettivamente installato come un servizio sula macchina: dal menu d'avvio, scegliete l'opzione "Install Apache as Service"; fatto questo, apache potrà essere avviato aprendo la finestra dei servizi (dal pannello di controllo), scegliendo Apache e successivamente su "start". Nel caso si volesse fermarlo, ovviamente, basterà cliccare su "stop".

In alternativa, Apache può essere avviato dalla linea di comando tramite i comandi:

NET START APACHE
NET STOP APACHE


rispettivamente per avviarlo e fermarlo.

Per avviare invece Apache da console, e non come un servizio, basterà cliccare l'opzione "Apache Server" dal menu d'avvio: verrà quindi aperta una finestra dos che restarà aperta durante tutto il funzionamento del webserver.
Per il restart o lo stop, sarà sufficiente aprire un'altra finestra e digitare, rispettivamente:

apache -k restart

oppure:

apache -k shutdown

Entrambe sono altamente preferibili ad un brutale "Ctrl+c", che chiuderebbe Apache invece di arrestarlo, con tutte le conseguenze del caso.


Apache per Windows:
Come avviene per i sistemi Unix, anche una normale installazione sotto Windows comprende una directory nella quale è presente una ricca documentazione per il webserver; questa è, solitamente, ./htdocs/manual, sottodirectory della directory principale definita durante l'installazione. Tutto il manuale è in formato HTML, ed è a grandi linee l'equivalente del manuale online leggibile all'indirizzo http://www.apache.org. In questo sito, è inoltre possibile leggere delle note specifiche alla distribuzione Windows alla pagina http://www.apache.org/docs/windows.html
Essendo Apache un webserver sviluppato su piattaforma Unix, ed essendo la versione per Windows un porting, apparirà chiaro che la versione di Apache per Windows non è completamente ottimizzata per offrire le migliori performances, come avviene invece per la versione Unix. Per dire ciò, l'Apache Group si basa su prove comparative del software su differenti piattaforme.
Il risultato del lavoro di porting, come loro stessi dicono, è un "ottimo codice ancora in beta", visto che il funzionamento è garantito per differenti gradi di utenza ma non è ancora al livello raggiunto sulle piattaforme per le quali Apache è stato originariamente pensato. Quindi funzionamento e performances garantite, anche se non ai massimi livelli.

Vediamo ora una rapida carrellata dei maggiori problemi (noti) di Apache utilizzato sotto Windows.

Messaggi d'errore personalizzati:
Vedremo in queste pagine come personalizzare i messaggi d'errore di Apache. I responsi personalizzati del webserver possono servire ai webmaster per far meglio capire agli utenti ciò che succede quando il loro browser esce con un messaggio d'errore in seguito ad una richiesta impossibile da soddisfare per i più svariati motivi (errori nell'esecuzione di script, richiesta id pagine inesistenti ecc.). I risultati della peronsonalizzazione possono essere fondamentalmente di due tipi: semplici messaggi di testo che spiegano sommariamente l'accaduto e redirezioni verso URL interne o esterne al nostro host.
Per impostare Apache in modo che riesca a produrre dei messaggi d'errore personalizzati bisognerà andare ad agire sul file srm.conf nella rootdir del webserver; in esso leggeremo infatti qualcosa del tipo:

# Customizable error response (Apache style)
# these come in three flavors
#
# 1) plain text
#ErrorDocument 500 "The server made a boo boo.
# n.b. the (") marks it as text, it does not get output
#
# 2) local redirects
#ErrorDocument 404 /missing.html
# to redirect to local url /missing.html
#ErrorDocument 404 /cgi-bin/missing_handler.pl
# n.b. can redirect to a script or a document using
# server-side-includes.
#
# 3) external redirects
#ErrorDocument 402 http://some.other_server.com/subscription_info.html


La sintassi base per i messaggi d'errore personalizzati è quindi:

ErrorDocument XXX azione

dove "ErrorDocument" è la direttiva, XXX è un numero di tre cifre corrispondente al codice d'errore del server (ad esempio 404, 500 ecc.) e "azione" è quello che il server deve fare in caso si riscontrino questi errori.

Soffermiamoci su "azione" prima di vedere alcuni esempi: questa può essere:

E' consigiato non abusare troppo delle redirezioni, soprattutto di quelle esterne: a molti potrebbe dare fastidio trovarsi inspiegabilmente in un sito differente dal vostro per motivi che non si riescono a spiegare.

Vediamo ora qualche esempio per chiarire le cose:


Errori di Apache
L'errore più noto che può essere notificato da Apache è il 404, di cui abbiamo parlato in precedenza, il famoso "File not found". Alla base di questa notifica vi è una dinamica abbastanza semplice e conosciuta:
1. Il client vorrebbe accedere ad una risorsa è digita un'URL o clicca su un link per comunicare la richiesta.
2. Il Web server non trova la risorsa desiderata nel percorso indicato, registra l'errore nei "log" e invia una notifica.
3. Il browser del client visualizza una pagina Html contenente la notifica dell'errore riscontrato.
La maggior parte delle risposte di Apache a richieste che non possono essere soddisfatte sono configurabili, è sufficiente agire sulla direttiva ErrorDocument indicando la tipologia di errore ("numero", o "codice" di erore) e il messaggio che si desidera venga visualizzato dall'utente. In alternativa è possibile redirigere il browser del client su una pagina di notifica (tipo "error.html") in cui dare al navigatore maggiori informazioni, scusarsi del disagio arrecato o fornire consigli su come reperire ugualmente la risorsa cercata.
Apache notifica principalmente due tipologie di errore: i 4XX, derivanti dalle richieste dei client e i 5XX dovuti alle risposte dei Web server.
Tra i 4XX abbiamo:
* 400: la richiesta non viene recepita da Apache in quanto incomprensibile (ad es: un errore sintattico nella digitazione dell'URL).
* 401: essendo necessaria un'autorizzazione per accedere alla risorsa richiesta, coloro che non la possiedono non potranno accedere ad essa.
* 402: la risorsa richiede un qualche forma di pagamento per poter essere accessibile.
* 403: Apache rifiuta di permettere l'accesso all'utente.
* 404: File Not Found
* 405: viene notificato un errore nel metodo con il quale viene effettuata la richiesta.
* 406: la risposta del server non è compatibile con la tipologia di richiesta.
* 407: la richiesta non può essere soddisfatta senza una previa autenticazione col proxy.
* 408: la richiesta del client si è fatta attendere oltre i tempi consentiti dalla Web Server ("Time Out").
* 409: notifica dei conflitti tra richiesta e risposta desiderata.
* 410: risposta non disponibile, neanche tramite un redirect.
* 411: non sarà possibile una risposta fino alla definizione del "Content-Length" (lunghezza richiesta).
* 412: prerequisito necessario alla soddisfazione della richiesta fallito.
* 413: la richiesta richiede una risorsa più grande di quella che Apache è in grado di processare.
* 414: URL troppo lunga proveniente dalla richiesta.
* 415: il formato della richiesta non è supportato.
Per quanto riguarda le notifiche 5XX, abbiamo invece appena sei voci:
* 500: errore interno al server, generalmente causato da un malfunzionamento del programma che mette a disposizione il servizio.
* 501: server non implementato per poter soddisfare la tipologia di richiesta.
* 502: il gatway o il proxy collegati al server inviano una risposta errata.
* 503: la richiesta inviata è temporaneamente inesaudibile.
* 504: il gatway o il proxy collegati al server inviano una risposta andando oltre il tempo concesso prima della notifica del "Time Out".
* 505: la versione del protocollo HTTP attraverso cui il client ha effettuato la richiesta non è supportata.


Limitare l'accesso con Apache
L'unica cosa che sarà necessario appurare è di avere come server Apache.
Appurato ciò, sarà necessario creare un file e chiamarlo: .htaccess, fatto questo basterà inserire il seguente codice:
deny from 26.7.19.88
oppure
deny from host.provider.com
Il primo caso limita l'accesso all'indirizzo IP scelto (che ovviamente è da cambiare) nel senso esempio si blocca l'accesso all'host definito.
Per bloccare l'accesso a più indirizzo basta inserire uno sotto l'altro i vari indirizzi da bloccare.