Archivi tag: apache

WI-FI IP camera (made in China): mettere al sicuro l’accesso da remoto

Problema

Negli ultimi anni si è assistito ad un vero e proprio boom riguardante l’acquisto di dispositivi di videosorveglianza basati sul protocollo IP,  ergo facilmente integrabili con le piccole reti domestiche preesistenti. Fin qui nulla di male, se non fosse che, spesso e volentieri, tali “aggeggi” montino dei firmware poco affidabili dal punto di vista della cybersecurity. Mi spiego meglio: cosa accadrebbe se consentissi l’accesso da remoto alla pagina Web di amministrazione della mia telecamera IP? Chi mi garantisce che:

1) Il codice server-side della suddetta pagina non sia vulnerabile;

2) Che non siano presenti una o più backdoor all’interno del codice sorgente del firmware.

dbpowerSoluzione

Se disponete di un server Linux a risparmio energetico (come nel mio caso) è possibile mettere al sicuro l’accesso da remoto alla nostra telecamera IP mediante l’uso di un reverse proxy. In particolare, la configurazione che sto per illustrarvi riguarda uno dei server Web più utilizzati in ambito open source, ovvero Apache.

Supponendo che la mia telecamera IP sia in ascolto sulla porta TCP 81 (HTTP-Alt) e che risponda all’indirizzo 192.168.1.5 , ecco la configurazione da me adoperata:

<VirtualHost *:81>
    ProxyPass / http://192.168.1.5:81/
    ProxyPassReverse / http://192.168.1.5:81/

    <Proxy *>
        Order deny,allow
        Allow from all
        AuthName "IPCamera Access"
        AuthType Basic
        AuthUserFile /etc/ipcam/passwd
        Require valid-user
    </Proxy>

</VirtualHost>

Nella fattispecie, oltre a loggare tutte le richieste di accesso provenienti dall’esterno (in modo da tenerne traccia), ho aggiunto un ulteriore meccanismo di autentica a quello già previsto dalla pagina Web di gestione. In questo modo sono riuscito a garantirmi 2 risultati:

1) Protezione contro attacchi di tipo Web-based;

2) Protezione contro eventuali backdoor presenti nel firmware.

Inoltre, dopo aver definito il suddetto VirtualHost, è stato necessario abilitare il modulo che fa funzionare Apache come reverse proxy, ovvero mod_proxy, decommentando o inserendo la seguente direttiva:

LoadModule proxy_module modules/mod_proxy.so

Per ciò che concerne le credenziali di accesso, invece, è stato possibile definirle utilizzando il comando htpasswd nel seguente formato:

[root@linuxbox ~]# htpasswd -c /etc/ipcam/passwd nomeutente

Infine ho ricaricato la configurazione di Apache per rendere effettive le suddette modifiche:

[root@linuxbox ~]# service httpd reload

Ora la vostra telecamera IP può essere considerata “relativamente” al sicuro.

Alla prossima.

CentOS 6: monitorare le performance di Nagios mediante MRTG

Il compito di un NMS, si sa, è quello di monitorare le prestazioni e lo stato di salute di server, router, switch, firewall e chi più ne ha più ne metta. Nel caso in cui gli oggetti da tenere sotto osservazione siano relativamente pochi (qualche centinatio) ed il server su cui è ospitato Nagios sia abbastanza corazzato (almeno 4/8 GB di RAM), il nostro NMS dovrebbe riuscire a svolgere il suo compito senza grosse difficoltà. Tutto si complica, ovviamente, se il numero degli oggetti da monitorare risulta piuttosto elevato (parliamo qualche migliaio). In tal caso è conveniente tenere sotto controllo le performance del nostro sistema di monitoring (e non solo quelle del server su cui è in esecuzione), poichè potrebbero essere presenti alcuni colli di bottiglia che ne inficiano il corretto funzionamento.

Esistono numerosi plugin sviluppati appositamente per Nagios ed in grado di restituirci dei feedback relativi allo stato di salute dell’NMS in questione, ma, per ovvie ragioni, ho deciso di demandare tale compito ad un tool esterno (leggasi Nagios indipendente): MRTG.

mrtg_logo

In questo post abbiamo visto come installarlo e come creare una configurazione valida per la misurazione della banda associata alle interfacce del nostro router. Adesso vedremo come integrarlo a Nagios in modo da ottenere (e graficizzare) le sue performance.

Di seguito riporto il contenuto del file nagios.cfg (presente all’interno della directory /etc/mrtg/), usato da MRTG per svolgere il proprio compito di monitoraggio:

WorkDir: /var/www/mrtg/nagios

# Service Latency and Execution Time
Target[nagios-a]: `/usr/bin/nagiostats --mrtg --data=AVGACTSVCLAT,AVGACTSVCEXT,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-a]: 100000
Title[nagios-a]: Average Service Check Latency and Execution Time
PageTop[nagios-a]: <H1>Average Service Check Latency and Execution Time</H1>
Options[nagios-a]: growright,gauge,nopercent
YLegend[nagios-a]: Milliseconds
ShortLegend[nagios-a]: &nbsp;
LegendI[nagios-a]: &nbsp;Latency:
LegendO[nagios-a]: &nbsp;Execution Time:
Legend1[nagios-a]: Latency
Legend2[nagios-a]: Execution Time
Legend3[nagios-a]: Maximal 5 Minute Latency
Legend4[nagios-a]: Maximal 5 Minute Execution Time

# Service Percent State Change
Target[nagios-b]: `/usr/bin/nagiostats --mrtg --data=AVGACTSVCPSC,AVGPSVSVCPSC,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-b]: 100
Title[nagios-b]: Average Service State Change
PageTop[nagios-b]: <H1>Average Service State Change</H1>
Options[nagios-b]: growright,gauge,nopercent
YLegend[nagios-b]: Percent
ShortLegend[nagios-b]: &nbsp;
LegendI[nagios-b]: &nbsp;Active Check % Change:
LegendO[nagios-b]: &nbsp;Passive Check % Change:
Legend1[nagios-b]: State Change
Legend2[nagios-b]: State Change
Legend3[nagios-b]: Maximal 5 Minute State Change
Legend4[nagios-b]: Maximal 5 Minute State Change

