Archivi tag: acl

Traffico TCP sulla porta 0

Qualche giorno fa Nagios mi ha segnalato un allarme di sicurezza che mi ha lasciato alquato basito:

When a syslog message is generated by the device a SEC info IPACCESSLOGP list 102 denied tcp 77.223.136.170(0) - 95.245.162.62(0), 1 packet 9:5:46:40.62

In soldoni, l’ACL attiva sull’interfaccia dialer (WAN) del mio router ha “scartato” un segmento TCP proveniente dall’IP 77.223.136.170 (porta 0) e diretto al mio (vecchio) IP pubblico (ovvero 95.245.162.62, porta 0).

Ora, è sufficiente avere un minimo di dimestichezza con lo stack TCP/IP per capire che l’anomalia sta proprio nella porta sorgente ed in quella di destinazione. Infatti, la porta 0 è riservata ed il suo impiego può avvenire per i motivi (leciti) più disparati.

Ad esempio, nel caso in cui il pacchetto IP (formato da header + payload) superi la MTU del link che deve attraversare, esso subirà un processo specifico, denominato “frammentazione”.

In particolare, essendo l’header TCP parte del payload IP (per via dell’incapsulamento – vedi immagine sottostante), ciascun frammento potrebbe contenere la suddetta intestazione per intero o solo parzialmente. Nel primo caso, l’header TCP originario si troverebbe soltanto nel primo frammento, mentre tutti gli altri conterrebbero la sola intestazione IP (dotata di ID specifico del frammento, offset per la ricostruzione del traffico in fase di ricezione – dimensione e bit MFMore Fragment – pari a 0 o 1 a seconda che si tratti dell’ultimo frammento o meno).

encaps

Più in generale, la porta TCP/UDP pari a 0 potrebbe stare a significare, molto semplicemente, assenza di layer 4 (basti pensare al protocollo ICMP).

Per quanto riguarda, invece, l’uso malevolo della porta 0, possiamo distinguere 3 macro-tipologie di casi:

1) Attacchi di tipo fingerprint. Essi si basano sul presupposto che spesso e volentieri le ACL non possono essere definite in modo tale da droppare esplicitamente il traffico in ingresso sulla porta 0 (TCP o UDP), ergo puntare ad essa è un modo abbastanza efficace (ma non infallibile) per ottenere info sulla tipologia di router oggetto di interesse (OS fingerprint – leggete questo per ulteriori dettagli);

2) Attacchi volti ad “aggirare” le ACL. Ad esempio, forzando la frammentazione del pacchetto IP ed agendo sul campo offset,  si potrebbe riuscire, in teoria, a sovrascrivere parte dell’intestazione TCP originaria (che punta ad una porta di destinazione “lecitamente” raggiungibile dall’esterno, come potrebbe essere la 25 per il protocollo SMTP) con una porta non accessibile dall’esterno (ad esempio la 23 per il protocollo Telnet). Per ulteriori dettagli su tale tipologia di attacco (denominato tiny overlapping fragment attack) leggete questo.

3) Attacchi di tipo DoS/DDoS. Forzando la frammentazione dei pacchetti IP sottostanti al layer 4 (TCP/UDP) si potrebbe riuscire a “sovraccaricare” il router di destinazione, soprattutto per via dell’overhead dovuto all’attività di “ricostruzione” del traffico. Inoltre, puntando ad una porta non lecita, ad esempio la 0, lo si costringerebbe ad inviare dei messaggi ICMP Port Unreachable (se abilitati sull’interfaccia), sovraccaricandolo ulteriormente.

Della casistica appena illustrata credo che l’allarme ricada, molto banalmente, negli attacchi di tipo fingerprint. Ovviamente ho alzato il livello di attenzione per evitare “brutte” sorprese in futuro.

Vi terrò comunque aggiornati.

Aggiornamento 1

A quanto pare si è trattato proprio di un portscan/fingerprint. Infatti, dopo circa 5 giorni dallo scan sulla porta TCP 0, ho registrato il seguente traffico:

Jan 25 15:29:15 192.168.2.1 1738: 001735: Jan 25 15:29:14.483 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 77.223.136.170(443) -> 79.31.118.x(43616), 1 packet
Jan 25 15:29:17 192.168.2.1 1739: 001736: Jan 25 15:29:15.988 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(256) -> 79.31.118.x(43617), 1 packet
Jan 25 15:29:18 192.168.2.1 1740: 001737: Jan 25 15:29:17.200 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(111) -> 79.31.118.x(43617), 1 packet
Jan 25 15:29:19 192.168.2.1 1741: 001738: Jan 25 15:29:18.204 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 77.223.136.170(1106) -> 79.31.118.x(43616), 1 packet
Jan 25 15:29:20 192.168.2.1 1742: 001739: Jan 25 15:29:19.204 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(700) -> 79.31.118.x(43617), 1 packet
Jan 25 15:29:20 192.168.2.1 1743: 001740: Jan 25 15:29:20.208 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 77.223.136.170(3493) -> 79.31.118.x(43616), 1 packet
Jan 25 15:29:22 192.168.2.1 1744: 001741: Jan 25 15:29:21.213 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(726) -> 79.31.118.x(43617), 1 packet
Jan 25 15:29:24 192.168.2.1 1746: 001743: Jan 25 15:29:23.365 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(777) -> 79.31.118.x(43618), 1 packet
Jan 25 15:29:26 192.168.2.1 1747: 001744: Jan 25 15:29:25.046 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 77.223.136.170(111) -> 79.31.118.x(43618), 1 packet

