Archivi categoria: Networking

Ubuntu: analisi e debug di un’interfaccia di rete malfunzionante

Di recente, analizzando i log di uno dei server che gestisco, mi sono accorto che una delle sue interfacce di rete continuava a generare tutta una serie di eventi del tipo:

root@linux-box:~$ dmesg | grep eth0
[  184.348573] 8139too 00:40:f4:44:68:8e: eth0: link up
[  190.271409] 8139too 00:40:f4:44:68:8e: eth0: link up
[  196.374125] 8139too 00:40:f4:44:68:8e: eth0: link up
[  201.823936] 8139too 00:40:f4:44:68:8e: eth0: link up
[  208.089862] 8139too 00:40:f4:44:68:8e: eth0: link up
[  212.200536] 8139too 00:40:f4:44:68:8e: eth0: link up
[  216.950829] 8139too 00:40:f4:44:68:8e: eth0: link up
[  221.071493] 8139too 00:40:f4:44:68:8e: eth0: link up
[  226.731134] 8139too 00:40:f4:44:68:8e: eth0: link up
[  230.778527] 8139too 00:40:f4:44:68:8e: eth0: link up
[  234.126353] 8139too 00:40:f4:44:68:8e: eth0: link up
[  238.936576] 8139too 00:40:f4:44:68:8e: eth0: link up
[  244.859427] 8139too 00:40:f4:44:68:8e: eth0: link up
[  250.845563] 8139too 00:40:f4:44:68:8e: eth0: link up
[  256.831661] 8139too 00:40:f4:44:68:8e: eth0: link up
[  262.458027] 8139too 00:40:f4:44:68:8e: eth0: link up
[  266.428794] 8139too 00:40:f4:44:68:8e: eth0: link up
[  271.305659] 8139too 00:40:f4:44:68:8e: eth0: link up
[  277.091885] 8139too 00:40:f4:44:68:8e: eth0: link up
[  282.768241] 8139too 00:40:f4:44:68:8e: eth0: link up
[  287.102103] 8139too 00:40:f4:44:68:8e: eth0: link up
[  290.866316] 8139too 00:40:f4:44:68:8e: eth0: link up
[  294.267496] 8139too 00:40:f4:44:68:8e: eth0: link up

ubuntu

In più, essa risultava completamente “sorda”, nel senso che anche sniffando il traffico mediante tcpdump, non vi era evidenza di frame/pacchetti di alcun genere, nonostante fosse collegata ad un segmento di rete piuttosto popolato.

Alla luce di ciò, le cause del suddetto malfunzionamento sarebbero potute essere 2:

1) guasto hardware;
2) aggiornamento che ha compromesso i driver del kernel che si interfacciano con la scheda (leggasi moduli), rendendola inutilizzabile.

Prima di procedere con l’analisi, però, è opportuno capire come avviene il riconoscimento dell’interfaccia di rete da parte del sistema operativo durante la fase di boot.

Chipset e moduli del kernel

Durante l’accesione (boot) della macchina, il sistema operativo riconosce la scheda di rete “dialongando” con il chipset di cui è dotata. Per individuarlo è sufficiente lanciare il seguente comando (con relativo output):

root@linux-box:~# lspci | grep Ethernet

04:01.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+ (rev 10)

Nella fattispecie, il chipset utilizzato dalla scheda è Realtek.

Il modulo del kernel in grado di interfacciarsi con essa prende il nome di r8139too e deve essere caricato in fase di avvio. Per verificare che il suddetto modulo sia effettivamente up è sufficiente lanciare il comando:

root@linux-box:~$ lsmod | grep 8139

il cui output sarà simile al seguente:

8139too                32177  0
8139cp                 27360  0

Udev e nomenclatura

Se il modulo è stato correttamente caricato, la scheda di rete può essere effettivamente “riconosciuta” come tale ed il sistema operativo sarà in grado di assegnarle un nome.

Durante tale fase entra in gioco il demone udev, che “leggerà” il contenuto del file di configurazione dedicato alle interfacce di rete, ovvero /etc/udev/rules.d/70-persistent-net.rules:

root@linux-box:~$ cat /etc/udev/rules.d/70-persistent-net.rules

# PCI device 0x10ec:/sys/devices/pci0000:00/0000:00:1e.0/0000:04:01.0 (8139too)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:40:f4:44:68:8e", ATTR{dev_id}=="0x0", ATTR{type}=="1", NAME="eth0"

La suddetta regola di esempio parla chiaro: appena viene identificata una scheda di rete recante come indirizzo MAC 00:40:f4:44:68:8e, come id 0x0 e come tipo 1, le dovrà essere assegnato come nome eth0.

Configurazione

A questo punto la scheda è pronta per essere configurata, secondo quanto definito all’interno del file /etc/network/interfaces:

auto eth0
iface eth0 inet static
address 192.168.11.1
netmask 255.255.255.0

Comandi di diagnostica

Se tutto è filato per il verso giusto, lanciando un semplice ifconfig, la suddetta scheda di rete sarà tra quelle disponibili:

root@linux-box:~$ ifconfig eth0
eth0      Link encap:Ethernet  IndirizzoHW 00:40:f4:44:68:8e
          indirizzo inet:192.168.1.1  Bcast:192.168.11.255  Maschera:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1989751 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3500430 errors:0 dropped:0 overruns:0 carrier:0
          collisioni:0 txqueuelen:1000
          Byte RX:339007498 (339.0 MB)  Byte TX:3756299292 (3.7 GB)
          Interrupt:16 Indirizzo base:0xe800

Inoltre, è possibile visualizzare il modulo in uso per interfacciarsi con la suddetta scheda, avvalendosi di ethtool con l’opzione -k:

root@linux-box:~$ ethtool -i eth0

il cui output sarà simile al seguente:

driver: 8139too
version: 0.9.28
firmware-version:
bus-info: 0000:04:01.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no

Per identificare, invece, alcuni dei suoi parametri di funzionamento, quali autonegoziazione, velocità, duplex, ecc., è sufficiente lanciare il comando:

root@linux-box:~# ethtool eth0

che ci darà un risultato simile al seguente:

Settings for eth0:
        Supported ports: [ TP MII ]
        Supported link modes:   10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
        Supported pause frame use: No
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full
                                100baseT/Half 100baseT/Full
        Advertised pause frame use: No
        Advertised auto-negotiation: Yes
        Link partner advertised link modes:  10baseT/Half 10baseT/Full
                                             100baseT/Half 100baseT/Full
        Link partner advertised pause frame use: Symmetric
        Link partner advertised auto-negotiation: Yes
        Speed: 100Mb/s
        Duplex: Full
        Port: MII
        PHYAD: 32
        Transceiver: internal
        Auto-negotiation: on
        Supports Wake-on: pumbg
        Wake-on: g
        Current message level: 0x00000007 (7)
                               drv probe link
        Link detected: yes

In alternativa, si possono ottenere delle informazioni più sintetiche utilizzando il più datato (e meno completo) mii-tool:

root@linux-box:~$ mii-tool eth0
eth0: negotiated 100baseTx-FD, link ok

Identificazione della causa

A valle delle riflessioni fatte fin’ora, tutto ciò che riguarda la scheda risulta coerente e conforme con quanto ci si aspettava, per cui è stato facile intuire, andando per esclusione, che si trattava, banalmente, di un guasto hardware.

Una volta sostituita la scheda, infatti, tutto ha ripreso a funzionare correttamente.

Alla prossima.

CentOS 6: debug del proxy Squid mediante cURL

Di recente, durante uno dei miei controlli di routine presso la rete di un cliente, mi sono accorto che il proxy ivi utilizzato (Squid) mandava in timeout tutte le richieste HTTP/HTTPS dirette al sito paypal.com.

squidOra, premesso che esistono diversi modi per fare un po’ di debug sul proxy, utilizzando ad esempio dei tool sviluppati ad hoc (uno su tutti squidclient), ho preferito adoperare semplicemente cURL, fondamentalmente per 3 motivi:

1) la sua semplicità di impiego;
2) l’ottima documentazione a corredo;
3) la possibilità di visualizzare gli header HTTP di ciascuna richiesta (tracciando eventuali redirect).

Ma bando alle ciance ed ecco come ho individuato (e risolto) l’anomalia riscontrata.

Test di funzionamento

Per prima cosa ho effettuato 2 differenti richieste: la prima diretta ad http://www.paypal.com e la seconda verso http://paypal.com, avvalendomi, rispettivamente, delle flag -v (verbose), -k (per ignorare eventuali problemi di certificati SSL/TLS), -x (per definire il proxy da utilizzare) e – L (che mi permette di indicare il sito target della richiesta). Per http://www.paypal.com ho ottenuto:

root@linux-box:~# curl -v -k -x http://192.168.10.1:3128 -L http://www.paypal.com
* About to connect() to proxy 192.168.10.1 port 3128 (#0)
*   Trying 192.168.10.1... connected
> GET http://www.paypal.com HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: www.paypal.com
> Accept: */*
> Proxy-Connection: Keep-Alive
>
* HTTP 1.0, assume close after body
< HTTP/1.0 302 Moved Temporarily
< Date: Tue, 21 Feb 2017 08:16:33 GMT
< Server: Apache
< Location: https://192.168.10.1/block.html
< Vary: Accept-Encoding
< Content-Length: 214
< Content-Type: text/html; charset=iso-8859-1
< X-Cache: MISS from localhost
< X-Cache-Lookup: MISS from localhost:3128
< Via: 1.0 localhost (squid/3.1.19)
* HTTP/1.0 connection set to keep alive!
< Connection: keep-alive
<
* Ignoring the response-body
* Connection #0 to host 192.168.10.1 left intact
* Issue another request to this URL: 'https://192.168.10.1/block.html'
* About to connect() to proxy 192.168.10.1 port 3128 (#1)
*   Trying 192.168.10.1... connected
* Establish HTTP proxy tunnel to 192.168.10.1:443
> CONNECT 192.168.10.1:443 HTTP/1.1
> Host: 192.168.10.1:443
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Proxy-Connection: Keep-Alive
>
< HTTP/1.0 200 Connection established
<
* Proxy replied OK to CONNECT request
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /*/*/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*        subject: C=IT; ST=Some-State; L=Roma; O=Test; CN=Test; emailAddress=hidden@email.it
*        start date: 2013-02-25 15:48:44 GMT
*        expire date: 2014-02-25 15:48:44 GMT
*        issuer: C=IT; ST=Some-State; L=Roma; O=Test; CN=Test; emailAddress=hidden@email.it
*        SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /block.html HTTP/1.0
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: 192.168.10.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 21 Feb 2017 08:16:33 GMT
< Server: Apache
< Last-Modified: Mon, 25 Feb 2013 16:13:19 GMT
< ETag: "f293-289-4d68ed1c4eeb4"
< Accept-Ranges: bytes
< Content-Length: 649
< Vary: Accept-Encoding
< Connection: close
< Content-Type: text/html
<
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Proibito</title>
</head>
<body>
<p align="center"><img src="http://192.168.10.1/images/forbidden.png" alt="forbidden" vspace="100"/></p>
<p align="center"><strong>I contenuti del sito sono stati bloccati per ragioni di sicurezza. Per maggiori informazioni contattare l'amministratore</strong></p>
</body>
</html>
* Closing connection #1
* SSLv3, TLS alert, Client hello (1):
* Closing connection #0

mentre per http://paypal.com l’output è stato il seguente:

root@linux-box:~# curl -v -k -x http://192.168.10.1:3128 -L http://paypal.com
* About to connect() to proxy 192.168.10.1 port 3128 (#0)
*   Trying 192.168.10.1... connected
> GET http://paypal.com HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: paypal.com
> Accept: */*
> Proxy-Connection: Keep-Alive
>
* HTTP 1.0, assume close after body
< HTTP/1.0 302 Moved Temporarily
< Date: Tue, 21 Feb 2017 08:17:36 GMT
< Server: Apache
< Location: https://192.168.10.1/block.html
< Vary: Accept-Encoding
< Content-Length: 214
< Content-Type: text/html; charset=iso-8859-1
< X-Cache: MISS from localhost
< X-Cache-Lookup: MISS from localhost:3128
< Via: 1.0 localhost (squid/3.1.19)
* HTTP/1.0 connection set to keep alive!
< Connection: keep-alive
<
* Ignoring the response-body
* Connection #0 to host 192.168.10.1 left intact
* Issue another request to this URL: 'https://192.168.10.1/block.html'
* About to connect() to proxy 192.168.10.1 port 3128 (#1)
*   Trying 192.168.10.1... connected
* Establish HTTP proxy tunnel to 192.168.10.1:443
> CONNECT 192.168.10.1:443 HTTP/1.1
> Host: 192.168.10.1:443
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Proxy-Connection: Keep-Alive
>
< HTTP/1.0 200 Connection established
<
* Proxy replied OK to CONNECT request
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /*/*/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*        subject: C=IT; ST=Some-State; L=Roma; O=Test; CN=Test; emailAddress=hidden@email.it
*        start date: 2013-02-25 15:48:44 GMT
*        expire date: 2014-02-25 15:48:44 GMT
*        issuer: C=IT; ST=Some-State; L=Roma; O=Test; CN=Test; emailAddress=hidden@email.it
*        SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /block.html HTTP/1.0
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: 192.168.10.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 21 Feb 2017 08:17:36 GMT
< Server: Apache
< Last-Modified: Mon, 25 Feb 2013 16:13:19 GMT
< ETag: "f293-289-4d68ed1c4eeb4"
< Accept-Ranges: bytes
< Content-Length: 649
< Vary: Accept-Encoding
< Connection: close
< Content-Type: text/html
<
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Proibito</title>
</head>
<body>
<p align="center"><img src="http://192.168.10.1/images/forbidden.png" alt="forbidden" vspace="100"/></p>
<p align="center"><strong>I contenuti del sito sono stati bloccati per ragioni di sicurezza. Per maggiori informazioni contattare l'amministratore</strong></p>
</body>
</html>
* Closing connection #1
* SSLv3, TLS alert, Client hello (1):
* Closing connection #0

Individuazione della causa di malfuzionamento

In entrambi i casi il proxy mi ha reindirizzato alla pagina di notifica di squidGuard, ovvero il software che si occupa del filtraggio dei siti Web. Ciò ha fatto scattare un campanello di allarme nella mia testa, in quanto entrambi i domini dovrebbero essere già consentiti, ragion per cui ho deciso di indagare ulteriormente analizzando i log delle blacklist di squidGuard:

root@linux-box:/var/log/squid# tail -f spyware.log
2017-02-21 09:57:06 [1636] Request(default/spyware/-) http://www.paypal.com/ 192.168.10.1/proxy - GET REDIRECT

Una volta individuata la blacklist di interesse (ovvero spyware) ho focalizzato alla mia attenzione sul file domains, andando alla ricerca di tutte le stringhe contenenti paypal.com. Così facendo, una entry ha subito destato in me qualche sospetto, ovvero:

-paypal.com

che ho prontamente sostituito con:

\-paypal.com

aggiungendo semplicemente il carattere di escape (\) davanti al carattere .

Ho quindi ricompilato le blacklist, settando i dovuti permessi e ricaricando la configurazione di Squid proxy:

root@linux-box:~# squidGuard -d -C all 
root@linux-box:~# chown proxy:proxy -R /var/lib/squidguard/db
root@linux-box:~# squid3 -k reconfigure

A questo punto ho lanciato una nuova richiesta verso http://paypal.com, proprio per sincerarmi che la entry errata contenuta nel file domains fosse proprio quella modificata in precedenza:

root@linux-box:/var/lib/squidguard/db/spyware# curl -v -k -x http://192.168.10.1:3128 -L http://paypal.com/
* About to connect() to proxy 192.168.10.1 port 3128 (#0)
*   Trying 192.168.10.1... connected
> GET http://paypal.com/ HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: paypal.com
> Accept: */*
> Proxy-Connection: Keep-Alive
>
* HTTP 1.0, assume close after body
< HTTP/1.0 302 Moved Temporarily
< Date: Tue, 21 Feb 2017 10:06:48 GMT
< Location: https://paypal.com/
< Server: BigIP
< Content-Length: 0
< X-Cache: MISS from localhost
< X-Cache-Lookup: MISS from localhost:3128
< Via: 1.0 localhost (squid/3.1.19)
* HTTP/1.0 connection set to keep alive!
< Connection: keep-alive
<
* Connection #0 to host 192.168.10.1 left intact
* Issue another request to this URL: 'https://paypal.com/'
* About to connect() to proxy 192.168.10.1 port 3128 (#1)
*   Trying 192.168.10.1... connected
* Establish HTTP proxy tunnel to paypal.com:443
> CONNECT paypal.com:443 HTTP/1.1
> Host: paypal.com:443
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Proxy-Connection: Keep-Alive
>
< HTTP/1.0 200 Connection established
<
* Proxy replied OK to CONNECT request
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using AES256-GCM-SHA384
* Server certificate:
*        subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=paypal.com
*        start date: 2016-11-04 00:00:00 GMT
*        expire date: 2018-11-01 12:00:00 GMT
*        issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
*        SSL certificate verify ok.
> GET / HTTP/1.0
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: paypal.com
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 301 Moved Permanently
< Location: https://www.paypal.com/
< Strict-Transport-Security: max-age=63072000
< Connection: close
< Content-Length: 0
<
* Closing connection #1
* SSLv3, TLS alert, Client hello (1):
* Issue another request to this URL: 'https://www.paypal.com/'
* About to connect() to proxy 192.168.10.1 port 3128 (#1)
*   Trying 192.168.10.1... connected
* Establish HTTP proxy tunnel to www.paypal.com:443
> CONNECT www.paypal.com:443 HTTP/1.1
> Host: www.paypal.com:443
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Proxy-Connection: Keep-Alive
>
< HTTP/1.0 200 Connection established
<
* Proxy replied OK to CONNECT request
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
*        subject: 1.3.6.1.4.1.311.60.2.1.3=US; 1.3.6.1.4.1.311.60.2.1.2=Delaware; businessCategory=Private Organization; serialNumber=3014267; C=US; postalCode=95131-2021; ST=California; L=San Jose; street=2211 N 1st St; O=PayPal, Inc.; OU=CDN Support; CN=www.paypal.com
*        start date: 2016-02-02 00:00:00 GMT
*        expire date: 2017-10-30 23:59:59 GMT
*        issuer: C=US; O=Symantec Corporation; OU=Symantec Trust Network; CN=Symantec Class 3 EV SSL CA - G3
*        SSL certificate verify ok.
> GET / HTTP/1.0
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: www.paypal.com
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 302 Moved Temporarily
< Server: Apache
< X-Recruiting: If you are reading this, maybe you should be working at PayPal instead! Check out https://www.paypal.com/us/webapps/mpp/paypal-jobs
< Paypal-Debug-Id: c075f46342370
< Cache-Control: no-cache
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< X-FRAME-OPTIONS: SAMEORIGIN
< Content-Security-Policy: default-src 'self' https://*.paypal.com https://*.paypalobjects.com https://nexus.ensighten.com 'unsafe-inline'; frame-src 'self' https://*.brighttalk.com https://*.paypal.com https://*.paypalobjects.com https://www.youtube.com/embed/ https://www.paypal-donations.com https://www.paypal-donations.co.uk https://*.qa.missionfish.org https://www.youtube-nocookie.com https://www.xoom.com https://*.pub.247-inc.net/; script-src 'self' https://*.brighttalk.com https://*.paypal.com https://*.paypalobjects.com https://www.youtube.com/iframe_api https://s.ytimg.com/yts/jsbin/ https://*.t.eloqua.com https://img.en25.com/i/elqCfg.min.js https://nexus.ensighten.com/ 'unsafe-inline' 'unsafe-eval'; connect-src 'self' https://*.paypal.com https://*.paypalobjects.com https://*.salesforce.com https://*.force.com https://*.eloqua.com https://nexus.ensighten.com https://storelocator.api.where.com https://api.paypal-retaillocator.com https://nominatim.openstreetmap.org https://www.paypal-biz.com; img-src 'self' * data:; object-src 'self' https://*.paypal.com https://*.paypalobjects.com; font-src 'self' https://*.paypalobjects.com;
< HTTP_X_PP_AZ_LOCATOR: slcb.slc
< Paypal-Debug-Id: c075f46342370
< Location: /it/home
< Content-Encoding: gzip
< Cache-Control: max-age=0, no-cache, no-store, must-revalidate
< Pragma: no-cache
< Content-Type: text/plain; charset=utf-8
< DC: phx-origin-www-1.paypal.com
< Content-Length: 56
< X-EdgeConnect-MidMile-RTT: 3
< X-EdgeConnect-Origin-MEX-Latency: 198
< X-EdgeConnect-MidMile-RTT: 169
< X-EdgeConnect-Origin-MEX-Latency: 198
< Date: Tue, 21 Feb 2017 10:06:51 GMT
< Connection: close
< Set-Cookie: LANG=it_IT%3BIT; Domain=.paypal.com; Path=/; Expires=Tue, 21 Feb 2017 18:52:46 GMT; HttpOnly
< Set-Cookie: tsrce=mppnodeweb; Domain=.paypal.com; Path=/; Expires=Wed, 22 Feb 2017 10:06:50 GMT; HttpOnly; Secure
< Set-Cookie: x-pp-s=eyJ0IjoiMTQ4NzY3MTYxMTM5NCIsIm0iOiIwIn0; Domain=.paypal.com; Path=/; HttpOnly; Secure
< Set-Cookie: nsid=s%3AUhjv0IeCf2Lsd4mAbdfaZCowZwbnEoLG.VPNYMobMlVf8MPI4EqbaGJHWsctx9knCbLdeDqVeGhg; Path=/; HttpOnly; Secure
< Set-Cookie: X-PP-SILOVER=name%3DLIVE3.WEB.1%26silo_version%3D880%26app%3Dmppnodeweb%26TIME%3D991013976%26HTTP_X_PP_AZ_LOCATOR%3Dslcb.slc; Expires=Tue, 21 Feb 2017 10:36:51 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
< Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT
< Set-Cookie: AKDC=phx-origin-www-1.paypal.com; expires=Tue, 21-Feb-2017 10:36:51 GMT; path=/; secure
< Set-Cookie: akavpau_ppsd=1487672211~id=cae8071e8da0e5fdb485811908c64fd0; path=/
< Strict-Transport-Security: max-age=63072000
<
* Closing connection #1
* SSLv3, TLS alert, Client hello (1):
* Issue another request to this URL: 'https://www.paypal.com/it/home'
* About to connect() to proxy 192.168.10.1 port 3128 (#1)
*   Trying 192.168.10.1... connected
* Establish HTTP proxy tunnel to www.paypal.com:443
> CONNECT www.paypal.com:443 HTTP/1.1
> Host: www.paypal.com:443
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Proxy-Connection: Keep-Alive
>
< HTTP/1.0 200 Connection established
<
* Proxy replied OK to CONNECT request
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSL re-using session ID
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
*        subject: 1.3.6.1.4.1.311.60.2.1.3=US; 1.3.6.1.4.1.311.60.2.1.2=Delaware; businessCategory=Private Organization; serialNumber=3014267; C=US; postalCode=95131-2021; ST=California; L=San Jose; street=2211 N 1st St; O=PayPal, Inc.; OU=CDN Support; CN=www.paypal.com
*        start date: 2016-02-02 00:00:00 GMT
*        expire date: 2017-10-30 23:59:59 GMT
*        issuer: C=US; O=Symantec Corporation; OU=Symantec Trust Network; CN=Symantec Class 3 EV SSL CA - G3
*        SSL certificate verify ok.
> GET /it/home HTTP/1.0
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: www.paypal.com
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: Apache
< X-Recruiting: If you are reading this, maybe you should be working at PayPal instead! Check out https://www.paypal.com/us/webapps/mpp/paypal-jobs
< Paypal-Debug-Id: ef6f606ac62a4
< Cache-Control: no-cache
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< X-FRAME-OPTIONS: SAMEORIGIN
< Content-Security-Policy: default-src 'self' https://*.paypal.com https://*.paypalobjects.com https://nexus.ensighten.com 'unsafe-inline'; frame-src 'self' https://*.brighttalk.com https://*.paypal.com https://*.paypalobjects.com https://www.youtube.com/embed/ https://www.paypal-donations.com https://www.paypal-donations.co.uk https://*.qa.missionfish.org https://www.youtube-nocookie.com https://www.xoom.com https://*.pub.247-inc.net/; script-src 'self' https://*.brighttalk.com https://*.paypal.com https://*.paypalobjects.com https://www.youtube.com/iframe_api https://s.ytimg.com/yts/jsbin/ https://*.t.eloqua.com https://img.en25.com/i/elqCfg.min.js https://nexus.ensighten.com/ 'unsafe-inline' 'unsafe-eval'; connect-src 'self' https://*.paypal.com https://*.paypalobjects.com https://*.salesforce.com https://*.force.com https://*.eloqua.com https://nexus.ensighten.com https://storelocator.api.where.com https://api.paypal-retaillocator.com https://nominatim.openstreetmap.org https://www.paypal-biz.com; img-src 'self' * data:; object-src 'self' https://*.paypal.com https://*.paypalobjects.com; font-src 'self' https://*.paypalobjects.com;
< ETag: W/"6646-N9seUapd2xMK7C+gFi/cTw"
< HTTP_X_PP_AZ_LOCATOR: dcg11.slc
< Paypal-Debug-Id: ef6f606ac62a4
< Cache-Control: max-age=0, no-cache, no-store, must-revalidate
< Pragma: no-cache
< Content-Type: text/html; charset=utf-8
< DC: phx-origin-www-1.paypal.com
< X-EdgeConnect-MidMile-RTT: 3
< X-EdgeConnect-Origin-MEX-Latency: 242
< X-EdgeConnect-MidMile-RTT: 175
< X-EdgeConnect-Origin-MEX-Latency: 242
< Date: Tue, 21 Feb 2017 10:06:54 GMT
< Content-Length: 26182
< Connection: close
< Set-Cookie: cookie_check=yes; Domain=.paypal.com; Path=/; Expires=Sun, 21 Feb 2027 10:06:52 GMT; HttpOnly; Secure
< Set-Cookie: LANG=it_IT%3BIT; Domain=.paypal.com; Path=/; Expires=Tue, 21 Feb 2017 18:52:48 GMT; HttpOnly
< Set-Cookie: tsrce=mppnodeweb; Domain=.paypal.com; Path=/; Expires=Wed, 22 Feb 2017 10:06:52 GMT; HttpOnly; Secure
< Set-Cookie: x-pp-s=eyJ0IjoiMTQ4NzY3MTYxMzk0NyIsIm0iOiIwIn0; Domain=.paypal.com; Path=/; HttpOnly; Secure
< Set-Cookie: nsid=s%3A74ujkGU9eWQSC2wQM8PXHRRoHjuQmucM.0ykPY%2FAkmfXl50QcbBuCSwC7lEm1YbqKWOXxw4FicY0; Path=/; HttpOnly; Secure
< Set-Cookie: X-PP-SILOVER=name%3DLIVE3.WEB.1%26silo_version%3D880%26app%3Dmppnodeweb%26TIME%3D1024568408%26HTTP_X_PP_AZ_LOCATOR%3Ddcg11.slc; Expires=Tue, 21 Feb 2017 10:36:53 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
< Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT
< Set-Cookie: AKDC=phx-origin-www-1.paypal.com; expires=Tue, 21-Feb-2017 10:36:54 GMT; path=/; secure
< Set-Cookie: akavpau_ppsd=1487672214~id=56a8294899d3c18083d0709205e7d737; path=/
< Strict-Transport-Security: max-age=63072000
<
<

richiesta che è andata a buon fine, per la causa del problema è stata correttamente individuata.

Soluzione definitiva

Per risolvere definitivamente tale anomalia (legata principalmente alla cattiva gestione, da parte di squidGuard, dei domini che contengono caratteri particolari), ho deciso di agire come segue. Poichè le blackist vengono aggiornate ogni notte in modo automatico, il file domains modificato in precedenza verrebbe continuamente sovrascritto, rendendo nulla la sostituzione di -paypal.com com con \-paypal.com. Quindi, per fare in modo che squidGuard torni a consentire definitivamente l’accesso al dominio paypal.com (e relativi sottodomini), ho deciso di creare un file domains all’interno della dir /var/lib/squidguard/db/whitelist, contenente la entry paypal.com:

root@linux-box:~# cat /var/lib/squidguard/db/whitelist/domains
paypal.com

Ho quindi modificato la configurazione di squidGuard (/etc/squid/squidGuard.conf), ridefinendo la sequenza di matching dell’ACL che si occupa del filtraggio:

acl {
        default {
                pass whitelist !aggressive !drugs !gambling !hacking !porn !proxy !redirector !spyware !suspect !violence !warez !custom
                redirect http://192.168.10.1/block.html
        }

Nella fattispecie, ho fatto in modo che venissero dapprima consentiti tutti i domini in whitelist, bloccati i domini presenti nelle blacklist ed infine consentiti tutti gli altri.

Ho quindi ricompilato le blacklist di squidGuard come visto in precedenza:

root@linux-box:~# squidGuard -d -C all 
root@linux-box:~# chown proxy:proxy -R /var/lib/squidguard/db
root@linux-box:~# squid3 -k reconfigure

ed il problema è stato definitivamente risolto.

Alla prossima.

Configurazione del demone snmpd su CentOS 6

Utilizzare il protocollo SNMP per il monitoraggio dei dispositivi di rete è sempre una buona scelta, tenendo bene a mente, però, che le versioni 1 e 2 non prevedono cifratura della community string e quindi sono vulnerabili ad eventiali attacchi MITM. Inoltre, in determinate circostanze, tale protocollo può essere impiegato anche per il monitoraggio delle macchine *nix, soprattutto per ciò che concerne lo stato delle interfacce di rete ed il loro throughput.

snmpInstallazione e configurazione di snmpd

Vediamo adesso come configurare il demone snmpd su una macchina CentOS 6.

Per prima cosa occorre installare i seguenti pacchetti tramite yum:

[root@server ~]# yum install net-snmp net-snmp-utils

A questo punto passiamo alla configurazione del demone vera e propria, editando il file /etc/snmp/snmp.conf. 

Definiamo, dapprima, le utenze ed i gruppi, mediante le seguenti direttive:

com2sec local      localhost        secret
com2sec mynetwork  192.168.1.0/24 secret

group local      v2c        local
group mynetwork  v2c        mynetwork

In particolare, mediante la keyword com2sec stiamo definendo l’utente local, il cui IP/hostname sorgente dovrà essere localhost e la cui community string dovrà essere secret. Discorso analogo vale per l’utente mynetwork.

Invece, per ciò che concerne la definizione dei gruppi, la keyword da utilizzare è group, seguita dal nome del gruppo, dalla versione del protocollo SNMP (v2c) e dal nome degli utenti che ne fanno parte (local nel primo caso e mynetwork nel secondo).

Successivamente è necessario abilitare l’intera alberatura degli OID, mediante la seguente direttiva:

view all    included  .1                               80

Infine, passiamo alla definizione delle ACL per i gruppi appena creati:

#               context sec.model sec.level prefix   read  write notif
access  local     ""      any       noauth   exact   all   none none
access  mynetwork ""      any       noauth   exact   all   none none

dove la prima riga indica il significato di ciascun campo utilizzato dopo la keyword access ed il gruppo a cui l’ACL si riferisce. Dalla suddetta configurazione è facile notare come entrambi i gruppi (local e mynetwork) abbiano solo la possibilità di effettuare GET SNMP (read) ma non SET (write).

Per completezza, è possibile editare dei campi facoltativi quali syslocation e syscontact:

syslocation Italy server.vostrodominio.com
syscontact Nome Cognome <vostro.indirizzo@email.it>

Riavviamo snmpd per rendere effettive le suddette modifiche:

[root@server ~]# service snmpd restart

ed effettuiamo una query di prova, avvalendoci del tool snmpwalk:

[root@server ~]# snmpwalk -v 2c -c secret localhost

Se otterremo in output l’intera alberatura SNMP supportata dalla macchina significa che il demone sta funzionando come dovrebbe.

 Configurazione di Nagios

Per fare in modo che il nostro NMS sia in grado di monitorare lo stato ed il throughput delle interfacce di rete, occorre definire i seguenti comandi all’interno del file /etc/nagios/objects/commands.cfg:

# 'check_snmp_if_status' command definition
define command{
        command_name    check_snmp_if_status
        command_line    $USER1$/check_snmp -H $HOSTADDRESS$ -C $ARG1$ -P $ARG2$ -o $ARG3$ -r $ARG4$
        }

# 'check_local_mrtgtraf' command definition
define command{
        command_name    check_local_mrtgtraf
        command_line    $USER1$/check_mrtgtraf -F "$ARG1$" -a "$ARG2$" -w "$ARG3$" -c "$ARG4$" -a "$ARG5$"
        }

ed i seguenti servizi all’interno del file di configurazione associato alla macchina da monitorare:

define service{
        use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_descripion             WAN Interface eth0 Operational Status
        check_command                   check_snmp_if_status!secret!IF-MIB::ifOperStatus.2!1
        }

define service{
        use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_descripion             LAN Interface eth1 Operational Status
        check_command                   check_snmp_if_status!secret!2c!IF-MIB::ifOperStatus.3!1
        }

define service{
        use                             local-service   ; Name of service template to use
        host_name                       localhost
        service_descripion             WAN Interface eth0 Bandwidth Usage
        check_command                   check_local_mrtgtraf!/var/www/mrtg/localhost_2.log!AVG!100000000,200000000!110000000,120000000!10
        }

define service{
        use                             local-service   ; Name of service template to use
        host_name                       localhost
        service_descripion             LAN Interface eth1 Bandwidth Usage
        check_command                   check_local_mrtgtraf!/var/www/mrtg/localhost_3.log!AVG!100000000,200000000!110000000,120000000!10
        }

Nella fattispecie, il monitoraggio del throughput viene realizzato mediante il plugin check_mrtgtraf, il cui scopo è quello di analizzare i file di log generati da MRTG (vedi questo post per ulteriori dettagli).

Ricarichiamo la configurazione di Nagios per rendere effettive le suddette modifiche:

[root@server ~]# service nagios reload

ed abbiamo finito.

Alla prossima.

CentOS 6, Nagios e NagVis: creazione di mappe personalizzate per l’attività di monitoring

Da qualche anno ormai sono solito postare diversi articoli riguardanti il mio NMS preferito, ovvero Nagios (nella versione core). Qualcuno di voi obietterà dicendo che c’è di meglio sul mercato, soprattutto per ciò che concerne la facilità/rapidità di utilizzo e configurazione. Personalmente credo che, utilizzando le terze parti che hanno reso celebre il software in questione, è possibile raggiungere livelli di usabilità e prestazioni del tutto simili a quelle degli NMS concorrenti e di ultima generazione (vedi, ad esempio, Icinga).

nagvis

In particolare, la mia infrastruttura di monitoraggio tipo si compone dei seguenti elementi:

1) Nagios core;

2) PNP4Nagios per la graficizzazione dei risultati ottenuti mediante i check;

2) Un sistema per la ricezione delle trap SNMP (snmptrapd + snmptt per la loro traduzione) convertite all’occorrenza in check passivi mediante il plugin submit_check_result;

3) Un tool per il monitoraggio delle macchine Windows mediante polling (NRPE + check_nrpe);

4) NSCA insieme ad NSClient++ per la ricezione dei check passivi provenienti dalle macchine Windows;

5) Swatch + NRDP per la conversione dei nuovi eventi registrati all’interno dei file di log (monitorati in tempo reale da swatch) in check passivi;

6) MRTG per il monitoraggio delle prestazioni della rete (throughput di picco e medio) e, all’occorrenza, per tenere sotto controllo le performance di Nagios (vedi questo articolo per ulteriori dettagli);

7) Event handlers vari ed eventuali per la risoluzione automatica dei problemi segnalati da Nagios;

8) NagVis per la creazione di mappe personalizzate, contenenti tutti gli elementi della nostra infrastruttura che vogliamo tenere sotto controllo (con grado di dettaglio libero a piacere).

In questo post tratterò, per l’appunto, l’installazione e la configurazione di NagVis.

Installazione e configurazione dell’event broker

Per prima cosa occorre scaricare ed installare sul nostro sistema il cosiddetto event broker, ovvero un applicativo che farà da “tramite” (lasciatemi passare il termine) tra Nagios e NagVis. Nella fattispecie, esso “interrogherà” Nagios sullo stato di un host o di un servizio e girerà il risultato a NagVis.

L’event broker di nostro interesse è mklivestatus (creato da Mathias Kettner, lo stesso autore di Check_Mk), la cui pagina ufficiale è questa.

Possiamo dunque scaricarlo:

[root@linuxbox ~]# cd /usr/local/

[root@linuxbox local]# wget 'https://mathias-kettner.de/download/check_mk-1.2.7i3p5.tar.gz'

decomprimerlo:

[root@linuxbox local]# tar -xvf check_mk-1.2.7i3p5.tar.gz

ed installarlo:

[root@linuxbox local]# cd check_mk-1.2.7i3p5 && ./configure && make && make install

A questo punto creiamo la directory rw all’interno di /var/spool/nagios, assegnandole il giusto owner:

[root@linuxbox local]# cd /var/spool/nagios && mkdir rw

[root@linuxbox nagios]# chown nagios:nagios rw

In questo modo il nostro event broker potrà salvare le informazioni, ricavate dall’NMS, all’interno dell’apposito file /var/spool/nagios/rw/live.

Ora possiamo integrare il suddetto applicativo a Nagios, modificandone il file di configurazione (/etc/nagios/nagios.cfg) come segue:

event_broker_options=-1

broker_module=/usr/local/lib/mk-livestatus/livestatus.o /var/spool/nagios/rw/live

Passiamo adesso a NagVis.

Installazione e configurazione di NagVis

Prima di tutto è necessario installare le dipendenze indispensabili al suddetto applicativo:

[root@linuxbox ~]# yum install php-gd php-mbstring php-pdo graphviz graphviz-graphs perl-GraphViz graphviz-doc rsync

A questo punto sarà possibile installare NagVis puntando a questo link. Esso si riferisce all’ultima versione stabile (ovvero la 1.8.5).

[root@linuxbox ~]# cd /usr/local/ && wget http://www.nagvis.org/share/nagvis-1.8.5.tar.gz

Una volta completato il download occorre decomprimere l’archivio:

[root@linuxbox local]# tar -xvf nagvis-1.8.5.tar.gz

e, successivamente, passare all’installazione vera e propria dell’applicativo:

[root@linuxbox local]# cd nagvis-1.8.5 && ./install.sh

Inoltre, occorre configurarlo come segue:

[root@linuxbox nagvis]# nano etc/nagvis.ini.php

[backend_live_1]
backendtype="mklivestatus"
socket="unix:/var/spool/nagios/rw/live"

Riavviamo httpd:

[root@linuxbox nagvis]# service nagios reload

e puntiamo all’indirizzo dell’interfaccia Web di NagVis:

http://ipserver/nagvis

Infine, dopo esserci loggati utilizzando le credenziali di default (admin/admin), possiamo modificarle ed installare delle immagini utili alla creazione delle nostre mappe attingendo da questo e quest’altro sito.

Il risultato finale sarà simile al seguente:

nagvis_vmwareIl post termina qui, alla prossima.

Nagios e CentOS 6: tuning dei service check timeout

In questo post vi ho parlato di come configurare Nagios affinchè riesca a monitorare lo stato degli aggiornamenti relativi ad una macchina Windows Server 2008 R2.

Per qualche tempo tutto ha funzionato correttamente, fino a quando il servizio in questione ha cominciato a restituirmi dei timeout. Aver ridotto gli intervalli dei check non ha portato i risultati sperati, per cui ho dovuto armarmi di pazienza ed iniziare a fare un po’ di sano troubleshooting.

nagiosProblema

Dopo l’uscita degli ultimi sistemi operativi di casa Microsoft (8, 10, Server 2012, Server 2012 R2), la verifica degli aggiornamenti relativi a Windows 7, Server 2008 e Server 2008 R2 (per i quali il supporto è ancora attivo) è diventato un processo lento e macchinoso, probabilmente a causa della minore priorità data agli OS in questione. Ecco la causa principale dei timeout di cui sopra. Come risolvere dunque? Procediamo utilizzando un metodo (quasi) infallibile, ovvero il divide et impera.

Step 1: verifica del timeout associato al comando check_nrpe

Il tool check_nrpe, utilizzato per interrogare lo stato della macchina Windows, prevede l’uso (facoltativo) della flag -t, utile per la definizione del tempo di timeout (che per default è pari a 10 secondi). Per questo motivo ho fatto in modo che il comando check_WMI_windows_updates prevedesse la possibilità di specificare un tempo di timeout libero a piacere (-t $ARG1$):

# nagios-WMI-windows-updates check command definition

define command {
        command_name    check_WMI_windows_updates
        command_line    /usr/lib64/nagios/plugins/check_nrpe -H $HOSTADDRESS$ -t $ARG1$ -c get_windows_updates
        }

Nella fattispecie, il servizio che si avvale del suddetto comando ha un tempo di timeout pari a 600 secondi, come riportato di seguito:

define service{
        use                             generic-service         ; Name of service template to use
        host_name                       Windows-Machine
        service_description             query WMI Updates for Microsoft Windows Machine
        check_command                   check_WMI_windows_updates!600
        normal_check_interval           120
        }

Esso deve coincidere con il timeout del comando get_windows_updates definito all’interno del file \Pugins\V2\V2_nrpe_commands.cfg, il cui contenuto sarà:

command[get_windows_updates]=cscrip.exe //nologo //T:600 c:\nrpe\plugins\v2\check_windows_updates.wsf /w:0 /c:1

Il suddetto timeout va definito anche all’interno del file bin\nrpe.cfg, nel modo seguente:

command_timeout= 600

Tutte queste modifiche erano già state opportunamente trattate nell’ambito del mio post originale, ma ho ritenuto comunque utile rammentarle.

Step 2: verifica del timeout associato ai servizi di Nagios

Fortunatamente, l’NMS in questione ci consente di definire un tempo di timeout “globale” per i check dei servizi definiti dall’utente. Esso è presente all’interno del file /etc/nagios/nagios.cfg e la direttiva di nostro interesse è service_check_timeout da impostare come segue:

service_check_timeout=600

Riavviamo quindi Nagios per rendere effettive le modifiche appena apportate:

[root@linuxbox ~]# service nagios reload

Step 3: verifica dei timeout delle NAT translations

L’ultima fase di troubleshooting consiste nella verifica dei timeout associati alle NAT translations del router. Il dispositivo in questione è un Cisco 877 e per visualizzare le informazioni di nostro interesse occorre utilizzare il comando:

sh ip nat translations verbose

il cui output sarà simile al seguente:

extended, timing-out, use_count: 0, entry-id: 427758, lc_entries: 0
tcp 78.13.12.241:443      192.168.4.2:443       ---                   ---
    create 2w0d, use 00:00:51 timeout:300000, timing-out,
    flags:

Come si può notare, il timeout di default per le connessioni TCP è pari a 300000 ms (300 secondi ovvero 5 minuti), ergo dobbiamo incrementarlo fino a 600000 per allinearlo alla configurazione di Nagios. Per fare ciò è sufficiente lanciare il comando:

ip nat translation tcp-timeout 600

Salviamo la configurazione del router mediante un copy run start ed i timeout del servizio spariranno come per magia.

Il post termina qui, alla prossima.

Cisco 877: configurazione del server DHCP integrato

Come ogni router che si rispetti, anche il Cisco 877 può essere configurato a mo’ di server DHCP, seguendo una procedura abbastanza semplice ed intuitiva. In questo post vedremo come tirare giù una configurazione base, comprensiva di una exclusion e di una reservation.

cisco 877Definizione dei pool DHCP e della reservation

Per prima cosa occorre definire i pool di indirizzi IP da cui il nostro server andrà “a pescare” quelli da assegnare alle macchine che ne faranno richiesta. Nello specifico, ho creato 2 pool, uno per gli indirizzi della LAN (pool wifi) ed uno necessario alla reservation (pool pcportatile), ovvero:

ip dhcp pool wifi
   network 192.168.7.0 255.255.255.0
   default-router 192.168.7.1
   dns-server 192.168.7.1
!
ip dhcp pool pcportatile
   host 192.168.7.3 255.255.255.0
   client-identifier 0149.d224.a5d4.0e
   default-router 192.168.7.1
   dns-server 192.168.7.1

Da notare che per il pool pcportatile ho utilizzato la direttiva client-identifier, recante il MAC address del dispositivo oggetto della reservation, nella forma aaaa.bbbb.cccc e con prefisso 01. Nella fattispecie, il MAC address del PC è 49:d2:24:a5:d4:0e, che in notazione Cisco diventa 49d2.24a5.d40e. Aggiungiamo quindi lo 01 come prefisso ed avremo il client-identifier finale, ovvero 0149.d224.a5d4.0e.

Detto ciò, un modo rapido di ricavare il suddetto identificativo consiste nell’utilizzo del seguente comando:

sh ip dhcp binding

il cui output sarà simile al seguente:

Bindings from all pools not associated with VRF:
IP address          Client-ID/              Lease expiration        Type
                    Hardware address/
                    User name
192.168.7.3         0149.d224.a5d4.0e       Infinite                Manual
192.168.7.8         0151.f0d3.fc7d.54       Sep 07 2016 09:15 AM    Automatic

Definizione dell’exclusion

Per ciò che concerne l’exclusion, la sua configurazione consta di un’unica direttiva, ovvero:

ip dhcp excluded-address 192.168.7.2

In tal modo faremo sì che l’IP 192.168.7.2 non rientri nei pool precedentemente definiti e quindi non possa essere assegnato a nessun dispositivo (poichè trattasi di un indirizzo statico associato ad una stampante).

Il post termina qui, alla prossima.

NRPE_NT e Nagios: script PowerShell per il controllo dell’uptime su Windows Server 2008 R2

Tenere sotto controllo l’uptime dei nostri server è molto importante, soprattutto se si ha a che fare con macchine in produzione. Per ciò che concerne i sistemi operativi di casa Microsoft (sia client che server), esiste un comando che può tornarci molto utile allo scopo, ovvero:

net stats srv

il quale, basandosi sul servizio Server di Windows, colleziona e fornisce tutta una serie di informazioni associate alla nostra macchina, tra cui, per l’appunto, il suo tempo di attività:

Statistics since 7/11/2016 9:21:08 AM

powershellAffinchè il suddetto task possa essere effettuato in automatico dal nostro NMS (Nagios), è necessario utilizzare uno scrip (get_uptime.ps1, creato da me allo scopo) da integrare al servizio NRPE_NT. Per ragioni di semplicità e comodità ho deciso di avvalermi di Windows PowerShell per la stesura dello stesso, il cui contenuto è il seguente:

$critical = $Args[0]
$warning = $Args[1]

if ($warning -and $critical) #both variable are defined and not empty
{
    if ($critical -lt $warning)
    {
        $os = Get-WmiObject win32_operatingsystem
        $uptime = (Get-Date) - ($os.ConvertToDateTime($os.lastbootuptime))
        $minutes_to_seconds = $Uptime.Minutes*60
        $hours_to_seconds = $Uptime.Hours*3600
        $days_to_seconds = $Uptime.Days*86400
        $uptime_in_seconds = $minutes_to_seconds + $hours_to_seconds + $days_to_seconds
        if ($uptime_in_seconds -gt $critical -and $uptime_in_seconds -gt $warning)
        {
            $Display = "OK: System Uptime is " + $Uptime.Days + " days, " + $Uptime.Hours + " hours, " + $Uptime.Minutes + " minutes"
            Write-Output $Display
            exit 0
        }
        elseif ($uptime_in_seconds -gt $critical -and $uptime_in_seconds -le $warning)
        {
            $Display = "WARNING: System Uptime is " + $Uptime.Days + " days, " + $Uptime.Hours + " hours, " + $Uptime.Minutes + " minutes"
            Write-Output $Display
            exit 1
        }
        else
        {
            $Display = "CRITICAL: System Uptime is " + $Uptime.Days + " days, " + $Uptime.Hours + " hours, " + $Uptime.Minutes + " minutes"
            Write-Output $Display
            exit 2
        }
    }
    else
    {
        $Usage = "Usage: .\get_uptime.ps1 <critical threshold in seconds> <warning threshold in seconds>"
        $Error1 = "Warning threshold must be greater then the critical one"
        Write-Output $Usage
        Write-Output $Error1
        exit 3
    }
}
else
{
    $Usage = "Usage: .\get_uptime.ps1 <critical threshold in seconds> <warning threshold in seconds>"
    $Error2 = "Warning threshold and critical threshold must be defined"
    Write-Output $Usage
    Write-Output $Error2
    exit 3
}

In soldoni, il suddetto scrip riceve due argomenti da linea di comando, ovvero la soglia critica e quella di warning, espresse entrambe in secondi. Ovviamente, trattandosi di tempo di attività, la prima deve essere strettamente minore della seconda.

Configurazione di NRPE_NT

Salviamo tale scrip all’interno della directory C:\nrpe\Plugins\V2 e successivamente editiamo il file C:\nrpe\Plugins\V2\V2_nrpe_commands.cfg, aggiungendo la seguente direttiva:

# =================================
# Windows System Uptime checks
# =================================

command[get_system_uptime]=cmd.exe /c echo C:\nrpe\Plugins\V2\get_uptime.ps1 "$ARG1$" "$ARG2$" | powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -command -

In particolare, stiamo definendo il comando get_system_uptime che si avvarrà di get_uptime.ps1 per l’individuazione del tempo di attività.

Occorre precisare che l’esecuzione dello scrip non può avvenire richiamando direttamente l’eseguibile powershell.exe, ma deve prima passare per cmd.exe (il cui output, mediante pipe, viene dato in pasto a PowerShell grazie alla direttiva -command –, dove il finale rappresenta “tutto ciò che proviene dal pipe”). Inoltre, si rende indispensabile bypassare l’executionpolicy di PowerShell, consentendo ad NRPE_NT di lanciare get_uptime.ps1 senza restrizioni.

Infine, riavviamo NRPE_NT per rendere effettive le suddette modifiche:

C:\Users\Administrator> net stop nrpe_nt
C:\Users\Administrator> net start nrpe_nt

Configurazione di Nagios

Per prima cosa è necessario creare un apposito comando all’interno del file /etc/nagios/object/commands.cfg:

# nagios-Windows-uptime check command definition

define command {
        command_name    check_Windows_uptime
        command_line    /usr/lib64/nagios/plugins/check_nrpe -H $HOSTADDRESS$ -t $ARG1$ -c get_system_uptime -a $ARG2$ $ARG3$
        }

Successivamente, all’interno del file che rappresenta l’host da monitorare, è necessario aggiungere un servizio specifico che si avvale del suddetto comando:

define service{
        use                             generic-service         ; Name of service template to use
        host_name                       Windows-Server
        service_descripion             query Windows System Uptime for Microsoft Windows Machine
        check_command                   check_Windows_uptime!30!60!900
        }

Ricarichiamo la configurazione di Nagios:

[root@linuxbox ~]# service nagios reload

ed abbiamo finito.

Alla prossima.

Logica di funzionamento del DNS (Domain Name System)

Prima di approfondire un argomento che avevo già trattato tempo addietro, ovvero il DNS cache poisoning (vedi qui per ulteriori dettagli), è utile illustrare la logica di funzionamento su cui si basa il Domain Name System.

Esistono, in soldoni, 2 tipologie di query DNS:
1) ricorsive;
2) iterative.

Supponiamo che il client voglia risolvere l’FQDN www.ciao.com

Nel primo caso il client contatterà il proprio resolver (ad esempio il nameserver dell’ISP) sottoponendogli la query. Se la risposta non è contenuta all’interno
della sua cache, esso effettuerà una query ai root nameserver. I root nameserver forniranno una risposta di tipo referral (con ANSWER SECTION vuota ed AUTHORITY SECTION non vuota), contenente una lista di nameserver da contattare per il top level domain (in gergo TLD) .com.
A questo punto il resolver contatterà uno dei nameserver autoritativi appena individuati, il quale fornirà una risposta di tipo referral indicando il nameserver autoritativo per il dominio cercato. Infine, quest’ultimo verrà interrogato e fornirà una risposta alla query (ANSWER SECTION non vuota) indicando l’indirizzo IP relativo al record A (www) ricercato (sempre se il suddetto record esiste).
La risposta, una volta giunta al resolver, verrà quindi girata al client.

recursiveDa notare che sia i root nameserver che i nameserver autoritativi per i TLD forniscono esclusivamente risposte di tipo referral, ergo funzionano solo
in modalità iterativa. Infatti, pensate a cosa accadrebbe se ciascun root nameserver interrogato (13 in tutto) iniziasse a fare query ricorsive per individuare
un determinato indirizzo IP… sarebbe una scelta davvero sconveniente (per usare un’espressione moderata) sia in termini di carico che in termini di latenza.

Inoltre, ciascun software che svolge funzioni di namserver utilizza degli algoritmi ben precisi per individuare il server a cui sottoporre la query (root, TLD o autoritativo che sia).
Nella fattispecie, bind usa la tecnica dell’RTT (Round Trip Time), grazie alla quale dovrebbe riuscire ad individuare il namserver più peformante (che coincide con quello che ha risposto più velocemente alla query).

Per ciò che concerne le query iterative, esse prevedono (in generale) il coinvolgimento diretto del client. Per prima cosa esso sottoporrà la query al proprio resolver, che gli risponderà con la lista dei root nameserver (risposta di tipo referral). Il root nameserver successivamente contattato dal client, gli fornirà una risposta di tipo referral indicando una lista di namserver autoritativi per il TLD .com. Dopodichè il client sottoporrà la query ad uno dei predetti nameserver, il quale gli fornirà come risposta una lista dei namserver autoritativi per il dominio ciao.com.
Infine, il client contatterà uno dei nameserver autoritativi per ciao.com che gli girerà la risposta contenente l’indirizzo IP per www.ciao.com (sempre se il record esiste).

Un esempio di query iterativa più essere facilmente ricavato utilizzando dig con l’opzione +trace, ad esempio:

[root@linuxbox ~]# dig +trace www.ciao.com

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.2 <<>> +trace www.ciao.com
;; global options: +cmd
.                       440639  IN      NS      b.root-servers.net.
.                       440639  IN      NS      m.root-servers.net.
.                       440639  IN      NS      h.root-servers.net.
.                       440639  IN      NS      k.root-servers.net.
.                       440639  IN      NS      a.root-servers.net.
.                       440639  IN      NS      i.root-servers.net.
.                       440639  IN      NS      f.root-servers.net.
.                       440639  IN      NS      e.root-servers.net.
.                       440639  IN      NS      j.root-servers.net.
.                       440639  IN      NS      d.root-servers.net.
.                       440639  IN      NS      l.root-servers.net.
.                       440639  IN      NS      g.root-servers.net.
.                       440639  IN      NS      c.root-servers.net.
;; Received 496 bytes from 192.168.1.1#53(192.168.1.1) in 38 ms

com.                    172800  IN      NS      a.gtld-servers.net.
com.                    172800  IN      NS      b.gtld-servers.net.
com.                    172800  IN      NS      c.gtld-servers.net.
com.                    172800  IN      NS      d.gtld-servers.net.
com.                    172800  IN      NS      e.gtld-servers.net.
com.                    172800  IN      NS      f.gtld-servers.net.
com.                    172800  IN      NS      g.gtld-servers.net.
com.                    172800  IN      NS      h.gtld-servers.net.
com.                    172800  IN      NS      i.gtld-servers.net.
com.                    172800  IN      NS      j.gtld-servers.net.
com.                    172800  IN      NS      k.gtld-servers.net.
com.                    172800  IN      NS      l.gtld-servers.net.
com.                    172800  IN      NS      m.gtld-servers.net.
;; Received 490 bytes from 192.203.230.10#53(192.203.230.10) in 4323 ms

ciao.com.               172800  IN      NS      dns2.progtech.net.
ciao.com.               172800  IN      NS      dns.progtech.net.
;; Received 111 bytes from 192.33.14.30#53(192.33.14.30) in 623 ms

www.ciao.com.           86400   IN      A       185.60.164.38
ciao.com.               86400   IN      NS      dns2.progtech.net.
ciao.com.               86400   IN      NS      dns.progtech.net.
;; Received 127 bytes from 80.190.149.57#53(80.190.149.57) in 82 ms

Per completezza, riporto il contenuto di una risposta ad una quey DNS, con le relative sezioni (QUERY, ANSWER, AUTHORITY, ADDITIONAL)

[root@linuxbox ~]# dig libero.it

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.2 <<>> libero.it
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23298
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;libero.it.                     IN      A

;; ANSWER SECTION:
libero.it.              300     IN      A       37.9.239.32

;; AUTHORITY SECTION:
libero.it.              10799   IN      NS      n2.libero.it.
libero.it.              10799   IN      NS      n1.libero.it.

;; ADDITIONAL SECTION:
n2.libero.it.           10799   IN      A       156.154.67.47
n1.libero.it.           10799   IN      A       156.154.66.47

;; Query time: 256 msec
;; SERVER: 10.1.1.1#53(10.1.1.1)
;; WHEN: Tue May 31 09:29:06 2016
;; MSG SIZE  rcvd: 109

essa ci tornerà utile quando vedremo più nel dettaglio la logica su cui si basa il DNS cache poisoning.

DNS Spoofing a fin di bene

Facendo una rapida ricerca su Google si evince che il DNS Spoofing è una tecnica di cracking che rientra nella categoria MITM (Man in The Middle), tramite la quale “si fa credere” al PC della vittima che il sito X (ad esempio www.facebook.com) risponde all’indirizzo IP della macchina dell’aggressore (ad esempio 192.168.1.5). Se oltre a ciò sulla macchina dell’aggressore è presente anche una replica della home di facebook (ottenuta, ad esempio, mediante wget), le credenziali della vittima potranno essere facilmente individuate, a meno di messaggi HSTS (connessione non sicura/sito non attendibile) e di utenti più smaliziati (assenza del “lucchetto” di fianco alla barra degli indirizzi del browser).

Essa può essere realizzata seguendo 2 alternative: l’inserimento di record ad hoc all’interno del file hosts della macchina vittima oppure modificando il suo nameserver primario (dalle impostazioni di rete). In quest’ultimo caso parliamo di DNS Hijacking.

dnsspoofing

Dopo questa breve premessa è comunque utile fare una precisazione: il DNS Spoofing non è sempre sinonimo di cracking. Infatti, basti pensare al caso in cui l’ISP decide di “bloccare” l’accesso ad un sito per via dei suoi contenuti, agendo direttamente sui propri nameserver in modo da creare una mappatura statica indirizzo IP/FQDN che rimanda ad una pagina Web specifica, in cui viene notificato all’utente il blocco in atto (con eventuale registrazione degli indirizzi delle macchine che tentano di accedervi).

Un altro caso di utilizzo “bonario” della tecnica in questione riguarda il “blocco” di domini che veicolano notoriamente spyware, adaware e malware di ogni tipo. In questo post vi mostrerò come configurare il nameserver locale (realizzato grazie a dnsmasq, vedi qui per ulteriori dettagli) in modo da ottenere il blocco dei suddetti domini, semplicemente facendoli puntare a 127.0.0.1 (localhost).

Occorre precisare, inoltre, che tale tecnica funziona solo ed esclusivamente nel caso in cui gli utenti non abbiano privilegi di amministrazione sulle loro macchine e che quindi non siano in grado di modificare le impostazioni delle schede di rete (lasciando come nameserver primario quello da noi configurato). In aggiunta, la manutenibilità dei siti da bloccare è di gran lunga superiore rispetto a quella offerta dai blocchi mediante file hosts di ciascuna macchina (poichè, nel primo caso, si ha a disposizione una lista “centralizzata” di domini malevoli).

Ma passiamo alla configurazione vera e propria di dnsmasq. I domini che intendiamo bloccare sono i seguenti:

doubleclick.net
scorecardresearch.com
criteo.com
imrworldwide.com

per cui le direttive da aggiungere a dnsmasq saranno le seguenti:

address=/doubleclick.net/127.0.0.1
address=/scorecardresearch.com/127.0.0.1
address=/criteo.com/127.0.0.1
address=/imrworldwide.com/127.0.0.1

da notare che verranno bloccati non solo i suddetti domini, ma anche tutti gli eventuali sottodomini ad essi riconducibili.

Riavviamo dnsmasq:

root@ubuntubox:~# service dnsmasq restart

e testiamo il funzionamento del blocco appena configurato, pingando uno dei domini che intendiamo “dirottare” su localhost:

root@ubuntubox:~# ping criteo.com
PING criteo.com (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_req=1 ttl=64 time=0.035 ms
64 bytes from localhost (127.0.0.1): icmp_req=2 ttl=64 time=0.037 ms
64 bytes from localhost (127.0.0.1): icmp_req=3 ttl=64 time=0.036 ms

ed anche qualche sottodominio:

root@ubuntubox:~# ping pippo.criteo.com
PING pippo.criteo.com (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_req=1 ttl=64 time=0.033 ms
64 bytes from localhost (127.0.0.1): icmp_req=2 ttl=64 time=0.051 ms
64 bytes from localhost (127.0.0.1): icmp_req=3 ttl=64 time=0.040 ms
64 bytes from localhost (127.0.0.1): icmp_req=4 ttl=64 time=0.039 ms

Infine, diamo una ripulita ai PC degli utenti utilizzando software specifici quali Malwarebytes (in modo da eliminare il problema alla radice), continuando anche a monitorare le hit del proxy alla ricerca di eventuali domini “sospetti”.

Alla prossima.

PS: tale tecnica, a mio avviso, è più performante (ma meno malleabile) rispetto al blocco realizzato mediante l’uso di un proxy (ad esempio squid + squidguard), poichè agendo direttamente sul meccanismo di risoluzione dei nomi, si crea meno overhead e si ottengono tempi di risposta molto più ridotti.

dnsmasq ed Ubuntu: configurare un server DNS/DHCP per ambienti SOHO

Premesso che per mettere in piedi un nameserver locale si possono utilizzare diverse soluzioni open source, anche di tipo enterprise (una su tutte è rappresentata da bind/named), ho deciso di installare dnsmasq su un server Ubuntu per 2 motivi:

1) la rete aveva dimensioni estremamente ridotte (un server, qualche workstation e 3 stampanti), quindi rientrava nell’ambito delle infrastrutture SOHO (Small Office Home Office);

2) vi era la necessità di tirar su anche un servizio di DHCP, configurabile direttamente sull’applicativo in questione (che quindi può svolgere, contemporaneamente, sia il ruolo di nameserver che quello di DHCP server).

dnsmasq

Configurazione del DHCP server

Fare in modo che dnsmasq svolga le funzioni tipiche di un server DHCP è un’operazione abbastanza banale. Infatti, è sufficiente editare la configurazione del demone in questione (operando sul file /etc/dnsmasq.conf), aggiungendo le seguenti direttive:

no-dhcp-interface=eth1

dhcp-range=eth1,192.168.0.100,192.168.0.199,8h

In particolare, ho messo in ascolto il server DHCP sulla sola interfaccia eth0 (dato che si tratta di una macchina dual homed, in cui la scheda eth1 è collegata ad Internet mediante uno screened router). Inoltre, ho definito il pool di indirizzi che possono assere assegnati ai client che ne fanno richiesta, con relativo lease time (8h).

Configurazione del nameserver

Tale configurazione è un po’ più complessa rispetto alla precedente ma risulta comunque abbordabile.

Diciamo che dnsmasq è un nameserver “giocattolo”, in cui molti record DNS devono essere definiti all’interno di un file “piatto”, quale, ad esempio, /etc/hosts (anche se è possibile definire un file ad hoc per tale scopo), senza che vi sia quindi la necessità di creare una specifica zona DNS (cosa che invece risulta essere mandatoria con altri nameserver “un po’ più seri”).

I record di tipo A presenti nel file /etc/hosts avevano un formato simile al seguente:

192.168.0.2     proxy
192.168.0.4     server1
192.168.0.5     PC1
192.168.0.6     stampante1
192.168.0.7     stampante2
192.168.0.9     stampante3
192.168.0.10    PC2

Per quanto riguarda, invece, la configurazione del servizio DNS, ho abilitato le seguenti direttive (all’interno del file /etc/dnsmasq.conf):

interface=eth0
except-interface=eth1
listen-address=192.168.0.2

expand-hosts

domain=soho.loc

Le prime 3 servono a mettere in ascolto il server solo ed esclusivamente sull’interfaccia rivolta verso la LAN. Con expand-hosts e domain=soho.loc, invece,  ho fatto in modo che le query DNS vadano a buon fine anche nel caso in cui venga fornito il solo hostname della macchina di cui si vuole conoscere l’indirizzo IP.

Poichè il suddetto nameserver deve risolvere solo ed esclusivamente gli indirizzi locali, ho dovuto definire i forwarder (o nameserver di upstream) a cui inviare le query per tutte le zone DNS pubbliche. La direttive che ho utilizzato sono le seguenti:

resolv-file=/etc/resolv.dnsmasq
strict-order

dove il contenuto del file /etc/resolv.dnsmasq era il seguente:

nameserver 8.8.8.8
nameserver 208.67.222.222
nameserver 8.8.4.4
nameserver 208.67.220.220

La direttiva strict-order faceva in modo che i forwarder venissero contattati seguendo  l’ordine con cui sono stati definiti all’interno del suddetto file (il secondo nameserver viene contattato solo nel caso in cui il primo non sia raggiungibile, ergo, per ottenere una maggiore ridondanza, ho deciso di alternare ai nameserver di Google quelli di OpenDNS).

Per avere un maggiore controllo sulle query inoltrate al nameserver locale, ho deciso di loggarle su un apposito file di testo grazie ai seguenti parametri di configurazione:

log-queries
log-facility=/var/log/dnsmasq/query.log

Ho anche configurato la rotazione dei log mediante il file dnsmasq posto all’interno della directory /etc/logrotate.d:

/var/log/dnsmasq/query.log {
        rotate 7
        weekly
        compress
        missingok
        notifempty
}

Infine, affinchè i client della LAN riuscissero a “riconoscere” i record DNSSEC (garantendo loro una maggiore sicurezza durante la navigazione su Internet), ho fatto in modo che dnsmasq girasse le query DNSSEC ai forwarder (demandando loro il ruolo di validator).

La direttiva che mi ha consentito di fare ciò è la seguente:

proxy-dnssec

Il fatto che il nameserver primario di Google (8.8.8.8) sia il primo della lista dei forwarder non è certamente un caso. Infatti, esso garantisce dei tempi di risposta più brevi rispetto a quelli di OpenDNS, oltre ad essere anche DNSSEC compliant (cosa che OpenDNS non è).

In definitiva, la configurazione di dnsmasq (in base alle mie esigenze) si è rivelata essere la seguente:

no-dhcp-interface=eth1

dhcp-range=eth1,192.168.0.100,192.168.0.199,8h

interface=eth0
except-interface=eth1
listen-address=192.168.0.2

expand-hosts

domain=soho.loc

resolv-file=/etc/resolv.dnsmasq
strict-order

log-queries
log-facility=/var/log/dnsmasq/query.log

proxy-dnssec

Dopo aver effettuato un controllo sintattico della suddetta configurazione mediante il comando:

root@ubuntubox:~# dnsmasq --test

ed aver riavviato il demone:

root@ubuntubox:~# service dnsmasq restart

sono passato ai test funzionali mediante dig. Per prima cosa ho effettuato una query di tipo A per il record proxy, utilizzando dapprima il solo hostname:

root@fw-scar:~# dig @localhost proxy

; <<>> DiG 9.8.1-P1 <<>> @localhost proxy
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3216
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;proxy.                         IN      A

;; ANSWER SECTION:
proxy.                  0       IN      A       192.168.0.2

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri May 20 15:50:11 2016
;; MSG SIZE  rcvd: 39

e successivamente l’intero FQDN:

 root@fw-scar:~# dig @localhost proxy.soho.loc

; <<>> DiG 9.8.1-P1 <<>> @localhost proxy.soho.loc
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30251
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;proxy.soho.loc.                        IN      A

;; ANSWER SECTION:
proxy.soho.loc.         0       IN      A       192.168.0.2

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri May 20 15:52:15 2016
;; MSG SIZE  rcvd: 48

Successivamente mi sono concentrato sui tempi di risposta per i domini pubblici (da parte dei forwarder), ottenendo i seguenti tempi pre-cashing:

root@fw-scar:~# dig @localhost repubblica.it | grep "Query time"
;; Query time: 50 msec

e post caching:

root@fw-scar:~# dig @localhost repubblica.it | grep "Query time"
;; Query time: 0 msec

Infine, ho testato la risoluzione dei record DNSSEC, utilizzando il comando:

root@fw-scar:~# dig @localhost pir.org +dnssec +multi

; <<>> DiG 9.8.1-P1 <<>> @localhost pir.org +dnssec +multi
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35285
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;pir.org.               IN A

;; ANSWER SECTION:
pir.org.                299 IN A 97.107.141.235
pir.org.                299 IN RRSIG A 5 2 300 20160602204000 (
                                20160519204000 58424 pir.org.
                                cJwr7HlIMA+DyQ8vqqmkNtHRAqsGVdKWTQkJeP/a5698
                                UTyK/cF08uYhH8xMk9I0RMWqtkJDM8od8hWmYUZgidzi
                                7Fh26m1FQYGAcN/PMw2/6wEnNh4ErWZtXe2fXRAS8btx
                                I+nyRPOCoAHR3CjC0cjKqtniUoWHt5x/51iEBw4= )

;; Query time: 86 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri May 20 15:57:36 2016
;; MSG SIZE  rcvd: 219

ricevendo come risposta sia il record A che il relativo RRSIG.

Alla fine della fiera ho messo in piedi un server DNS/DHCP funzionante e funzionale.

Alla prossima.