# Host Latency and Execution Time
Target[nagios-c]: `/usr/bin/nagiostats --mrtg --data=AVGACTHSTLAT,AVGACTHSTEXT,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-c]: 100000
Title[nagios-c]: Average Host Check Latency and Execution Time
PageTop[nagios-c]: <H1>Average Host Check Latency and Execution Time</H1>
Options[nagios-c]: growright,gauge,nopercent
YLegend[nagios-c]: Milliseconds
ShortLegend[nagios-c]: &nbsp;
LegendI[nagios-c]: &nbsp;Latency:
LegendO[nagios-c]: &nbsp;Execution Time:
Legend1[nagios-c]: Latency
Legend2[nagios-c]: Execution Time
Legend3[nagios-c]: Maximal 5 Minute Latency
Legend4[nagios-c]: Maximal 5 Minute Execution Time

# Host Percent State Change
Target[nagios-d]: `/usr/bin/nagiostats --mrtg --data=AVGACTHSTPSC,AVGPSVHSTPSC,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-d]: 100
Title[nagios-d]: Average Host State Change
PageTop[nagios-d]: <H1>Average Host State Change</H1>
Options[nagios-d]: growright,gauge,nopercent
YLegend[nagios-d]: Percent
ShortLegend[nagios-d]: &nbsp;
LegendI[nagios-d]: &nbsp;Active Check % Change:
LegendO[nagios-d]: &nbsp;Passive Check % Change:
Legend1[nagios-d]: State Change
Legend2[nagios-d]: State Change
Legend3[nagios-d]: Maximal 5 Minute State Change
Legend4[nagios-d]: Maximal 5 Minute State Change

# Hosts/Services Actively Checked
Target[nagios-e]: `/usr/bin/nagiostats --mrtg --data=NUMHSTACTCHK5M,NUMSVCACTCHK5M,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-e]: 7000
Title[nagios-e]: Hosts/Services Actively Checked
PageTop[nagios-e]: <H1>Hosts/Services Actively Checked</H1>
Options[nagios-e]: growright,gauge,nopercent
YLegend[nagios-e]: Total
ShortLegend[nagios-e]: &nbsp;
LegendI[nagios-e]: &nbsp;Hosts:
LegendO[nagios-e]: &nbsp;Services:

# Hosts/Services Passively Checked
Target[nagios-f]: `/usr/bin/nagiostats --mrtg --data=NUMHSTPSVCHK5M,NUMSVCPSVCHK5M,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-f]: 7000
Title[nagios-f]: Hosts/Services Passively Checked
PageTop[nagios-f]: <H1>Hosts/Services Passively Checked</H1>
Options[nagios-f]: growright,gauge,nopercent
YLegend[nagios-f]: Total
ShortLegend[nagios-f]: &nbsp;
LegendI[nagios-f]: &nbsp;Hosts:
LegendO[nagios-f]: &nbsp;Services:

# Used/Avail External Command Buffers
Target[nagios-g]: `/usr/bin/nagiostats --mrtg --data=TOTCMDBUF,USEDCMDBUF,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-g]: 7000
Title[nagios-g]: External Command Buffers
PageTop[nagios-g]: <H1>External Command Buffers</H1>
Options[nagios-g]: growright,gauge,nopercent
YLegend[nagios-g]: Buffers
ShortLegend[nagios-g]: &nbsp;
LegendI[nagios-g]: &nbsp;Total:
LegendO[nagios-g]: &nbsp;Used:

# Active Host Checks
Target[nagios-i]: `/usr/bin/nagiostats --mrtg --data=NUMSACTHSTCHECKS5M,NUMOACTHSTCHECKS5M,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-i]: 7000
Title[nagios-i]: Active Host Checks
PageTop[nagios-i]: <H1>Active Host Checks</H1>
Options[nagios-i]: growright,gauge,nopercent
YLegend[nagios-i]: Checks
ShortLegend[nagios-i]: &nbsp;
LegendI[nagios-i]: &nbsp;Scheduled Checks:
LegendO[nagios-i]: &nbsp;On-Demand Checks:

# Active Service Checks
Target[nagios-j]: `/usr/bin/nagiostats --mrtg --data=NUMSACTSVCCHECKS5M,NUMOACTSVCCHECKS5M,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-j]: 7000
Title[nagios-j]: Active Service Checks
PageTop[nagios-j]: <H1>Active Service Checks</H1>
Options[nagios-j]: growright,gauge,nopercent
YLegend[nagios-j]: Checks
ShortLegend[nagios-j]: &nbsp;
LegendI[nagios-j]: &nbsp;Scheduled Checks:
LegendO[nagios-j]: &nbsp;On-Demand Checks:

# Passive Host/Service Checks
Target[nagios-k]: `/usr/bin/nagiostats --mrtg --data=NUMPSVHSTCHECKS5M,NUMPSVSVCCHECKS5M,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-k]: 7000
Title[nagios-k]: Passive Host/Service Checks
PageTop[nagios-k]: <H1>Passive Host/Service Checks</H1>
Options[nagios-k]: growright,gauge,nopercent
YLegend[nagios-k]: Checks
ShortLegend[nagios-k]: &nbsp;
LegendI[nagios-k]: &nbsp;Host Checks:
LegendO[nagios-k]: &nbsp;Service Checks:

# Cached Host/Service Checks
Target[nagios-l]: `/usr/bin/nagiostats --mrtg --data=NUMCACHEDHSTCHECKS5M,NUMCACHEDSVCCHECKS5M,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-l]: 7000
Title[nagios-l]: Cached Host/Service Checks
PageTop[nagios-l]: <H1>Cached Host/Service Checks</H1>
Options[nagios-l]: growright,gauge,nopercent
YLegend[nagios-l]: Checks
ShortLegend[nagios-l]: &nbsp;
LegendI[nagios-l]: &nbsp;Host Checks:
LegendO[nagios-l]: &nbsp;Service Checks:

# External Commands
Target[nagios-m]: `/usr/bin/nagiostats --mrtg --data=NUMEXTCMDS5M,0,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-m]: 7000
Title[nagios-m]: External Commands
PageTop[nagios-m]: <H1>External Commands</H1>
Options[nagios-m]: growright,gauge,nopercent
YLegend[nagios-m]: Commands
ShortLegend[nagios-m]: &nbsp;
LegendI[nagios-m]: &nbsp;Commands:
LegendO[nagios-m]: &nbsp;

# Parallel/Service Host Checks
Target[nagios-n]: `/usr/bin/nagiostats --mrtg --data=NUMPARHSTCHECKS5M,NUMSERHSTCHECKS5M,PROGRUNTIME,NAGIOSVERPID`
MaxBytes[nagios-n]: 7000
Title[nagios-n]: Parallel/Serial Host Checks
PageTop[nagios-n]: <H1>Parallel/Serial Host Checks</H1>
Options[nagios-n]: growright,gauge,nopercent
YLegend[nagios-n]: Checks
ShortLegend[nagios-n]: &nbsp;
LegendI[nagios-n]: &nbsp;Parallel Checks:
LegendO[nagios-n]: &nbsp;Serial Checks:

Il giro del fumo può banalmente essere riassunto in questo modo: viene lanciato l’applicativo nagiostats, al quale vengono affiancate alcune flag come –mrtg e –data (quest’ultima serve a specificare i parametri da monitorare, ad esempio NUMPSVHSTCHECKS5M,NUMPSVSVCCHECKS5M,PROGRUNTIME,NAGIOSVERPID).

Occorre precisare, inoltre,  che nagiostats viene eseguito direttamente dal crontab che richiama MRTG, ragion per cui è indispensabile configurare SElinux in modo da consentire tale operazione.

Creiamo la directory che ospiterà la pagina Web contenente le i grafici associati alle prestazioni di Nagios:

[root@linuxbox ~]# mkdir -p /var/www/mrtg/nagios

e successivamente passiamo alla creazione della pagina index.html:

[root@linuxbox ~]# indexmaker --output=/var/www/mrtg/nagios/index.html /etc/mrtg/nagios.cfg

Infine, modifichiamo il contenuto del file /etc/cron.d/mrtg, aggiungendo la stringa:

*/5 * * * * root LANG=C LC_ALL=C /usr/bin/mrtg /etc/mrtg/nagios.cfg --lock-file /var/lock/mrtg/nagios_l --confcache-file /var/lib/mrtg/nagios.ok

Come ultimo step creiamo la configurazione di Apache per l’accesso alla pagina Web in cui sono presenti i grafici generati da MRTG:

[root@linuxbox ~]# nano /etc/httpd/conf.d/mrtg.conf

Il cui contenuto dovrà essere simile al seguente:

Alias /mrtg /var/www/mrtg

<Location /mrtg>
    Order deny,allow
    Allow from all
    AuthName "MRTG Access"
    AuthType Basic
    AuthUserFile /etc/mrtg/passwd
    Require valid-user
</Location>

Infine, creiamo il file contenente user e pass per l’accesso alla suddetta pagina Web:

[root@linuxbox ~]# htpasswd -c /etc/mrtg/passwd <vostrouser>

Ricarichiamo la configurazione di Apache:

[root@linuxbox ~]# service apache reload

ed abbiamo finito:

mrtg-nagios

Alla prossima.

CentOS 6: realizzare un network intrusion detection system open source – Parte 3

Dopo aver installato e configurato snort, barnyard2, pulledpork e MySQL (vedi qui e qui), ora vedremo come installare l’interfaccia Web del nostro sistema NIDS, ovvero Snorby.

Poichè tale interfaccia si basa su Ruby, è necessario predisporre il nostro sistema per il supporto del linguaggio di scripting in questione.

snorby-dashboard

Preparazione della macchina

Per prima cosa installiamo i software prerequisiti, mediante i comandi:

yum -y groupinstall "Development Tools"

yum install -y openssl-devel readline-devel libxml2-devel libxslt-devel mysql mysql-devel mysql-libs mysql-server urw-fonts libX11-devel libXext-devel qconf fontconfig-devel libXrender-devel unzip

yum -y install xz urw-fonts libXext openssl-devel libXrender

Successivamente, scarichiamo ed installiamo ImageMagick , per la creazione di immagini bitmap, e wkhtmltopdf, per la conversione delle pagine HTML in PDF (funzionalità indispensabile durante la generazione dei report):

cd /usr/local/src

wget ftp://ftp.fifi.org/pub/ImageMagick/ImageMagick-6.8.9-6.tar.gz

tar -xvf ImageMagick-6.8.9-6.tar.gz

cd ImageMagick-6.8.9-6

./configure

make

make install

ldconfig 

cd ..

wget http://sourceforge.net/projects/wkhtmltopdf/files/0.12.1/wkhtmltox-0.12.1_linux-centos6-amd64.rpm/download

rpm -Uvh wkhtmltox-0.12.1_linux-centos6-amd64.rpm

Adesso scarichiamo rvm, attraverso il quale sarà possibile installare la versione di Ruby compatibile con Snorby (ovvero la 1.9.3, che, purtroppo, è ormai obsoleta e non più mantenuta):

curl -L get.rvm.io | bash -s stable

Installiamo dunque Ruby e facciamo in modo che il sistema utilizzi la versione 1.9.3 come default:

rvm install 1.9.3

rvm use --default 1.9.3

Ora, utilizzando il packet manager di Ruby (ovvero gem), procediamo con l’installazione di Rails (il framework) e di passenger (necessario per integrare Snorby e Apache):