Aggiornamento 2

In data 26 Gennaio ho ricevuto un altro pacchetto da/verso la suddetta porta:

When a syslog message is generated by the device a SEC info IPACCESSLOGP list 101 denied tcp 23.236.147.202(0) - 79.31.118.x(0), 1 packet 0:14:52:02.45

Vediamo se tra qualche giorno il nuovo IP sorgente utilizzerà lo stesso ordine di port probing del suo predecessore.

Aggiornamento 3

Come volevasi dimostrare, a distanza di qualche ora è arrivato il port probing vero e proprio:

Jan 27 18:36:33 192.168.2.1 19380: 019433: Jan 27 18:36:32.479 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 23.236.147.202(139) -> 79.31.118.x(46096), 1 packet
Jan 27 18:36:35 192.168.2.1 19381: 019434: Jan 27 18:36:34.475 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 23.236.147.202(1002) -> 79.31.118.x(46097), 1 packet
Jan 27 18:36:36 192.168.2.1 19382: 019435: Jan 27 18:36:35.500 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 23.236.147.202(2701) -> 79.31.118.x(46095), 1 packet
Jan 27 18:36:36 192.168.2.1 19383: 019436: Jan 27 18:36:36.500 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 23.236.147.202(11967) -> 79.31.118.x(46095), 1 packet
Jan 27 18:36:38 192.168.2.1 19384: 019437: Jan 27 18:36:37.552 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 23.236.147.202(1494) -> 79.31.118.x(46095), 1 packet
Jan 27 18:36:39 192.168.2.1 19385: 019438: Jan 27 18:36:38.556 UTC: %SEC-6-IPACCESSLOGP: list 101 permitted tcp 23.236.147.202(8021) -> 79.31.118.x(46095), 1 packet
Jan 27 18:36:43 192.168.2.1 19387: 019440: Jan 27 18:36:42.353 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 23.236.147.202(139) -> 79.31.118.x(46097), 1 packet
Jan 27 18:36:48 192.168.2.1 19388: 019441: Jan 27 18:36:47.154 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 23.236.147.202(139) -> 79.31.118.x(46095), 1 packet

Anche in questo caso le porte oggetto dell’attacco sono quelle > 1023. Ho quindi fatto qualche modifica all’ACL configurata sulla dia0 del mio router, sostituendo la regola:

access-list 101 permit tcp any gt 1023 any log

con:

access-list 101 permit tcp any gt 1023 any established log

in modo tale da consentire il traffico proveniente dalle porte > 1023 solo se si riferiscono a delle connessioni già esistenti.

Aggiornamento 4

Sono riuscito a ricreare parzialmente la suddetta tipologia di traffico, utilizzando un apposito tool denominato hping, il quale è in grado di forgiare dei pacchetti RAW/TCP/UDP/ICMP da impiegare durante le operazioni di OS fingerprint e non solo.

Ad esempio, mediante il comando:

[root@linuxbox ~]# hping3 -S -V <mio indirizzo IP>

sono riuscito a generare una sfilza di pacchetti TCP recanti i classici 40 byte di header, payload 0 e flag SYN settata a 1, la cui destinazione proprio è la famigerata porta 0.

Di seguito riporto il tracciato tcpdump da locale (grazie al quale si può notare che la porta sorgente è una porta alta, ovvero maggiore di 1023, e che la porta di destinazione è sempre la 0):

09:41:14.967184 IP 192.168.1.1.1232 > 79.31.118.x.0: Flags [S], seq 2094000106, win 512, length 0
09:41:15.967305 IP 192.168.1.1.1233 > 79.31.118.x.0: Flags [S], seq 517260399, win 512, length 0
09:41:16.967425 IP 192.168.1.1.1234 > 79.31.118.x.0: Flags [S], seq 399923675, win 512, length 0
09:41:17.967477 IP 192.168.1.1.1235 > 79.31.118.x.0: Flags [S], seq 725026004, win 512, length 0
09:41:18.967573 IP 192.168.1.1.rmtcfg > 79.31.118.x.0: Flags [S], seq 1830159741, win 512, length 0
09:41:19.967638 IP 192.168.1.1.1237 > 79.31.118.x.0: Flags [S], seq 342672970, win 512, length 0

Mentre il log generato dal mio router è il seguente:

Apr  3 09:39:35 192.168.2.1 108805: 108943: Apr  3 08:39:34.979 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1232) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:37 192.168.2.1 108807: 108945: Apr  3 08:39:36.979 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1233) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:39 192.168.2.1 108808: 108946: Apr  3 08:39:38.980 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1234) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:41 192.168.2.1 108809: 108947: Apr  3 08:39:40.980 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1235) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:43 192.168.2.1 108810: 108948: Apr  3 08:39:42.981 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1236) -> 79.31.118.x(0), 1 packet
Apr  3 09:39:45 192.168.2.1 108811: 108949: Apr  3 08:39:44.977 UTC: %SEC-6-IPACCESSLOGP: list 101 denied tcp 95.254.89.x(1237) -> 79.31.118.x(0), 1 packet

Invece, forzando a 0 la porta sorgente del suddetto traffico (e mantenendola tale per tutta la durata del test – opzione -k) attraverso il comando:

[root@linuxbox ~]# hping3 -S -VV -s 0 -k <mio indirizzo IP>

sono riuscito ad intercettarlo localmente come dimostrato dal seguente tracciato:

10:32:21.495218 IP 192.168.1.1.0 > 79.31.118.x.0: Flags [S], seq 1600061111, win 512, length 0
10:32:22.495334 IP 192.168.1.1.0 > 79.31.118.x.0: Flags [S], seq 965785080, win 512, length 0
10:32:23.495411 IP 192.168.1.1.0 > 79.31.118.x.0: Flags [S], seq 677172521, win 512, length 0
10:32:24.495492 IP 192.168.1.1.0 > 79.31.118.x.0: Flags [S], seq 473418678, win 512, length 0

ma è stato successivamente scartato dal router sorgente, ergo non è mai giunto a destinazione.

Nei prossimi giorni proverò a ripetere il test utilizzando il router di un vendor differente.

CentOS 6: monitorare le ACL del nostro router Cisco mediante Nagios ed snmptt

Durante gli ultimi mesi ho discusso ampiamente della configurazione di Nagios per la ricezione dei check passivi, quali trap SNMP o security alert. Adesso vi mostrerò come integrare le predette tipologie di allarmi in modo da riuscire a monitorare le ACL del nostro router Cisco.

Premessa

Esiste un modo più veloce per ottenere il monitoraggio delle ACL rispetto a quello che sto per illustrare. Esso consiste, fondamentalmente, nella configurazione di un syslog server (dotato dell’applicativo swatch per l’analisi in tempo reale dei file di log) a cui il nostro router Cisco dovrà puntare. Nel caso in cui un determinato pattern (ad esempio / denied /) dovesse essere matchato da swatch, quest’ultimo genererà un’opportuna notifica email da inoltrare all’amministratore di rete.

La mia configurazione, invece, si basa sulla logica seguente: il router Cisco genererà delle opportune trap SNMP segnalando ciò che avviene a livello di ACL (traffico consentito oppure negato). Esse verranno intercettate da snmptrapd e tradotte da snmptt, per poi essere elaborate dall’event handler submit_check_result e date in pasto a Nagios. Ho optato per tale configurazione poichè sulla mia linux box che funge da syslog server e da NMS sono già attivi sia snmptrapd che snmptt e quindi ho ritenuto conveniente sfruttarli piuttosto che mettere in funzione swatch.

nagiosConfigurazione del router Cisco

La configurazione del router Cisco si basa in 3 passaggi: settaggio della direttiva log per ciascuna entry che andrà a formare l’ACL da monitorare,  settaggio del syslog server a cui inviare le trap ed abilitazione di queste ultime.

Ad esempio, l’ACL di nostro interesse dovrà essere formata da entry di questo tipo:

access-list 102 deny ip host 255.255.255.255 any log

Inoltre, per definire la community string RO (read only) e l’indirizzo IP del server che si occuperà della ricezione delle trap, occorrerà digitare le seguenti direttive:

snmp-server host 192.168.1.1 keypublic
snmp-server community keypublic RO

mentre le trap potranno essere abilitate nel modo seguente:

snmp-server enable traps snmp authentication linkdown linkup coldstart warmstart
snmp-server enable traps tty
snmp-server enable traps config-copy
snmp-server enable traps config
snmp-server enable traps resource-policy
snmp-server enable traps cpu threshold
snmp-server enable traps syslog
snmp-server enable traps firewall serverstatus

 Contenuto dello scrip submit_check_result

Secondo quanto già riportato in questo post, sappiamo che snmptt effettua una traduzione “statica” delle trap (mediante il comando snmpttconvertmib). Per tale motivo, affinchè si possa indurre Nagios a generare dei security alert solo dopo la ricezione di trap ben determinate, occorre modificare il codice sorgente relativo all’event handler submit_check_result. Di seguito riporto il contenuto dello scrip in questione da me customizzato:

 echocmd="/bin/echo"

