Metti che sbagli a configurare il tuo apache e crei un «open proxy»

Lo so, la documentazione va letta bene e più volte, ma capita di avere fretta oppure che la documentazione sia vaga. Così mi è successo di configurare male un server apache che, dopo due anni, è stato usato come «open proxy», cioè come proxy senza nessun controllo. Questo vuol dire che chiunque, impostando come proxy l’ip del mio server, poteva accedere ad internet senza rivelare il proprio indirizzo ip.

L’errore che avevo commesso era il seguente: avevo abilitato il modulo proxy perché apache inoltrasse alcune richieste ad altri siti, nascondendoli ai client. In questo modo su un solo IP davo accesso a varie applicazioni gestite su diverse macchine virtuali. Apache riceveva la richiesta http://www.miodominio.tld/sitoA e la inoltrava all’apache sulla macchina virtuale A, se riceveva la richiesta http://www.miodominio.tld/sitoB la inoltrava all’apache sulla macchina virtuale B, eccetera.

La mia configurazione, una volta attivato il modulo proxy, era la seguente:

<IfModule mod_proxy.c>
   ProxyRequests On
   <Location "/sitoA">
      ProxyPass http://192.168.74.40/
   </Location>
   <Location "/sitoB">
      ProxyPass http://192.168.74.41:8080/
   </Location>
</IfModule>

L’errore sta nel fatto che ProxyRequests non serve ad attivare questo tipo di richieste (apache configurato come reverse proxy), ma quelle del normale proxy (configurato come forward proxy).

Evidentemente ci sono persone che scoprono quando un server web è configurato male e ne approfittano, sicché ieri pomeriggio mi è arrivato l’allarme automatico che indicava sia l’eccessivo utilizzo della banda, sia il carico anomalo in apache. Dopo aver capito cosa era successo, ed essermi documentato meglio, ho impostato il parametro ProxyRequests a Off e la cosa sarebbe stata risolta, ma…

… ma controllando i log di apache continuavo a vedere decine di richieste riferite a siti non miei, alle quali apache rispondeva 200 (HTTP OK). Come ad esempio queste due:

222.186.15.212 - - [02/Mar/2016:06:38:12 +0100] "GET http://909888.com/ HTTP/1.1" 200 272 "http://909888.com/" "Mozilla/5.0+(compatible;+Baiduspider/2.0;++http://www.baidu.com/search/spider.html)"
104.223.72.222 - - [02/Mar/2016:06:38:09 +0100] "GET http://www.heshijiuxian.net/ HTTP/1.1" 200 272 "http://www.baidu.com" "Mozilla/5.0 (compatible; Googlebot/2.1; http://www.google.com/bot.html)"

Proseguendo nella mia indagine sul server apache ho capito il problema. Il mio server gestisce sullo stesso IP siti diversi, quindi è accessibile sia come http://www.miodominio.tld/ che come http://www.altromiodominio.tld/. Per far questo ho dovuto abilitare il NameVirtualHost di apache che in pratica dice ad apache: ascolta su un IP, e quando ti arriva una richiesta, estrai l’intestazione chiamata «host» e in base a quella usa la configurazione del sito corrispondente (cercandola tra i vari VirtualHost configurati).

Non è che sia scritto proprio in caratteri cubitali, ma la documentazione dice anche, tra le righe, che se l’host non viene trovato né tra i ServerName dei vari VirtualHost e nessure tra i ServerAlias, allora viene usato il VirtualHost collegato all’hostname della macchina. Quindi tutte le richieste che si riferiscono a host non gestiti (come quelle che trovavo nei log) restituivano in realtà la pagina del sito principale di questa macchina.

Per risolvere il problema, ho creato un nuovo VirtualHost con un ServerAlias tale da farlo utilizzare per tutti questi siti. In quel VirtualHost viene restituito errore di autorizzazione, come ad esempio:

5.79.83.31 - - [02/Mar/2016:11:10:48 +0100] "GET http://pornobiz.org:81/test_url1/image.php HTTP/1.0" 403 486 "-" "Opera/9.50 (Windows NT 5.1; U; en)"
5.79.83.31 - - [02/Mar/2016:11:10:48 +0100] "CONNECT 74.125.133.138:443 HTTP/1.1" 400 0 "-" "-"

Il VirtualHost è fatto così:

<VirtualHost indirizzo-ipv4:80 [indirizzo-ipv6]:80>
  ServerName www.example.com
  ServerAlias *
  DocumentRoot /var/www/
  <Directory />
    Options FollowSymLinks
    AllowOverride None
  </Directory>
  <Directory /var/www/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    deny from all
  </Directory>
  ErrorLog /var/log/apache2/error-www.example.com.log
  LogLevel notice
  CustomLog /var/log/apache2/access-www.example.com.log combined
  ServerSignature On
</VirtualHost>

Notare che ServerAlias non contiene un hostname, ma un pattern che corrisponde a tutti gli hostname possibili, così da utilizzare questo VirtualHost per qualsiasi URL.
Ovviamente, per non fare ricadere in questo caso anche gli hostname che vengono invece gestiti dagli altri VirtualHost configurati in precedenza, è stato necessario chiamare il file di questo con un nome che fosse alfabeticamente ultimo, cioè zzz.conf. In questo modo, quando apache cerca il VirtualHost da usare, esamina tutti i file in /etc/apache2/sites-enabled nell’ordine alfabetico, e prende quest’ultimo solo se l’host della richiesta non corrisponde ad uno di quelli gestiti dagli altri VirtualHost.