gem install rails

gem install passenger

passenger-install-apache2-module

Installiamo alcuni pacchetti prerequisiti:

gem install devise_cas_authenticatable -v '1.1.0'

e

gem install bundler

In particolare, quest’ultimo si occupa di gestire le dipendenze tra i gem (ed è il software responsabile della creazione dei file Gemfile e Gemfile.lock).

Installazione e configurazione di Snorby

Creiamo la directory nella quale ospitare Snorby:

mkdir -p /var/www/html/snorby

e scarichiamo l’applicazione vera e propria:

cd /var/www/html/snorby

wget -O snorby.zip --no-check-certificate https://github.com/Snorby/snorby/archive/master.zip

Scompattiamo l’archivio, posizioniamoci nella directory snorby-master e spostiamone il contenuto all’interno di /var/www/html/snorby:

unzip snorby.zip

cd snorby-master/

mv * ../

Modifichiamo ora il contenuto del file Gemfile, sostituendo le direttive di default per rake, json e devise_cas_authenticatable con le seguenti:

gem 'rake', '0.9.2.2'
gem 'json', '~> 1.8.3'
gem 'thin'

gem 'devise_cas_authenticatable',  '~> 1.1.0'

Inoltre, è necessario inserire la direttiva gem ‘thin’ subito dopo gem ‘json’, commentando quella dopo gem “letter_open”:

gem 'json', '~> 1.8.3'
gem 'thin'

group(:development) do
     gem "letter_opener"
   # gem 'thin'

Discorso simile vale per il file Gemfile.lock, in cui bisogna modificare le direttive rake e json nel seguente modo:

rake (0.9.2.2)

json (1.8.3)

Lanciamo il comando bundle install in modo da installare i pacchetti gem (con le relative dipendenze) definiti all’interno del Gemfile precedentemente editato:

bundle install

Eliminiamo la dir snorby-master (ormai vuota) e passiamo alla configurazione di Snorby:

rm -rf snorby-master/

cd config

cp snorby_config.yml.example snorby_config.yml

nano snorby_config.yml

definendo la giusta timezone:

time_zone: Europe/Rome

A questo punto possiamo configurare la connessione al database, editando il file config/database.yml:

cd ..

cp config/database.yml.example config/database.yml

nano config/database.yml

il cui contenuto sarà simile al seguente:

# Snorby Database Configuration
#
# Please set your database password/user below
# NOTE: Indentation is important.
#
snorby: &snorby
  adapter: mysql
  username: vostrouser
  password: "vostrapassword" # Example: password: "s3cr3tsauce"
  host: localhost

development:
  database: snorby
  <<: *snorby

test:
  database: snorby
  <<: *snorby

production:
  database: snorby

Avviamo l’applicazione (con finalità di test), mediante i comandi:

rake snorby:setup

rails server thin -e production

da lanciare all’interno della dir /var/www/html/snorby ed il cui output dovrebbe essere simile al seguente:

=> Booting Thin
=> Rails 3.1.12 application starting in production on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on 0.0.0.0:3000, CTRL+C to stop

http://ip:3000/users/login

Provando ora a connetterci (con il nostro browser) a http://ip:3000/users/login dovremmo riuscire a visualizzare l’interfaccia di Snorby (con il relativo form per il login, dove l’email di default è snorby@example.com e la password è semplicemente snorby).

Integrazione tra Snorby e Apache

Come già affermato in precedenza, il modulo di Apache che consente al nostro server Web di interfacciarsi con le applicazioni scritte in Ruby prende il nome di passenger.

Per prima cosa occorre dunque configurare il suddetto modulo:

nano /etc/httpd/conf.d/mod_passenger.conf

il cui contenuto dovrà essere:

LoadModule passenger_module /usr/local/rvm/gems/ruby-1.9.3-p551/gems/passenger-5.0.16/buildout/apache2/mod_passenger.so

PassengerRoot /usr/local/rvm/gems/ruby-1.9.3-p551/gems/passenger-5.0.16
PassengerDefaultRuby /usr/local/rvm/gems/ruby-1.9.3-p551/wrappers/ruby

Infine, modifichiamo il file di configurazione di Apache (/etc/httpd/conf/httpd.conf), creando un virtual host opportuno (in ascolto sulla porta TCP 82):

Listen 82

<VirtualHost *:82>
     Servername vostroserver.vostrodominio.com
     DocumentRoot /var/www/html/snorby/public
     <Directory /var/www/html/snorby/public>
        Order deny,allow
        Allow from all
        Options -MultiViews
        AuthName "Snorby Access"
        AuthType Basic
        AuthUserFile /etc/snorby/passwd
        Require valid-user
    </Directory>
</VirtualHost>

Tale virtual host richiede l’autentica HTTP, ergo occorre creare il file in cui verranno salvate le coppie username/password da utilizzare:

mkdir -p /etc/snorby

htpasswd -c /etc/snorby/passwd vostroutente

Infine, riavviamo Apache:

service httpd reload

ed abbiamo finito.

Alla prossima.

Apache e mod_rewrite: redirect automatico per i dispositivi di tipo mobile

Scenario

Un sito Web, chiamiamolo per semplicità www.domain.com, che prevede due versioni: una per i desktop computer (e simili) e l’altra per i dispositivi mobile (smartphone, tablet, ecc.).

In particolare, i dispositivi mobile devono essere reindirizzati automaticamente su una landing page (choose.domain.com) e da questa pagina consentire all’utente di scegliere quale versione del sito visualizzare.

Soluzione

La soluzione da me implementata prevede l’identificazione dei client mobile (basata fondamentalmente sullo User Agent), il redirect degli stessi verso la landing page (mediante mod_rewrite) ed il settaggio di un cookie per “ricordare” la versione del sito che l’utente ha scelto di visualizzare (ovviamente fino a quando il cookie non scadrà o verrà rimosso volutamente dall’utente stesso).