CommandFile="/var/spool/nagios/cmd/nagios.cmd"

# get the current date/time in seconds since UNIX epoch
datetime=`date +%s`

# create the command line to add to the command file
if [[ $1 == "ip router" ]];then

        if [[ $4 =~ "denied igmp" ]];then

                exit 0;

        elif  [[ $4 =~ "denied" ]];then

                service="Router ACL Connection Denied";

                output="$4 | connection_denied=1"
                cmdline="[$datetime] PROCESS_SERVICE_CHECK_RESULT;router;$service;$3;$output";

        else

                cmdline="[$datetime] PROCESS_SERVICE_CHECK_RESULT;router;$2;$3;$4";

        fi

else

   cmdline="[$datetime] PROCESS_SERVICE_CHECK_RESULT;$1;$2;$3;$4";

fi

# append the command to the end of the command file
`$echocmd $cmdline >> $CommandFile`

Nella fattispecie, vengono dapprima identificate le trap che riguardano il router. Successivamente, nel caso in cui esse contengano il pattern igmp denied, lo scrip uscirà senza effettuare alcuna operazione. Tale “scrematura” è stata necessaria poichè il mio ISP effettua regolarmente del polling IGMP mediante il proprio querier 192.168.100.1 (per il servizio IPTV).

Nel caso in cui, invece, le trap dovessero contenere la stringa denied, la variabile cmdline verrà popolata con l’host name dell’oggetto monitorato da Nagios (per il quale si dovrà aggiornare lo stato del servizio che si occupa di tenere d’occhio le ACL). Nel mio caso tale host name è semplicemente router. Inoltre, l’output  verrà rimaneggiato in modo da tenere traccia delle performance data (graficizzandole mediante l’uso di pnp4nagios).

MIB da utilizzare e configurazione di Nagios

Per prima cosa occorre scaricare le MIB CISCO-SYSLOG-MIB e CISCO-SYSLOG-MIB-V1SMI dal repository FTP della Cisco, effettuandone il parsing mediante snmpttconvertmib.

Successivamente, su Nagios occorrerà definire per l’host name router il servizio che si occuperà di monitorare le ACL:

define service{
        use                             local-service
        host_name                       router
        service_descripion              Router ACL Connection Denied
        check_command                   check_passive
        passive_checks_enabled          1
        active_checks_enabled           0
        max_check_attempts              1
        is_volatile                     1
        check_freshness                 1
        freshness_threshold             600
        flap_detection_enabled          0
        }

Come ultimo step, a configurazione ultimata possiamo riavviare Nagios per rendere effettive le suddette modifiche:

[root@NMS ~]# service nagios reload

ed abbiamo finito.

A presto.

Modifica delle ACL NTFS mediante PowerShell

Scenario

Una macchina con a bordo Windows Server 2008 R2 che funge da Web server (IIS7). Si vuole fare in modo che gli utenti possano effettuare l’upload (mediante un form opportunamente creato) di immagini e file di vario genere.

Problema

Le ACL NTFS relative alla root directory di IIS (ovvero C:\inetpub\wwwroot) non consentono le operazioni di modifica agli utenti Web anonimi (appartenenti al gruppo IIS_IUSRS), ergo qualsiasi tentativo di upload avrà esito negativo. Inoltre, l’alberatura delle sottodirectory è abbastanza complessa ed è qualcosa del tipo /nomesubdir/immagini, in cui nomesubdir è variabile (ce ne sono circa un migliaio), mentre immagini è la dir di destinazione degli upload (sulla quale bisogna garantire i permessi di modifica).

Soluzione

La prima soluzione che viene in mente prevede per lo più tanta pazienza ed un lavoro certosino da attuare, fondamentalmente, in 2 passaggi: l’accesso manuale a ciascuna subdir e la modifica delle ACL NTFS per la directory immagini ivi contenuta.

La seconda soluzione è certamente più rapida e smart: creare uno scrip PowerShell in grado di modificare le suddette ACL per tutte le directory immagini poste all’interno delle subdir.

powershellEcco lo scrip:

$Acl = Get-Acl "C:\inetpub\wwwroot\*\immagini"
$Ar = New-Object  system.security.accesscontrol.filesystemaccessrule("IIS_IUSRS","Modify","ContainerInherit, ObjectInherit", "None","Allow")
foreach($Ac in $Acl)
{
    $Ac.SetAccessRule($Ar)
    Set-Acl "C:\inetpub\wwwroot\*\immagini" $Ac
}

Esso prevede, in soldoni, 2 fasi: la prima in cui vengono identificati i permessi relativi alla directory immagini presente in ciascuna subdir  (mediante la cmdlet Get-Acl); la seconda in vengono definiti i nuovi permessi per il gruppo IIS_IUSRS, applicandoli a tutte le  immagini (ed ai file in esse contenuti).

Rollback

