Quando si parla di Apache e controllo degli accessi il pensiero va immediatamente all'autenticazione di base HTTP, realizzata generalmente mediante un file .htpasswd
contenente nomi utente e password cifrate. È il sistema più semplice, più conosciuto e maggiormente utilizzato per creare aree ad accesso limitato in un sito web. Non è però l'unico.
In queste pagine vedremo come sia possibile implementare uno schema di controllo basato sul nome di host o sull'indirizzo IP del client. Il modulo
mod_access (disponibile fino alla versione 2.1 poi sostituito da
mod_authz_host
), grazie alle direttive Allow,
Deny ed Order, permette di realizzare tale tipo di restrizione. Naturalmente nulla vieta di utilizzare contemporaneamente una limitazione d'accesso basata su host ed una basata su password, in questo caso la direttiva
Satisfy determina come le due componenti debbano interagire.
Non andiamo oltre e per ora accontentiamoci di focalizzare l'attenzione sugli elementi fondamentali.
La direttiva Allow
La sintassi basilare della direttiva è:
Allow from host1 host2 host3 ...
Essa determina quali host possano accedere ad una certa area. Il contesto d'applicazione è
<Directory>, <Files>, <Location>
o file di configurazione per-directory (.htaccess
).
Cominciamo subito con qualche esempio per chiarirne l'utilizzo. Se vogliamo concedere l'accesso a tutti:
Allow from all
Sebbene una simile configurazione possa apparire inutile e ridondante, non lo è affatto se utilizzata in combinazione con le direttive Deny ed Order come si vedrà in seguito.
Passiamo ora a permettere l'accesso ad un particolare host sulla base del suo nome di dominio completo (FQDN, Fully Qualified Domain Name):
Allow from mioserver.miodominio.it
Se invece vogliamo limitarci a nomi di dominio parziali:
Allow from miodominio.it
Allow from .org altrodominio.biz
In questo caso verranno esplicitamente fornite le risorse richieste a tutti gli host il cui nome corrisponde o termina secondo quanto specificato dalle direttive. Quindi rispettano la prima condizione sia server1.miodominio.it che server2.miodominio.it. La corrispondenza deve essere completa ovvero non verrà autorizzato server3.ilmiodominio.it.
Con il secondo allow accettiamo tutti gli host con TLD org oltre a quelli appartenenti al dominio altrodominio.biz.
Passiamo ora ad utilizzare gli indirizzi IP. In questo caso uno o più indirizzi specificati godranno dell'accesso:
Allow from 217.199.180.20
Allow from 10.26.1.20 10.26.1.30
Possiamo limitarci ad indicare alcuni ottetti per specificare le sottoreti ammesse:
Allow from 192.168.50
Allow from 217.171.50 62.110
La prima riga, ad esempio, consente l'accesso a tutti gli host con indirizzi da 192.168.50.1 a 192.168.50.255. Analoga sarà l'interpretazione della seconda riga.
Possiamo riferirci anche ad una coppia rete-maschera di rete o CIDR (Classless Inter-Domain Routing):
Allow from 217.199.180.0/255.255.255.0
Allow from 192.30.250.0/19
La direttiva Deny
Ha sintassi analoga alla precedente così come medesimo contesto d'applicazione: <Directory>, <Files>, <Location> e file di configurazione per-directory.
Deny from host1 host2 host3 ...
Il suo significato risulta esattamente opposto ad Allow, ovvero definisce a quali host debba venir inibito l'accesso.
Deny from server1.miosito.it
Così facendo l'host server1.miosito.it verrà escluso dalle risorse rese disponibili sul sito.
L'esemplificazione di questa direttiva si ridurrebbe ad una mera ripetizione al negativo della precedente. Vi risparmio, dunque, un'inutile elencazione passando all'argomento successivo.
La direttiva Order
Quest'istruzione determina in che ordine Apache debba valutare le precedenti direttive Allow e Deny. Nella pratica le configurazioni vengono comunemente realizzate ricorrendo ad essa in combinazione con le altre, come comprenderemo meglio dai successivi esempi. La sua sintassi è:
Order tipo_ordine
Le possibili varianti per "tipo_ordine" sono:
- Deny,Allow: la direttiva deny viene valutata prima di allow; l'accesso è permesso per default; qualunque host non elencato in deny o elencato in allow ottiene l'accesso.
- Allow,Deny: la direttiva allow viene valutata prima di deny; l'accesso è negato per default; qualunque host non elencato in allow o elencato in deny non ottiene l'accesso.
- Mutual-failure: sebbene poco utilizzata esiste anche questa scelta. Essa indica che solo gli host della lista di allow che non compaiono in deny hanno il permesso di accedere.
L'ambito di applicazione sarà, al solito, <Directory>, <Files>, <Location>
e file di configurazione per-directory.
Passiamo subito a qualche esempio chiarificatore. Se vogliamo negare l'accesso alla directory /miosito/dir_controllata all'host host.cattivo.it ed autorizzare tutti gli altri:
<Directory /miosito/dir_controllata>
Order Deny,Allow
Deny from host.cattivo.it
Allow from all
</Directory>
Ora neghiamo l'accesso a chiunque tranne agli host del dominio dominiofidato.it:
<Directory /miosito/dir_controllata>
Order Deny,Allow
Deny from all
Allow from dominiofidato.it
</Directory>
Proseguiamo negando, come sopra, l'accesso a tutti tranne agli host del dominio dominiofidato.it, però tra questi escludiamo escluso.dominiofidato.it:
<Directory /miosito/dir_controllata>
Order Allow,Deny
Allow from dominiofidato.it
Deny from escluso.dominiofidato.it
</Directory>
Il risultato appare chiaro se si rammenta che per l'opzione Allow,Deny l'accesso è negato di default. Attenzione che in questo caso, se non specifichiamo nulla oltre ad Order, otterremo comunque di negare l'accesso a tutti stante la condizione di default:
<Directory /miosito/dir_controllata>
Order Allow,Deny
</Directory>
La configurazione che segue è tratta direttamente dal file httpd.conf ed impedisce la visualizzazione dal web dei file .htaccess e .htpasswd:
<Files ~ "^.ht">
Order allow,deny
Deny from all
</Files>
Ancora un esempio proveniente dal file di configurazione di Apache, sempre fonte d'ispirazione, che autorizza la visualizzazione dei report sullo stato del server all'host www.miosito.it digitando http://www.miosito.it/server-status:
<Location /server-status>
SetHandler server-status
Order deny,allow
Deny from all
Allow from www.miosito.it
</Location>
Termino segnalando che le direttive vengono valutate secondo l'ordine stabilito da Apache per i diversi contenitori, in altre parole un order all'interno di un contenitore
<Location>
viene valutato dopo un order che si trova in una sezione
<Directory>
o in un file .htaccess, potendo così stravolgere quanto precedentemente impostato.
Conclusioni
Sin qui abbiamo analizzato le istruzioni fondamentali che permettono il controllo degli accessi basato sull'host. Dopo aver familiarizzato con queste passeremo, in un prossimo articolo, ad esaminare qualche particolarità entrando maggiormente nel dettaglio di alcune configurazioni. Se siete interessati ad approfondire l'argomento vi do appuntamento, a breve, sulle pagine di HTML.it.
Nella prima parte dell'articolo abbiamo analizzato le configurazioni fondamentali che consentono di limitare l'accesso a sezioni del nostro sito, operando un controllo basato sull'hostname o sull'indirizzo IP dei client. In particolare ci eravamo soffermati sulle direttive Allow
, Deny
e Order
. Dopo aver compreso le basi del meccanismo implementato dal Web server Apache per mezzo del modulo mod_access (dalla versione 2.1 in poi sostituito da mod_authz_host
), proseguiremo trattando alcuni aspetti un po' meno comuni del suo utilizzo.
Controllo basato sulle variabili d'ambiente
Affermando che Apache sia in grado di controllare l'accesso dei client sulla base della combinazione IP/hostname abbiamo, per semplicità, trascurato il fatto che può catturarne altre caratteristiche. Queste potranno essere gestite mediante alcune variabili d'ambiente, environment variables. Gli esempi, come al solito, chiariranno meglio il concetto, mentre rimando al link ufficiale chi fosse interessato ad un approfondimento. Completiamo la sintassi di Allow
e Deny
, in precedenza descritta, aggiungendo un'ulteriore variante:
Allow from env=variabile
Deny from env=variabile
Supponiamo di voler limitare l'accesso sulla base dello User-Agent del client, riconoscibile dagli header della richiesta HTTP. Abbiamo costruito una sezione del sito compatibile solo con Internet Explorer e quindi vogliamo tenere alla larga gli altri browser.....mi raccomando è solo un esempio!
BrowserMatch MSIE ms_browser <Directory /miosito/dir_controllata> Order Deny,Allow Deny from all Allow from env=ms_browser </Directory>
Utilizzando la direttiva BrowserMatch impostiamo la variabile ms_browser
quando il client ci fornisce, nell'header relativo, la stringa MSIE, tipica di Internet Explorer. Successivamente chiudiamo le maglie negando l'accesso a tutti, tranne ai browser per cui la variabile d'ambiente risulta impostata.
Nell'esempio che segue concediamo l'accesso alla directory solo se la pagina di provenienza (referer) si trova su www.miosito.it e quindi risulta impostata la variabile d'ambiente internal_pg
.
SetEnvIf Referer www.miosito.it internal_pg <Directory /miosito/dir_controllata> Order Deny,Allow Deny from all Allow from env=internal_pg </Directory>
L'approfondimento delle direttive BrowserMatch
e SetEnvIf
ci porterebbe lontani, d'altro canto il loro utilizzo negli esempi risulta immediato. Per chi non si accontentasse è sempre disponibile la documentazione ufficiale. Tralascio, inoltre, analoghi esempi che si potrebbero fare con la direttiva Deny
in quanto speculari a quelli visti.
Controllo basato sul metodo HTTP
Sin qui le direttive adottate hanno fatto implicitamente riferimento a tutti i metodi HTTP: GET, POST, PUT, CONNECT etc. In alcuni casi può risultare utile applicare il controllo solo a particolari richieste HTTP. Per ottenere ciò ricorriamo al contenitore <Limit>
.
<Limit POST PUT> Order Deny,Allow Deny from all Allow from dominiofidato.it </Limit>
L'esempio sopra riportato restringe l'uso dei metodi POST e PUT ai soli host appartenenti a dominiofidato.it lasciando libero l'utilizzo dei rimanenti. Fate attenzione: il nome del metodo è case-sensitive.
In alternativa si potrebbe ricorrere a <LimitExcept>
che restringe il controllo a tutti i metodi eccezion fatta per quelli elencati. In linea di principio è sempre meglio un approccio che blocca tutto tranne quello che si decide esplicitamente di ammettere.
<LimitExcept POST GET> Order Deny,Allow Deny from all Allow from dominiofidato.it </LimitExcept>
In questo caso concediamo agli host che non appartengono a dominiofidato.it solo i metodi POST e GET.
Controllo basato sia su password che su host
Come accennato nel precedente articolo, Apache permette di realizzare contemporaneamente una limitazione d'accesso basata su host ed una basata su password, in tal caso la direttiva Satisfy
determina come le due componenti debbano interagire. Ecco la sintassi:
Satisfy Any|All
Vediamo il significato dei due possibili valori:
- All: valore di default, richiede al client sia di soddisfare l'autenticazione come host sia di fornire una coppia username e password validi.
-
Any: al client viene richiesto di soddisfare l'autenticazione come host o, in alternativa, fornire uno username e password corretti.
Supponendo di voler concedere l'accesso ai computer della rete interna ed anche ai client esterni, solo se in possesso delle credenziali, possiamo adottare una configurazione simile a questa:
<Directory /miosito/dir_controllata> AuthType Basic AuthName "Area Protetta" AuthUserFile /usr/local/apache/passwd/passwords Require valid-user Order Allow,Deny Allow from 192.168.10. Satisfy Any </Directory>
Le prime quattro righe impongono un'autenticazione Basic che si appoggia al file delle password posizionato in /usr/local/apache/passwd/passwords
. Le seconde due permettono l'accesso ai client il cui indirizzo IP comincia per 192.168.10. L'ultima, infine, stabilisce che per accedere sia necessario passare almeno uno dei due controlli.
Una breve notazione: dalla versione di Apache 2.0.51, ricorrendo ai contenitori <Limit>
e <LimitExcept>
, possiamo utilizzare la direttiva Satisfy
limitatamente ad un particolare metodo HTTP.
L'interazione tra contenitori
Appare importante a questo punto focalizzare l'attenzione sui contenitori <Directory>
, <Files>
, <Location>
, più volte utilizzati negli esempi di questo e del precedente articolo. I primi due si riferiscono al filesystem, ovvero le direttive in essi contenute avranno effetto su path reali del filesystem. Nel caso di <Directory>
si applicheranno alla directory indicata ed alle sue sottodirectory. L'esempio che segue influenza tutto l'albero a partire da /web/miosito/content
:
<Directory /web/miosito/content> Order allow,deny Deny from all </Directory>
Analogo effetto si otterrebbe con un .htaccess opportunamente posizionato.
Nel caso di <Files>
le direttive influenzeranno ciascun file corrispondente al nome specificato. Se inseriamo nella sezione principale del file di configurazione:
<Files nonsitocca.html> Order allow,deny Deny from all </Files>
impediremo l'accesso ai file "nonsitocca.html" dovunque si trovino. Possiamo combinare i contenitori per limitare gli effetti ai file memorizzati in una porzione del filesystem:
<Directory /web/miosito/content> <Files nonsitocca.html> Order allow,deny Deny from all </Files> </Directory>
<Location>
si riferisce, invece, allo spazio Web e quindi:
<Location /privata> Order Allow,Deny Deny from all </Location>
influenzerà le richieste per http://www.miosito.it/privata, http://www.miosito.it/privata123, http://www.miosito.it/privata/files/file.html e tutte le altre che iniziano per "/privata".
Una volta chiarito il ruolo dei contenitori è fondamentale comprendere l'ordine con cui vengono applicate le direttive per evitare sorprese sgradite sulla configurazione finale. L'ordine tra le diverse sezioni, nel caso di utilizzo contemporaneo (il cosiddetto merge), è <Directory>
, <Files>
e <Location>
.
Cosa succede invece nel confronto tra contenitori del medesimo tipo? Le <Directory>
vengono processate in ordine crescente se si riferiscono alla stessa porzione di filesystem: <Directory /web/miosito/content>
avrà la precedenza su <Directory /web/miosito/content/sottodir>
, diversamente seguono l'ordine con cui compaiono nel file di configurazione.
Gli altri due contenitori vengono processati secondo l'ordine con cui compaiono nel file di configurazione. Dopo tante spiegazioni vediamo un inatteso effetto pratico:
<Location /> Order deny,allow Allow from all </Location> <Directory /path/to/documentroot> Order allow,deny Allow from all Deny from host.cattivo.it </Directory>
Malgrado <Location>
preceda il contenitore <Directory>
non viene valutato per primo data la priorità stabilita da Apache. <Directory>
nega l'accesso a host.cattivo.it ma subito dopo <Location>
sovrascrive la regola permettendo l'accesso a tutti. Il risultato sarà l'annullamento della protezione.
Conclusioni
Abbiamo visto in queste pagine come il controllo degli accessi possa essere implementato mediante schemi non banali data la potenza e versatilità che contraddistingue Apache. Vi invito, a costo di sembrare noioso, a scorrere il file httpd.conf dove troverete documentate sia le configurazioni più semplici che quelle meno immediate...dopodiché non vi resta che sbizzarrirvi nelle prove.