mod_rewrite_logoMa bando alle ciance ed ecco la configurazione:

#Redirect per Iphone, Ipad, Android
 RewriteCond %{HTTP_USER_AGENT} "iPhone|iPad|Android" [NC]
 RewriteCond %{QUERY_STRING} !^full=true$ [NC]
 RewriteCond %{HTTP_COOKIE} !^.*full.*$ [NC]
 RewriteRule ^(.*)$ http://choose.domain.com [R=301,L]
RewriteCond %{QUERY_STRING} ^full=true$ [NC]
 RewriteCond %{HTTP_COOKIE} !^.*full.*$ [NC]
 RewriteRule .* - [co=full:true:.domain.com:7200:/]

Analizziamola direttiva per direttiva. Con:

RewriteCond %{HTTP_USER_AGENT} "iPhone|iPad|Android" [NC]

verifico che lo User Agent del visitatore contenga una delle keyword elencate (ed intervallate da semplici OR logici), ovvero iPhone, iPad ed Android.

Successivamente mi accerto che il link contattato dall’utente non contenga la querystring ?full=true

RewriteCond %{QUERY_STRING} !^full=true$ [NC]

il punto esclamativo (!) all’inizio della rewrite condition indica la negazione. Verifico inoltre che sul browser dell’utente non vi siano cookie contenenti la stringa full:

RewriteCond %{HTTP_COOKIE} !^.*full.*$ [NC]

Infine, se tutte e 3 le condizioni fin’ora elencate sono vere (le rewrite conditions elencate una dopo l’altra prevedono l’AND implicito), eseguo un redirect permanente (HTTP 301) sulla landing page:

RewriteRule ^(.*)$ http://choose.domain.com [R=301,L]

Nel caso in cui, invece, il link contattato dall’utente contenga la querystring ?full=true:

RewriteCond %{QUERY_STRING} ^full=true$ [NC]

ed il browser da egli utilizzato non presenti cookie che rechino la keyword full:

RewriteCond %{HTTP_COOKIE} !^.*full.*$ [NC]

salvo nel suddetto browser un cookie che ricordi la sua scelta, ovvero quella di visualizzare il sito in versione desktop (full), fino a quando il cookie stesso non sarà scaduto (dopo 7200 minuti, ovvero 5 giorni):

RewriteRule .* - [CO=full:true:.domain.com:7200:/]

dove la flag di mod_rewrite utilizzata è banalmente CO, la cui sentassi è la seguente:

[CO=NAME:VALUE:DOMAIN:lifetime:path:secure:httponly]

che ho utilizzato nella forma ridotta:

[CO=NAME:VALUE:DOMAIN:lifetime:path]

Infine, la flag [NC] utilizzata al termine di ciascuna rewrite condition, consente di non fare distinzione tra caratteri maiuscoli e minuscoli (NC, infatti, sta per NO CASE).

Per ora è tutto, alla prossima.

Tenere sotto controllo le performance di Apache con mod_status e Nagios

Apache è uno dei server Web più utilizzati al mondo poichè molto robusto, piuttosto performante e soprattutto perchè open source.

Ovviamente, affichè le prestazioni dell’applicativo in questione possano migliorare sensibilmente, è necessario operare sul suo file di configurazione, effettuando un tuning dello stesso. A tal proposito, è alquanto utile, durante questa attività, tenere Apache sotto controllo utilizzando uno dei suoi moduli appositamente creato per svolgere la suddetta mansione, ovvero mod_status.

 

apache_status.jpeg

Vediamo ora come abilitarlo e configurarlo in modo opportuno.

Configurazione di Apache

Per prima cosa editiamo il file /etc/httpd/conf/httpd.conf, operando su di esso le seguenti modifiche:

1) decommentiamo la direttiva:

LoadModule status_module modules/mod_status.so

2) abilitiamo le statistiche estese, decommentando la seguente entry:

ExtendedStatus On

Nell’ambito della configurazione del vhost (o dei vhosts) su cui vogliamo fare in modo che siano consultabili le statistiche relative al funzionamento del nostro server Web, inseriamo quanto segue:

<Location /server-status>
 SetHandler server-status
 Order deny,allow
 Deny from all
 Allow from <IP 1>
 Allow from <IP 2>
 Allow from <IP 3>
 Allow from <IP 4>
 Allow from <IP 5>
 </Location>

dove i vari IP sono quelli consentiti per la visualizzazione della pagina Web contenente lo stato di funzionamento di Apache.

Se non utilizzate vhosts, potete semplicemente decommentare le suddette entries (già presenti nel file di configurazione di Apache).

Riavviamo dunque il demone per rendere effettive le modifiche:

[root@serverWeb ~]# service httpd reload

Configurazione di Nagios

Una volta configurato Apache, è possibile utilizzare Nagios per automatizzare i controlli sul server Web. Ovviamente, l’indirizzo IP del nostro NMS deve essere tra quelli consentiti in <Location /server-status>.

Il plugin che ho scelto per effettuare i check in questione è check_apachestatus.pl, scaricabile da qui.

Rinominiamo lo scrip appena scaricato e rendiamolo eseguibile:

[root@NMS ~]# mv check_apachestatus.pl.txt ckeck_apachestatus.pl

[root@NMS ~]# chmod +x check_apachestatus.pl

Spostiamolo nella dir dei plugin di Nagios:

[root@NMS ~]# mv check_apachestatus.pl  /usr/lib/nagios/plugins/

Prima di eseguirlo, però, è necessario scaricare le librerie perl relative a Nagios, mediante il comando:

[root@NMS ~]# yum install perl-Nagios-Plugin

Ora possiamo procedere con la configurazione di Nagios vera e propria.

Per prima cosa, all’interno del file /etc/nagios/objects/commands.cfg definiamo questo nuovo comando:

# 'check_apache_status' command definition
define command{
command_name    check_apache_status
command_line    $USER1$/check_apachestatus.pl -H $ARG1$ -p $ARG2$ -t $ARG3$ -w $ARG4$ -c $ARG5$
}

dove -H rappresenta l’FQDN o semplicemente l’indirizzo IP del nostro server Web su cui è in esecuzione mod_status (e su cui è consultabile la relativa pagina server-status); -p rappresenta la porta su cui il server Web è in ascolto; -t rappresenta il timeout relativo ad ogni check; -w rappresenta il numero di open slots al di sotto del quale far scattare un warning; -c rappresenta il numero di open slots al di sotto del quale far scattare un avviso di tipo critical.

A titolo di informazione, gli open slots rappresentano semplicemente il numero di processi fork in ascolto (ovvero in attesa di nuove connessioni) relativi ad httpd.

Non ci resta che creare un apposito servizio sul file di configurazione di Nagios che identifica il nostro server Web. Ad esempio, all’interno del file /etc/nagios/objects/serverweb.cfg possiamo scrivere:

define service{
        use                             local-service         ; Name of service template to use
        host_name                       serverweb.vostrodominio.com
        service_description             Apache Status
        check_command                   check_apache_status!serverweb.vostrodominio.com!80!10!5!0
        notifications_enabled           0
        }

Infine, riavviamo Nagios:

[root@NMS ~]# service nagios restart

Ed abbiamo finito.

Alla prossima.


Esportare un certificato SSL da Apache a IIS

Molti hosting provider (tra cui Godaddy) mettono a disposizione tutta una serie di servizi per i loro clienti, tra cui la possibilità di creare N domini, con relativo pannello di controllo per la gestione delle zone DNS, fornire i cosiddetti certificati SSL per HTTPS e così via.

ssl.jpg

Poichè Godaddy non è una CA vera e propria (Certification Authority), i suddetti certificati devono essere “garantiti” da una terza parte (che prende il nome di Intermediate CA, vedi qui per approfondire). Proprio per questa ragione, dopo aver inviato la richiesta per il certificato SSL (mediante il cosiddetto file *.csr, acronimo di Certificate Signature Request), l’hosting provider in questione ci consentirà di scaricare tre file:

1) il certificato SSL vero e proprio (ad esempio miodominio.crt);

2) il certificato SSL della intermediate CA (sf_bundle.crt);

3) la chiave privata RSA (file *.pem).

I suddetti file non possono essere utilizzati “as is” nel caso di IIS, ma devono essere opportunamente esportati in formato pkcs#12 (vedi pkcs per approfondire). Di seguito la procedura relativa all’export:

Per prima cosa concateno il certificato SSL per il mio dominio a quello della intermediate CA:

cat sf_bundle.crt miodominio.com.crt >> miodominio.com.all.crt

Successivamente, mediante openssl, esporto il suddetto certificato in formato pkcs#12 (con estensione *.pfx):

openssl pkcs12 -export -out miodominio.com.pfx -inkey miodominio.com.pem -in miodominio.com.all.crt -name 'miodominio.com'

Infine, installo il suddetto file su IIS, facendo attenzione che il servizio sia in bind sulla porta 443 (HTTPS), ed il gioco è fatto.

Alla prossima.

Centos 6: Apache e le ACL basate sull’IP sorgente

Per fare in modo che il contenuto di alcuni file presenti nella directory a cui punta Apache possa essere visualizzato solo da determinati IP sorgenti è necessario definire delle ACL direttamente nel file .htaccess posizionato nella suddetta dir, oltre ad effettuare una piccola modifica all’interno del file di configurazione di Apache stesso, ovvero /etc/httpd/conf/httpd.conf.

 

apache-logo_new.png

Il contenuto del file .htaccess dovrà essere strutturato nel modo seguente:

Order Deny,Allow
Deny from All
Allow from <IP1>
Allow from <IP2>
Allow from <IP3>
Allow from <IP4>
Allow from <IP5>

mentre all’interno del file di configurazione di Apache occorre aggiungere la seguente direttiva:

<Directory /var/www/securecontent>
         AllowOverride All
</Directory>

dove securecontent è la directory il cui contenuto vuole essere riservato solo ai suddetti IP.

Infine eseguiamo un reload della configurazione di Apache:

[root@webserver ~]# service httpd reload

ed abbiamo finito.

Alla prossima.

Apache virtual host su IP pubblico dedicato

Scenario

Un virtual host di Apache che deve essere accessibile solo da determinati indirizzi IP pubblici.

Problema

Sulla macchina sono presenti anche altri virtual host “pubblici”.

Soluzione

Mettere in bind il virtual host in oggetto su un indirizzo IP pubblico dedicato e successivamente creare delle regole ad hoc mediante Iptables.

 

apache,virtual host,httpd,bind,virtual interface,dedicated public ip,private access,logging,syslogd,iptables,rc.local

Per prima cosa occorre creare un’interfaccia virtuale da associare all’indirizzo IP pubblico dedicato. Su CentOS tale operazione è piuttosto banale e consta dei seguenti passi:

1) Creo il file contenente i parametri dell’interfaccia all’interno della directory /etc/sysconfig/network-scrips/:

[root@server network-scrips]# sudo nano ifcfg-eth0:0

il cui contenuto dovrà essere simile al seguente:

 DEVICE=eth0:0
 ONBOOT=yes
 HWADDR=
 IPADDR=<indirizzo IP pubblico>
 NETMASK=<netmask>
 BROADCAST=<indirizzo di broadcast>
 GATEWAY=<indirizzo del default gw>
 NETWORK=
 TYPE=Ethernet

2) Attivo l’interfaccia virtuale e mi sincero che sia effettivamente operativa:

[root@server network-scrips]# ifup eth0:0

[root@server network-scrips]# ifconfig

il cui output dovrebbe essere simile al seguente:

eth0:0    Link encap:Ethernet  HWaddr <mac address>
           inet addr:<indirizzo IP>  Bcast:<indirizzo di broadcast>  Mask:<netmask>
           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
           Interrupt:169 Memory:fb5e0000-fb600000