Naturalmente la modifica dei permessi NTFS associati a file e cartelle è sempre un’operazione abbastanza invasiva e delicata, ergo è opportuno garantirsi la possibilità di ripristinare la situazione iniziale (ovvero quella precedente alle suddette modifiche).

Ecco lo scrip in grado di effettuare il rollback dei permessi:

$Acl = Get-Acl "C:\inetpub\wwwroot\*\immagini"
$Ar = New-Object  system.security.accesscontrol.filesystemaccessrule("IIS_IUSRS","Modify","ContainerInherit, ObjectInherit", "None","Allow")
foreach($Ac in $Acl)
{
    $Ac.RemoveAccessRuleAll($Ar)
    Set-Acl "C:\inetpub\wwwroot\*\immagini" $Ac
}

La logica è sempre la stessa, l’unica variazione riguarda la funzione RemoveAccessRuleAll($Ar) che ha sostituito la SetAccessRule($Ar) utilizzata in precedenza.

Alla prossima.

Cisco 2811: utilizzare le route-map per creare delle regole di destination NAT basate su IP sorgente

Scenario

Supponiamo che si abbia a che fare con un ufficio centrale (main office) a cui sono collegati N uffici periferici (branch office) tramite dei tunnel VPN IPsec Site-to-Site dedicati (che concorrono a formare la classica topologia a stella). Supponiamo, inoltre, che i suddetti uffici periferici, per questioni di failover, debbano essere in grado di raggiungere i servizi presenti nell’ufficio centrale anche nel caso in cui i tunnel VPN non siano disponibili (passando quindi  direttamente per Internet).

vpn-ipsec1Utilizzando delle regole di destination NAT classiche, del tipo:

ip nat inside source static tcp 192.168.2.4 80 interface fastethernet0/0 80

(dove 192.168.4.2 è l’IP locale del server Web esposto su Internet), i branch office non saranno in grado di raggiungere il server in questione tramite il tunnel VPN (utilizzando il protocollo HTTP).

Ergo, il fatto che un determinato servizio sia pubblicato su Internet, implica automaticamente l’impossibilità di raggiungerlo anche tramite il tunnel VPN.

Per ovviare a tale problematica esistono 2 soluzioni: la prima, meno impegnativa (ma che richiede la modifica della URL lato client in caso di failover), consiste nel modificare la configurazione del server in modo tale che rimanga in ascolto su 2 porte distinte, ad esempio la TCP 80 per Internet e la TCP 81 per la VPN;  la seconda, più impegnativa (ma anche molto più scalabile), consiste nel creare sul nostro router Cisco 2811 (main office) delle route-map (che si avvalgono di opportune ACL) in grado di filtrare gli indirizzi IP sorgenti dei client che vogliono collegarsi al server Web. In questo modo, se la richiesta di connessione proviene da un determinato IP privato tipico di una VPN Site-to-Site (ad esempio 192.168.3.1), per essa non viene applicato il destination NAT; viceversa, nel caso in cui la richiesta di connessione provenga da Internet, verrà applicato il destination NAT come di consueto.

Ho definito la seconda soluzione come la più scalabile delle 2 per un semplice motivo: impostando la route-map sul router del main office e modificando sul nameserver locale il record di tipo A che punta all’IP del server Web, si può fare in modo che quest’ultimo possa essere contattato tramite tunnel VPN o tramite Internet a seconda dei casi senza dover modificare la URL lato browser (passando, ad esempio, da http://www.vostrodominio.com a http://www.vostrodominio.com:81).

Vediamo adesso come mettere in pratica la soluzione #2.

Configurazione del router Cisco 2811 (main office)

Per prima cosa occorre creare l’ACL in grado di “riconoscere” gli IP locali e di negare il destination NAT:

Router(config)# access-list 150 deny ip host 192.168.2.4 192.168.3.0 0.0.0.255
Router(config)# access-list 150 deny ip host 192.168.2.4 192.168.4.0 0.0.0.255
Router(config)# access-list 150 deny ip host 192.168.2.4 192.168.5.0 0.0.0.255
Router(config)# access-list 150 deny ip host 192.168.2.4 192.168.6.0 0.0.0.255
Router(config)# access-list 150 permit ip host 192.168.2.4 any

Successivamente creiamo la route-map vera e propria:

Router(config)# route-map nonat
Router(config-route-map)# match ip address 150

dove 150 è il numero dell’ACL estesa precedentemente definita.

Infine, associamo la route-map appena creata alla regola di destination NAT:

Router(config)# ip nat inside source static tcp 192.168.2.4 <IP Pubblico> 80 route-map nonat extendable

Ovviamente, affinchè la suddetta soluzione sia realmente scalabile, è necessario che il vostro collegamento ad Internet sia dotato di indirizzo IP pubblico statico.

Salviamo adesso la configurazione del nostro router:

Router# copy run start

e passiamo al vaglio alcune soluzioni alternative alle route-map.

1) Utilizzo dei record DNS di tipo SRV (vedi qui per ulteriori dettagli). Essi ci consentono non solo di specificare il protocollo di comunicazione ma anche la porta su cui è in ascolto il server, definendo una priorità per ciascuna entry che li compone:

_http._tcp.vostrodominio.com. 86400 IN SRV 0 5 81 www.vostrodominio.com.
_http._tcp.vostrodominio.com. 86400 IN SRV 1 5 80 www1.vostrodominio.com.

dove 0 e 1 sono le priorità, 81 e 80 le porte su cui è in ascolto il server. In caso di timeout sulla porta 81 e l’IP di www (raggiungibile via VPN) il browser “dovrebbe” switchtare automaticamente sulla 80 e l’IP di www1. Ho utilizzato il condizionale poichè non tutti i broswer supportano tale meccanismo ed un workaround (applicato però solo da alcuni di essi), consiste nel definire record A con il medesimo hostname ma indirizzi IP differenti: nel caso in cui la connessione al primo IP della lista vada in timeout, il broswer tenterà automaticamente di connettersi al secondo IP (e così via).

2) Utilizzo di un firewall interno per filtrare le connessioni in uscita (outbound). ln questo caso, grazie ad esso, potremmo creare delle regole ad hoc (source NAT) per il mapping delle porte di destinazione, ad esempio (utilizzando iptables):

[root@firewall ~]# iptables -t nat -A OUTPUT -p tcp -d www.vostrodominio.com --dport 80 -j DNAT --to-destination www.vostrodominio.com:81

Anche in questo caso, prima di applicare la suddetta regola di firewalling, sarà necessario modificare sul nameserver il record A per l’hostname www.

E’ tutto. 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.

Traffico PPTP in uscita dai router Cisco

Il PPTP (Point to Point Tunnel Protocol) è uno dei protocolli utilizzati nell’ambito delle cosiddette VPN (Virtual Private Network). Esso venne introdotto dalla Microsfot e garantisce un certo livello di sicurezza, certamente molto inferiore a quello tipico delle VPN IPSec o SSL/TLS.

Site-to-site-pptp-example.jpg

Senza scendere troppo nel dettaglio è bene specificare che il protocollo PPTP non va per niente daccordo con il NAT/PAT. Per questo motivo, affinchè le connessioni in uscita dalla nostra LAN e dirette al server VPN remoto vadano a buon fine, è necessario implementare un meccanismo di PPTP Passthrough. In realtà, tale meccanismo si basa sull’EGRE (Enhanced Generic Routing Protocol), quindi quello che faremo sarà semplicemente consentire il traffico GRE in ingresso alla nostra LAN.

Inoltre, poichè tale connessione è di tipo punto-punto, il router non vedrà l’indirizzo IP sorgente relativo alla VPN, ergo non dovremo neppure modificare le regole dell’ACL che hanno come scopo il blocco del traffico proveniente da Internet e con indirizzi IP privati (spoofing).

Come al solito, bando alle ciance ed ecco la regola da inserire subito prima il deny ip any any (implicito) della nostra ACL:

access-list 102 permit gre any any log

Ebbene si, il GRE è un protocollo differente da quelli visti fin’ora (ad esempio IP, TCP o UDP), non prevede l’uso di porte ed è abbastanza intelligente da lavorare senza ulteriori configurazioni.

Una volta aggiunta tale regola sul nostro router Cisco sarà possibile atterrare tranquillamente sul VPN Concentrator, ricevere un indirizzo IP appartenente al pool privato e navigare tra le risorse di rete (ed eventualmente su Internet) come se si fosse connessi direttamente alla LAN dell’ufficio.

E’ tutto. Bye.

Installare MySQL da sorgenti

Chiunque abbia mai avuto a che fare con Linux conoscerà sicuramente i cosiddetti packet manager (yum, aptitude, emerge, ecc.). Utilizzandoli insistentemente si rischia di non sapere più come comportarsi nel caso in cui sia necessario installare una vecchia versione di un pacchetto software, oppure una versione beta dello stesso (non presente nei repositories).

 

My.jpg

La prima scelta, solitamente, ricade sui pacchetti precompilati per una specifica architettura hardware ed un sistema operativo ben determinato. Quando questi pacchetti non sono disponibili (a.k.a. Gentoo), è necessario scaricare i file sorgenti e compilare il tutto a manetta.

Dopo questa breve introduzione, vi mostrerò come installare MySQL 5.0.91 su Gentoo. Tale procedura vale per tutte le versioni di MySQL che necessitano di compilazione manuale. Ma bando alle ciance e veniamo al dunque.

Per prima cosa creiamo la directory in cui verrà installato il pacchetto in questione:

nightfly@nightbox:~$ mkdir /usr/local/mysql

Adesso, dopo aver scaricato mediante wget la tarball contenente i sorgenti di MySQL, possiamo procedere con la loro compilazione ed installazione:

 nightfly@nightbox:~$ tar -xvf mysql-5.0.91.tar.gz
 nightfly@nightbox:~$ cd mysql-5.0.91
 nightfly@nightbox:~$ ./configure --prefix=/usr/local/mysql
 nightfly@nightbox:~$ make
 nightfly@nightbox:~$ make install

Aggiungiamo l’utente mysql che useremo per avviare il demone e modifichiamo l’owner della directory target:

 nightfly@nightbox:~$ chown mysql:mysql /usr/local/mysql
 nightfly@nightbox:~$ cd /usr/local/mysql/bin

Installiamo i DB di default:

nightfly@nightbox:~$ ./mysql_install_db

Copiamo il file di configurazione di MySQL su /etc:

nightfly@nightbox:~$ cp /usr/local/mysql/share/mysql/my-medium.cnf  /etc
 nightfly@nightbox:~$ mv /etc/my-medium.cnf /etc/my.cnf

Copiamo gli eseguibili in /usr/local/sbin:

nightfly@nightbox:~$ cp /usr/local/mysql/bin /usr/local/sbin

Verifichiamo che la copia sia andata a buon fine:

nightfly@nightbox:~$ which mysql

Copiamo il demone in /etc/init.d e rinominiamolo in mysqld:

 nightfly@nightbox:~$ cp /usr/local/mysql/share/mysql/mysql.server /etc/init.d
 nightfly@nightbox:~$ cd /etc/init.d
 nightfly@nightbox:~$ mv mysql.server mysqld

Avviamo il demone e verifichiamo che sia attivo mediante un netstat ed un ps:

nightfly@nightbox:~$ /etc/init.d/mysqld start

nightfly@nightbox:~$ netstat -anp | grep :3306
nightfly@nightbox:~$ ps aux | grep mysqld

A questo punto possiamo definire la password per l’utente root digitando:

nightfly@nightbox:~$ mysqladmin -u root password <password>

L’ultima cosa da fare consiste nella definizione delle ACL di accesso ai DB. Un esempio di ACL è il seguente:

mysql> GRANT ALL ON *.* TO root IDENTIFIED BY 'rootpassword';

ovvero sto definendo il permesso (GRANT) di effettuare INSERT, UPDATE, DELETE e SELECT (ALL) su tutte le tabelle (*) di tutti i DB presenti (.*).

Come ultima verifica proviamo ad accedere a MySQL da locale e da remoto, lanciando il comando:

nightfly@nightbox:~$mysql -u root -prootpassword

(da locale);

nightfly@nightbox:~$mysql -h <hostname> -u root -prootpassword

(da remoto).

Se i tentativi di connessione vanno a buon fine vuol dire che il nostro DBMS è stato installato correttamente ed è pronto per l’uso.

A presto.

Spam bot sui server Web

Scenario

Due server Web in produzione, SO *nix e framework Drupal.

Problema

Una tonnellata di email dirette agli indirizzi di posta elettronica più disparati.

Premessa

Riassumendo, è proprio questo il problema che si è verificato nei giorni scorsi su alcuni server che gestisco. Ora, affinchè lo spam bot possa funzionare è indispensabile che sulla macchina sia installato ed in esecuzione un MTA, magari senza autenticazione. Si, lo so, non prevedere alcun meccanismo di autenticazione per le email in uscita è altamente sconsigliato, ma dipende strettamente da quello che ci devi fare. Mi spiego: su quelle macchine le uniche email che devono essere inviate sono quelle generate da alcuni strumenti di monitoring, quali logwatch, rkhunter e compagnia bella. Ergo, in realtà, l’MTA non fa altro che appoggiarsi ad uno smarthost per l’inoltro della posta elettronica, fornito dall’hosting provider (ed il cui unico filtro è rappresentato dall’indirizzo IP sorgente). In soldoni, se la richiesta proviene da un IP appartenente al pool della LAN relativa all’hosting provider, la mail viene inviata, altrimenti nisba.

 

spambot.jpg

Detto ciò, è bene precisare che l’MTA attivo su quelle macchine è exim e non Postfix (per una semplice ragione di dimestichezza, ovvero conosco meglio il primo rispetto al secondo).

Soluzione

La prima cosa che ho notato listando il contenuto delle directory su cui sono ospitati i siti Web è stata la presenza di file tipici di WordPress, ad esempio wp-config.php. Si, esatto, questo spam bot è stato pensato per ambienti WP, come abbia fatto ad intrufolarsi in un framework Drupal devo ancora scoprirlo. Quello che so, però, è che si comporta sempre allo stesso modo: infetta il server, prende possesso dell’MTA ed invia email a più non posso.

Dunque, come potete facilmente immaginare, per arginare il problema ho impostato determinate ACL su exim, definendole in base all’indirizzo email di destinazione. Infatti, poichè le email di monitoring sono destinate esclusivamente a me ed al webmaster, è bastato inserire la seguente direttiva nel file di configurazione dell’MTA in questione:

accept  hosts = vostro.indirizzo1@email.it : vostro.indirizzo2@email.it