Successivamente creo la configurazione del virtual host all’interno della directory /etc/httpd/vhosts.d/:

[root@server vhosts.d]# nano privatevhost.conf

il cui contenuto dovrà essere:

Listen <ip pubblico assegnato all'interfaccia virtuale>:80
NameVirtualHost <ip pubblico assegnato all'interfaccia virtuale>:80

<VirtualHost <ip pubblico assegnato all'interfaccia virtuale:80>
  ServerName privatevhost.dominio.com
  ServerAlias privatevhost.dominio.com

  DocumentRoot /var/www/virtual/privatevhost.dominio.com/htdocs

  ErrorLog /var/www/virtual/privatevhost.dominio.com/logs/error.log
  CustomLog /var/www/virtual/privatevhost.dominio.com/logs/access.log combined
  #ServerSignature Off

  Redirect 404 /favicon.ico

  <Location /favicon.ico>
   ErrorDocument 404 "No favicon"
  </Location>

</VirtualHost>

Lancio un reload della configurazione di Apache per rendere effettive le suddette modifiche:

[root@server vhosts.d]# service httpd reload

A questo punto posso procedere con la creazione dei filtri di accesso mediante iptables:

iptables -F
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT

iptables -A INPUT -s <IP sorgente consentito>/32 -d <IP pubblico assegnato all'interfaccia virtuale>/32 -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -s <IP sorgente consentito>/32 -d <IP pubblico assegnato all'interfaccia virtuale>/32 -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -s <IP sorgente consentito>/32 -d <IP pubblico assegnato all'interfaccia virtuale>/32 -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -s <IP sorgente consentito>/32 -d <IP pubblico assegnato all'interfaccia virtuale>/32 -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -d <IP pubblico assegnato all'interfaccia virtuale>/32 -j LOG  --log-prefix "Private Area Access Attempt:" --log-level 4
iptables -A INPUT -d <IP pubblico assegnato all'interfaccia virtuale>/32 -p ICMP -j ACCEPT
iptables -A INPUT -d <IP pubblico assegnato all'interfaccia virtuale>/32 -j DROP

exit 0

In soldoni, ho prima consentito l’accesso via Web al suddetto virtual host solo a determinati indirizzi IP pubblici. Successivamente ho impostato una regola per il logging dei tentativi di accesso non autorizzati, consentendo solo il traffico ICMP (aka ping) proveniente da qualunque indirizzo sorgente (per questione di praticità durante le eventuali operazioni di diagnostica).

Infine ho droppato tutto il traffico diretto all’interfaccia virtuale che non rispetta nessuna delle regole definite in precedenza.

Copio le suddette regole all’interno del file /etc/rc.local per renderle attive anche dopo eventuali reboot della macchina e facciamo alcuni test per verificare che tutto funzioni correttamente (tentativo di accesso via Browser al virtual host, prima da indirizzo IP consentito e successivamente da indirizzo IP non consentito).

Inoltre, per loggare i tentativi di accesso non autorizzati, occorre modificare la configurazione del file syslog.conf, aggiungendo la seguente entry all’inizio del file in questione:

kern.warning                                    /var/log/iptables.log

Infine, lancio un restart del demone di logging:

[root@server vhosts.d]# service syslog restart

E’ tutto, alla prossima.

Apache, virtual host ed SSL su CentOS

La cosa fantastica di Apache è che ti consente di gestire i cosiddetti virtual host, ovvero N server Web virtuali, ognuno dei quali presenta le proprie caratteristiche peculiari.

Essi risultano particolarmente comodi quando si ha la necessità di imbastire dei frontend che rispondano per alcuni domini su HTTPS e per altri su HTTP.

logo_apache22.jpg

Come al solito, la presente guida si focalizzerà sulla configurazione del server vera e propria (httpd.conf), e successivamente sulla configurazione di ciascun virtual host.

Configurazione del server

La prima modifica da effettuare nel file di configurazione di Apache riguarda l’abilitazione del protocollo HTTPS. In particolare, esso verrà gestito grazie ad uno specifico modulo, ovvero mod_ssl.so, non presente nell’installazione di default relativa ad Apache.

Ergo, sarà necessario dapprima scaricarlo mediante il comando:

[root@serverweb conf]# yum install mod_ssl

Non ho installato anche openssl in quanto sono partito dal presupposto che siate già in possesso dei certificati X.509 (nel formato Apache) relativi al vostro dominio.

A questo punto è necessario abilitare il suddetto modulo aggiungendo la seguente direttiva nel file /etc/conf/httpd.conf:

LoadModule ssl_module modules/mod_ssl.so

Successivamente, si dovrà procedere con la messa in ascolto sul server della porta TCP 443 (HTTPS).

Per fare ciò si può aggiungere la seguente stringa nel file di configurazione di Apache:

Listen 443

Infine, sempre nel file di configurazione in questione, si dovrà specificare in quale directory sono presenti le direttive relative ai virtual host:

# Include the virtual host configurations:
Include /etc/httpd/vhosts.d/*.conf

Configurazione del virtual host

Posizioniamoci nella directory oggetto dell’include e creiamo un nuovo file di configurazione per il virtual host:

[root@serverweb vhosts.d]# nano virtualhost1.conf

Il cui contenuto sarà simile al seguente:

<VirtualHost *:443>
  ServerName www.miodominio.com

  DocumentRoot /var/www/virtualhosts/www.miodominio.com/htdocs

  SSLEngine on
  SSLCertificateFile /etc/ssl/sslcert.crt
  SSLCertificateKeyFile /etc/ssl/sslkey.pem
  SSLCertificateChainFile /etc/ssl/sf_bundle.crt

  <Directory /var/www/virtual/static.betuniq.info/htdocs>
      AllowOverride All
      Order allow,deny
      Allow from all
   </Directory>

  ErrorLog /var/www/virtualhosts/www.miodominio.com/logs/ssl_error.log
  CustomLog /var/www/virtualhosts/www.miodominio.com/logs/ssl_access.log combined
  #ServerSignature Off

  Redirect 404 /favicon.ico

  <Location /favicon.ico>
   ErrorDocument 404 “No favicon”
  </Location>

</VirtualHost>

Come avrete intuito, il virtual host in questione è in ascolto sulla porta TCP 443, quindi è in grado di servire solo ed esclusivamente il traffico HTTPS:

<VirtualHost *:443>

Con ServerName specifico il dominio associato al virtual host in questione mentre con DocumentRoot indico la direcotry in cui sono presenti le pagine Web (e relativi file, come immagini, fogli di stile, ecc.).

Con SSLEngine on abilito il motore SSL e con le direttive:

SSLCertificateFile /etc/ssl/sslcert.crt
SSLCertificateKeyFile /etc/ssl/sslkey.pem
SSLCertificateChainFile /etc/ssl/sf_bundle.crt

indico rispettivamente il pathname relativo al certificato X.509 (sslcert.crt), della chiave privata RSA (sslkey.pem) e del certificato di terze parti (sf_bundle.crt).

Le altre stringe riguardano semplicemente i file di log e le politiche di overwrite sulla directory (ad esempio mediante file .htaccess).

Ora, affinchè il suddetto dominio rimanga in ascolto sia sulla 443 che sulla 80 (HTTP puro), si può creare un ulteriore file di configurazione, contenente però la direttiva:

<VirtualHost *:80>

nessuna entry associata all’SSL ed ai certificati ma la stessa DocumentRoot del vhost precedente.

Per rendere effettive le modifiche senza creare disservizio è sufficiente lanciare il comando:

[root@serverweb conf]# service httpd reload

Se tale comando non restituisce errori è un ottimo segno.

Per avere ulteriore conferma del corretto funzionamento relativo al nostro server Web, si possono fare due check mediante netstat:

[root@serverweb conf]# netstat -anp | grep :80

e

[root@serverweb conf]# netstat -anp | grep :443

Se il server risulta in Listen è molto probabile che stia funzionando correttamente. Fate comunque delle prove con un browser per esserne certi.

E’ tutto. Alla prossima.

Logging con Varnish Cache

In questo post ho spiegato, a grandi linee, cos’è Varnish Cache ed a cosa serve. Il problema che mi ponevo era, sostanzialmente, quello di individuare l’IP sorgente delle richieste HTTP, in modo che il log di Apache (httpd) fosse in grado di tenerne traccia.

http, header http, client ip, logging, x-forwarded-for, varnishlog, backand, varnishncsa, httpd, apache

Infatti, nel caso in cui Varnish sia in esecuzione sulla stessa macchina su cui gira Apache, l’IP sorgente delle richieste HTTP sarà sempre e comunque 127.0.0.1 (aka localhost). In particolare, sarà Varnish ad intercettare le suddette richieste sulla porta 80 e, successivamente, ad inoltrarle al server Web di backend.

Sempre nel post in questione ho mostrato una direttiva del file di configurazione di Varnish (dafault.vcl), in cui viene manipolato il dato HTTP, modificandone l’header (precisamente considerando il campo X-FORWARDED-FOR come IP sorgente della richiesta, in modo da inserirlo nel file di log). Inutile dire che tale soluzione, seppure lecita, è sconveniente per due motivi:

1) manipolare i dati HTTP risulta in qualche modo oneroso in termini computazionali;

2) tale operazione potrebbe non andare a buon fine, in quanto il campo X-FORWARDED-FOR potrebbe essere vuoto.

Cosa fare dunque? Semplice, utilizzare due validi strumenti messi a disposizione da Varnish Cache, ovvero varnishncsa e varnishlog.

Il primo ci consente di salvare in un file di log apposito le richieste HTTP che Varnish ha preso in carico. Il secondo, invece, può essere facilmente customizzato, in modo da tenere traccia solo delle informazioni che ci interessano. Personalmente, ritengo che utilizzare entrambi per loggare il traffico utente sia inutile, ecco perchè uso varnishncsa per il logging delle richieste HTTP e varnishlog per tenere traccia delle comunicazioni con i backend.

Ma vediamo adesso come utilizzare i tool in questione (che su CentOS sono semplicemente dei demoni).

Per prima cosa avviamo varnishncsa utilizzando il comando:

[user@host varnish]# service varnishncsa start

Successivamente, facciamo in modo che il suddetto demone entri in esecuzione automaticamente su diversi runlevel, mediante il comando chkconfig:

[user@host varnish]# chkconfig --level 2345 varnishncsa on

A questo punto non ci rimane che configurare varnishlog. Se lanciamo il comando:

[user@host varnish]# varnishlog help

otteniamo una lista delle flag utilizzabili. Quella che a noi interessa è -b, ovvero si vuole imporre a varnishlog di registrare solo gli eventi relativi alla comuncazione con i backend (utile in caso di troubleshooting). Ecco uno stralcio del man che indica il significato della suddetta flag:

 -b     Include log entries which result from communication with a backend server.  If neither -b nor -c  is  specified, varnishlog acts as if they both were.

Modifichiamo il demone, posizionandoci nella directory /etc/init.d e digitando:

[user@host varnish]# nano varnishlog

Nella direttiva:

DAEMON_OPTS="-a -w $logfile -D -P $pidfile"

inseriamo la flag -b. Essa diventerà:

DAEMON_OPTS="-a -b -w $logfile -D -P $pidfile"

Ora impostiamo l’esecuzione automatica del demone in questione (come già fatto per varnishncsa):

[user@host varnish]# chkconfig --level 2345 varnishlog on

Infine, avviamolo:

[user@host varnish]# service varnishlog start

Adesso Varnish Cache sarà in grado di loggare tutti gli eventi che la coinvolgono.

Alla prossima.