Per rendere effettive tali modifiche è stato necessario riavviare exim:

[root@bqweb2 ~]# service exim restart

Non conoscendo il baco che ha consentito al malware di infiltrarsi sui server, ho deciso anche di tirar su uno scrip bash che controllasse il contenuto delle dir target ed in caso di anomalie mi inviasse un’apposita email. In questo modo ho realizzato un sistema di sicurezza proattivo.

Ecco lo scrip:

#!/bin/bash

destinatario=vostro.indirizzo@email.it

cd /var/www/

grep -HR "wp-config.php" * > botcheck;

if [ -s botcheck ];then

cat botcheck | mail -iv -s "Server Bqweb2 Infected!" $destinatario;

fi

rm botcheck;

exit 0;

Esso non fa altro che andare alla ricerca del file wp-config.php. Se lo trova mi avvisa in modo tale da poter fare pulizia della directory.

Appena avrò maggiori info sul baco che ha consentito allo spam bot di infilarsi sulle mie macchine le pubblicherò.

Alla prossima.

Installare e configurare NFS

L’acronimo NFS sta per Network File System ed è un sistema di sharing utilizzato in ambiente Linux. A differenza di Samba, che consente ad un sistema *nix di fungere da file server per macchine Windows, NFS è riservato solo ed esclusivamente ai sistemi operativi Unix-like.

linux, windows, samba, nfs, sharing, file server, rpc, portmap, ACL, fstab, mount

Configurarlo e farlo funzionare non è banale, in quanto, oltre alla configurazione del server, occorre lavorare anche sui client, facendo in modo che possano accedere alle directory condivise.

Configurazione del server

Per fare in modo che una macchina Linux possa funzionare da server NFS è necessario installare i seguenti pacchetti:

[root@server ~]# yum install nfs-server
[root@server ~]# yum install portmap

Il primo, ovviamente, è il demone che tira su il servizio NFS vero e proprio; il secondo, invece, serve a gestire le chiamate RPC.

Una volta installati i suddetti pacchetti, passiamo alla configurazione di NFS. Per fare ciò occorre editare il file /etc/exports:

[root@server etc]#nano exports

aggiungendo la directory da condividere (con pathname assoluto) e relativa ACL. Quest’ultima permetterà di fare una distinzione tra le macchine che possono avere accesso alle risorse condivise e quelle a cui l’accesso è stato negato.

/var/www/html/share                192.168.49.0/255.255.255.24 (rw,sync)

Le ultime due flag indicano che le macchine a cui è consentito l’accesso possono operare sia in lettura che in scrittura (rw) e che il contenuto della directory deve essere costantemente sincronizzato tra client e server (sync). Ovviamente, la directory da sharare deve essere esistente, dunque, se ancora non l’avete creata, fatelo mediante un banale mkdir <nomedirectory>.

Inoltre, poichè il meccanismo di controllo degli accessi definito in precedenza è abbastanza blando (si basa sulo ed esclusivamente sull’indirizzo IP delle macchine che vogliono accedere agli share), è opportuno fare in modo che tali servizi non vengano esposti all’esterno, facendo uso di un firewall o di un dispositivo che implementa il NAT/PAT.

Bene, non ci resta che avviare i servizi nfs e portmap:

[root@server etc]# service portmap start
[root@server etc]# service nfs start

Se tutto è andato a buon fine, lanciando un netstat -anp, dovrebbero risultare in ascolto le seguenti porte:

111 UDP (portmap)

2049 TCP/UDP (NFS)

Abilitiamo l’avvio automatico dei suddetti servizi:

[root@server etc]# chkconfig --levels 2345 nfs on
[root@server etc]# chkconfig --levels 2345 portmap on

e lato server abbiamo finito.

Configurazione dei client

Come primo step, è necessario installare il seguente pacchetto:

[root@client ~]# yum install nfs-utils

Successivamente, la cosa più semplice da fare per consentire ai client di accedere alle directory condivise, consiste nell’editare il file /etc/fstab:

[root@client ~]# nano /etc/fstab

aggiungendo una entry del tipo:

<IP LAN server>:/var/www/html/share    /var/www/html/share    nfs    hard,intr,rw,sync 0 0

In particolare, in questa direttiva sono presenti i seguenti campi:

1) share remota;

2) punto di mount locale (che deve essere una directory esistente);

3) tipo di file system;

4) ulteriori flag.

Per montare la share appena creata possiamo lanciare il seguente comando:

[root@linux ~]# mount -a

che monta tutte le partizioni definite nel file fstab, compresa quella NFS.

Per verificare che la share sia effettivamente up, basta digitare il comando mount (che per default mostra tutte le partizioni già montate).

Infine, se si aggiunge una nuova share e la si vuole rendere subito disponibile (senza un restart del demone NFS), è sufficiente lanciare sul server il seguente comando:

[root@server etc]# exportfs -a

Alla prossima.