Nella puntata precedente abbiamo realizzato il fw per la nostra piccola lan virtuale.
Andiamo ora a realizzare la SAN, cioè quel sistema che esporterà via rete i dischi verso il cluster. In effetti questo è un artificio, in un contesto reale i dischi delle SAN sono visibili contemporaneamente a tutti i sistemi e sono normalmente connessi ai server attraverso schede a fibra ottica per ottimizzare i trasferimenti.
Con vmware, ad esempio, è possibile armeggiare un po' con la configurazione ed avere un disco realmente condiviso tra due (o più, credo, ma ho sperimentato solo con 2) server diversi, con virtualbox questo non è possibile, allora proviamo ad aggirare il problema.
La macchina virtuale che farà da SAN, nel mio caso, ha le seguenti caratteristiche:
1 scheda di rete sulla lan-net
1 scheda di rete sulla san-net
Ricordo che la lan-net è la rete interna al firewall (10.100.100.0/24 nel mio caso) mentre la san-net è la rete che useremo per accedere ai dischi. Si potrebbe, in effetti, utilizzare una unica scheda di rete per entrambe le funzioni (cioè raggiungibilità del server ed esportazione dei dischi) però così è formalmente più corretto ed è una configurazione auspicabile quando si abbia una grossa mole di dati che passano sulla rete.
Ci sono diversi standard per il trasporto dei dati su una rete: nfs, sshfs, AoE, iscsi,... I due più interessanti, secondo me, sono AoE (cioè Ata over Ethernet) e iScsi. AoE è forse più semplice da configurare, però non permette né l'autenticazione dei client che si collegano al server per accedere ai dischi né supporta il fatto che client e server stiano su lan diverse. Al contrario iScsi offre sia l'autenticazione che la ruotabilità, permette cioè di esportare dischi anche attraverso lan diverse. Inoltre c'è una interessante feature sperimentale di virtualbox che usa iscsi, poi vedremo meglio.
Nello screenshot qui sotto c'è la configurazione del sistema virtuale.
Ho aggiunto 3 dischi con controller SATA (dovrebbero fornire prestazioni migliori, anche se in effetti in questa applicazione non dovrebbe influire molto) che esporteremo verso il cluster. Questi dischi sono vuoti. Ciascun disco va inizializzato con fdisk. Ad esempio il primo:
C'è inoltre un disco "boot generico" che useremo per l'esperimento :)
In questo caso abbiamo bisogno di due schede di rete, una verso la lan interna (lan-net) e una per esportare i dischi (san-net).
Il disco di boot è quello clonato dal template, per cui come per il fw ci sono delle modifiche da fare. Una nota: se avete configurato in precedenza il fw con le regole postate potete accedere al sistema via ssh dalla macchina host. Per accedere via ssh alla san1 bisogna collegarsi dalla shell del sistema fw in quanto san1 non ha schede di rete che possono accedere alla rete host.
Come fatto in precedenza annotiamo i mac delle schede di rete.
Modifica del file /etc/hosts
#ip sulla lan locale lan-net
10.100.100.1 fw.rebeldia-lab.local fw
10.100.100.10 san1.rebeldia-lab.local san1
#ip sulla lan dello storage san-net
10.120.32.1 san1.san-net.local
Riavvio...
lan0 Link encap:Ethernet HWaddr 08:00:27:b9:c4:d0
inet addr:10.100.100.10 Bcast:10.100.100.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:feb9:c4d0/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:70 errors:0 dropped:0 overruns:0 frame:0
TX packets:62 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:7644 (7.4 KiB) TX bytes:8060 (7.8 KiB)
Interrupt:11 Base address:0xd020
san0 Link encap:Ethernet HWaddr 08:00:27:93:f0:08
inet addr:10.120.32.1 Bcast:10.120.32.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fe93:f008/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:120 (120.0 B) TX bytes:468 (468.0 B)
Interrupt:10 Base address:0xd240
PING www.euro.fyeu.b.yahoo.com (217.146.186.51) 56(84) bytes of data.
64 bytes from www.vip.ird.yahoo.com (217.146.186.51): icmp_seq=1 ttl=50 time=56.0 ms
64 bytes from www.vip.ird.yahoo.com (217.146.186.51): icmp_seq=2 ttl=50 time=55.0 ms
^C64 bytes from www.vip.ird.yahoo.com (217.146.186.51): icmp_seq=3 ttl=50 time=54.4 ms
--- www.euro.fyeu.b.yahoo.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 10191ms
rtt min/avg/max/mdev = 54.464/55.176/56.066/0.718 ms
Prima di proseguire con l'installazione di iscsi potrebbe, per chi non conoscesse il protocollo, dare una occhiata qui
Dunque, san1 sarà il terminatore della connessione (il server) mentre i vari client che dovranno accedere ai dischi saranno gli iniziatori.
Installiamo il software necessario (per questo è necessario che san1 possa accedere ad internet):
nel mio esempio il layout dei dischi è il seguente:
/dev/sda è un disco di boot generico
/dev/sdb,sdc,sdd sono dischi vuoti da 5 GB
Ogni entità iscsi, che per semplicità chiameremo disco :), è rappresentata nella seguente maniera:
iqn.yyyy-mm.
iqn è il formato di rappresentazione più usato. In pratica i vari campi hanno il seguente significato:
yyyy-mm : anno e mese. A piacimento... ma non nel futuro.
[:identificatore] : il nome che vogliamo dare alla risorsa per riconoscerla meglio.
La configurazione del terminatore si effettua modificando il file /etc/ietd.conf (questa serie di post è solo a scopo di test, la configurazione di iscsi non sarà autenticata e avrà la configurazione minima per funzionare):
Target iqn.2010-09.local.rebeldia-lab:bootdisk
Lun 0 Path=/dev/sda,Type=fileio
Target iqn.2010-09.local.rebeldia-lab:SANdisk1
Lun 0 Path=/dev/sdb,Type=fileio
Target iqn.2010-09.local.rebeldia-lab:SANdisk2
Lun 0 Path=/dev/sdc,Type=fileio
Target iqn.2010-09.local.rebeldia-lab:SANdisk3
Lun 0 Path=/dev/sdd,Type=fileio
Lettura della lista dei pacchetti in corso... Fatto
Generazione dell'albero delle dipendenze in corso
Lettura informazioni sullo stato... Fatto
Il pacchetto iscsitarget-modules è un pacchetto virtuale fornito da:
iscsitarget-modules-2.6.26-2-xen-686 2.6.26+0.4.16+svn162-6+lenny1
iscsitarget-modules-2.6.26-2-vserver-686-bigmem 2.6.26+0.4.16+svn162-6+lenny1
iscsitarget-modules-2.6.26-2-vserver-686 2.6.26+0.4.16+svn162-6+lenny1
iscsitarget-modules-2.6.26-2-openvz-686 2.6.26+0.4.16+svn162-6+lenny1
iscsitarget-modules-2.6.26-2-amd64 2.6.26+0.4.16+svn162-6+lenny1
iscsitarget-modules-2.6.26-2-686-bigmem 2.6.26+0.4.16+svn162-6+lenny1
iscsitarget-modules-2.6.26-2-686 2.6.26+0.4.16+svn162-6+lenny1
iscsitarget-modules-2.6.26-2-486 2.6.26+0.4.16+svn162-6+lenny1
Bisogna esplicitamente sceglierne uno da installare.
E: Il pacchetto iscsitarget-modules non ha candidati da installare
...
san1:~# /etc/init.d/iscsitarget start
Starting iSCSI enterprise target service: succeeded.
nell'help di virtualbox c'è la voce relativa alla procedura per consentire all'ambiente virtuale (cioè alla macchina virtuale prima del boot) di fungere da iniziatore (client) verso la san.
Per fare questo esperimento però bisogna spegnere il sistema san1, aggiungere nella configurazione una scheda di rete in bridge o in nat. Questo perchè il meccanismo di routing delle vlan non permette di accedere ad una rete interna prima del boot della macchina.
Creiamo una macchina virtuale con le caratteristiche che vogliamo, non aggiungiamo dischi al sistema e rimuoviamo anche la scheda di rete che di default viene aggiunta alla creazione. Avremo quindi un sistema diskless e nicless.
Le informazioni da annotare prima di cominciare sono
1) ip di san1 della interfaccia (nuova) aggiunta = 10.19.74.75 (lan non interna)
2) un mac address, generato ad esempio dalle proprietà delle schede di rete
3) un indirizzo ip da assegnare alla scheda di rete del sistema virtuale = 10.19.74.251
Ora sul sistema HOST con l'utenza che usate per avviare virtualbox:
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
domenico@cerbero:~$ VBoxManage setextradata TEST VBoxInternal/Devices/IntNetIP/0/Config/MAC 08:00:27:ee:9a:45
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
domenico@cerbero:~$ VBoxManage setextradata TEST VBoxInternal/Devices/IntNetIP/0/Config/IP 10.19.74.251
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
domenico@cerbero:~$ VBoxManage setextradata TEST VBoxInternal/Devices/IntNetIP/0/Config/Netmask 255.255.255.0
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
domenico@cerbero:~$ VBoxManage setextradata TEST VBoxInternal/Devices/IntNetIP/0/LUN#0/Driver IntNet
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
domenico@cerbero:~$ VBoxManage setextradata TEST VBoxInternal/Devices/IntNetIP/0/LUN#0/Config/Network privata1
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
domenico@cerbero:~$ VBoxManage setextradata TEST VBoxInternal/Devices/IntNetIP/0/LUN#0/Config/IsService 1
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
A questo punto dovrebbe essere correttamente configurata l'interfaccia sulla san-net. Attiviamo l'iniziatore e facciamo connettere il disco:
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
iSCSI disk created. UUID: c75b6257-5dbe-4d4d-9b99-ad0b2b2184e1
A questo punto si riavvia il sistema, se è andato tutto bene, il sistema diskless farà il boot.
Il boot è chiaramente un po' più lento.
E' importante, affinché questa prova abbia buon esito, che il sistema san1 sia acceso e che la scheda di rete in bonding o in nat sia correttamente configurata prima di avviare la macchina di test.
A questo punto è possibile spegnere la san1, rimuovere la scheda in bridge o in nat e riavviare san1.
Altra prova possibile, si clona un'altra immagine del disco template, si construisce una macchina di prova con una sola scheda di rete sulla lan interna san-net, si assegna il disco clonato come primario e la si avvia.
una volta avviato il sistema installiamo quanto necessario per l'iniziatore (client)
10.120.32.1:3260 via sendtargets
template-debian:~# iscsiadm -m discovery -t st -p 10.120.32.1
10.120.32.1:3260,1 iqn.2010-09.local.rebeldia-lab:bootdisk
10.120.32.1:3260,1 iqn.2010-09.local.rebeldia-lab:SANdisk2
10.120.32.1:3260,1 iqn.2010-09.local.rebeldia-lab:SANdisk1
10.120.32.1:3260,1 iqn.2010-09.local.rebeldia-lab:SANdisk3
Questi dischi importati possono essere facilmente utilizzabili:
Logging in to [iface: default, target: iqn.2010-09.local.rebeldia-lab:SANdisk2, portal: 10.120.32.1,3260]
Login to [iface: default, target: iqn.2010-09.local.rebeldia-lab:SANdisk2, portal: 10.120.32.1,3260]: successful
[ 442.357305] scsi 0:0:0:0: Direct-Access IET VIRTUAL-DISK 0 PQ: 0 ANSI: 4
[ 442.490153] Driver 'sd' needs updating - please use bus_type methods
[ 442.504137] sd 0:0:0:0: [sda] 10485760 512-byte hardware sectors (5369 MB)
[ 442.509827] sd 0:0:0:0: [sda] Write Protect is off
Attraverso il protocollo iscsi è possibile esportare anche partizioni o file system invece che dischi interi. L'importante è configurare correttamente il terminatore e, soprattutto, che il fs che stiamo esportando non siano montati sul sistema terminatore.
Nella prossima puntata il cluster.
domenico .-. www.mentularia.info
domenica 20 settembre 2009
Esperimenti con VirtualBox: creare una lan virtuale - 2/3 - SAN
giovedì 17 settembre 2009
Esperimenti con VirtualBox: creare una lan virtuale - 1/3 - Firewall
Pur non essendo, forse, VirtualBox il miglio prodotto per la virtualizzazione tuttavia è quello che mi piace di più, anche se prodotti concorrenti come VMware offrono funzionalità che non sono presenti in VB.
Lo scopo di questo post è di raccogliere una serie di esperimenti fatti con VB per creare una lan interamente virtualizzata.
Se si dispone di un pc abbastanza "carrozzato" (difficile in questi giorni trovare un pc con meno di 4GB di ram e qualche centinaia di GB di spazio disco) è possibile creare una lan composta da 4-5 computer virtuali.
L'idea generale è quella di realizzare una lan secondo lo schema sotto riportato:

Le macchine virtuali da creare sono quindi quattro: un firewall, due nodi per il cluster e una SAN.
Se non è chiaro cosa sia un cluster si può avere una idea leggendo qui, invece per una descrizione sulla SAN si può leggere qui.
Come dicevo in precedenza useremo VirtualBox per questo esperimento. Conviene, per velocizzare le operazioni, costruire un sistema base che poi personalizzeremo a seconda delle esigenze. Questo ci permette di dover installare una sola volta il sistema operativo.
Creiamo una macchina virtuale di base, potete impostare a piacimento i parametri. L'importante è dare un nome al disco fisso che sia facilmente identificabile (una buona idea ptrebbe essere template.vdi :) ).Tale disco sarà utilizzato per produrre tutti i dischi di avvio dei vari sistemi sulla lan.Dopo aver configurato tutti i parametri della macchina virtuale nel riepilogo dovreste avere una cosa del genere:

accendiamo la macchina "template", installiamo debian lenny e quindi spegnamo la macchina virtuale.Siccome il disco di questa macchina ci servirà per costruire i dischi di tutti gli altri sistemi è bene rimanere, nella fase di installazione, il più generico possibile. Quindi imposteremo un hostname generico, tipo "template" ed utilizzeremo una sola scheda di rete, connessa ad internet, che in questa fase ci serve tanto per l'installazione che per l'aggiornamento del sistema.
Importante prima di procedere con i passi successivi bisogna rimuovere, dal gestore supporti virtuali, il disco template (nel mio caso template.vdi):

Selezionare il disco da rilasciare, premere "Rilascia" e confermare nella schermata successiva. Selezionare nuovamente il disco, che ora risulterà Connesso a: Non Connesso e premere "Rimuovi". Confermare con "Rimuovi" nella schermata successiva e "Mantieni" nell'ultima schermata. Questo permette di avere il disco tolto dal controllo del gestore supporti virtuali, ma di non cancellare il disco fisicamente
Diversamente da quanto avviene con vmware non basta copiare il disco e rinominarlo per importarlo su una macchina virtuale. Bisogna utilizzare il seguente comando:
C:\Program Files\Sun\VirtualBox>VBoxManage.exe clonevdi template.vdi fw-boot-disk.vdi
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Clone hard disk created in format 'VDI'. UUID: f548d710-fcea-4118-8353-e21cf6794de6
Sistemi HOST linux
domenico@cerbero:~$ VBoxManage clonevdi template.vdi /vm/rebeldia-lab.local/fw-boot-disk.vdi
VirtualBox Command Line Management Interface Version 3.0.6
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Clone hard disk created in format 'VDI'. UUID: 1d8d923e-e42a-4b82-819c-f3ec285ffe5b
Analogamente vengono clonati i dischi di boot per il cluster (Consiglierei, per motivi di opportunità e di tempo, di non creare entrambi i dischi per i due nodi del cluster. Conviene farne uno solo e poi, dopo i vari aggiustamenti, clonare quello in modo da avere il sistema sui due nodi del cluster assolutamente allineato) e per la SAN.
Importiamo i vari dischi creati all'interno del gestore dei supporti virtuali, premendo il pulsante "Aggiungi" e selezionando, quindi, i dischi da porre sotto il controllo del gestore.
A questo punto creiamo le macchine virtuali che faranno parte della nostra lan, avendo cura di impostare, quando richiesto, i dischi clonati in precedenza. Verifichiamo che tutto funzioni accendendoli (uno alla volta o tutti assieme, in questa fase non importa). Se tutti i sistemi caricano il sistema operativo correttamente si può passare al punto successivo. Spegniamo tutti i sistemi virtuali e iniziamo a riconfigurare, prima però è necessario avere ben chiaro come deve essere la configurazione globale della lan. Abbiamo necessità di una lan di gestione, utilizzando la quale si riesca ad accedere ai sistemi, una lan privata per il cluster e una privata per la SAN. Lo specchietto seguente riporta le varie esigenze:
Lan del cluster: 192.168.200.0/24 (cluster-net)
Lan della SAN: 10.120.32.0/24 (san-net)
1) Il Firewall
Rispetto al template il firewall necessita di una scheda di rete aggiuntiva. La prima scheda sarà attestata sulla rete esterna (WAN) ed avrà l'ip assegnato tramite DHCP. La seconda scheda sarà invece sulla lan di gestione, avrà ip 10.100.100.1
Passiamo a modificare la configurazione della macchina virtuale. Aggiungiamo una scheda di rete. La prima interfaccia (WAN) sarà in bridge su una scheda di rete del sistema host che possa essere raggiunta dal DHCP server. La secondo interfaccia sarà, invece, dichiarata come connessa alla rete interna lan-net:

I mac per le due schede sono (le lettere in minuscolo):
Scheda 1 = eth0 = 080027786f18 che, nella notazione normale diventa, 08:00:27:78:6f:18
Scheda 2 = eth1 = 0800277cbd05 e cioè 08:00:27:7c:bd:05
Regoliamo, ora, a nostro piacimento la memoria da assegnare alla macchina virtuale. E' bene tenere conto che la somma della memoria virtuale di tutti i sistemi non dovrebbe andare oltre la metà (i più avventurosi dicono non oltre i 2/3) della ram totale del sistema. Impostati tutti i parametri avviamo il firewall
Chiaramente, siccome tutti i dischi sono clonati da un master avremo il medesimo hostname, le medesime regole udev, le medesime chiavi ssh...
Bisogna dunque effettuare le seguenti modifiche:
modificare il file /etc/hostname inserendo il nome del server (nel mio caso fw). La modifica avrà effetto al boot successivo.
Modificare il file /etc/hosts inserendo il nome dell'host e l'eventuale dominio.
127.0.0.1 localhost
10.100.100.1 fw.rebeldia-lab.local fw
fw:~# dpkg-reconfigure openssh-server
Creating SSH2 RSA key; this may take some time ...
Creating SSH2 DSA key; this may take some time ...
Restarting OpenBSD Secure Shell server: sshd.
Al boot, oppure quando si connette una periferica al sistema viene creato un nodo nell'alberatura di /dev per ogni periferica. Udev è il tool di sistema che si occupa di questo. Anche per le schede di rete il meccanismo è analogo. Il file /etc/udev/rules.d/70-persistent-net.rules (su debian, in linea di massima il nome del file da modificare contiene persistent-net.rules) contiene le regole statiche per la creazione dei device ethX (ma, come si vede sotto, non è obbligatorio chiamare le schede ethX). Per quanto non dovrebbe variare l'ordine delle interfacce ethX (ovvero ciò che era eth0 all'installazione rimane eth0 per sempre) in alcuni casi può succedere che venga modificato l'ordine delle schede. Questo può essere un problema, specie se si è configurato il sistema per assegnare staticamente un ip ad una determinata scheda.
Ad esempio nel caso del mio fw il file /etc/udev/rules.d/70-persistent-net.rules contiene:
# PCI device 0x1022:0x2000 (pcnet32)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:7c:bd:05", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="lan0"
Basta quindi inserire il mac address corretto per ciascuna interfaccia. Questa operazione è piuttosto importante in quanto tutti sistemi sono cloni di una unica macchina per cui avranno registrate le interfacce del template in posizione eth0, ad esempio. Per cui quando voi create la nuova macchina virtuale avrete delle schede con, ovviamente, mac diversi e quindi sul sistema troverete eth1 dove vi attendevate eth0.
IMPORTANTE: ogni regola (nell'esempio ci sono due regole) deve stare su una linea unica, senza a capo.
Per impostare gli ip statici bisogna editare /etc/network/interfaces inserendo e/o modificandone il contenuto. Sempre nel mio sistema:
iface lo inet loopback
# eth0: scheda sulla wan
allow-hotplug eth0
iface eth0 inet dhcp
# lan0: scheda verso la lan
allow-hotplug lan0
auto lan0
iface lan0 inet static
address 10.100.100.1
netmask 255.255.255.0
broadcast 10.100.100.255
network 10.100.100.0
eth0 Link encap:Ethernet HWaddr 08:00:27:78:6f:18
inet addr:10.19.74.73 Bcast:10.19.74.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fe78:6f18/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:383 errors:0 dropped:0 overruns:0 frame:0
TX packets:208 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:33317 (32.5 KiB) TX bytes:30148 (29.4 KiB)
Interrupt:11 Base address:0xd020
lan0 Link encap:Ethernet HWaddr 08:00:27:7c:bd:05
inet addr:10.100.100.1 Bcast:10.100.100.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fe7c:bd05/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:468 (468.0 B)
Interrupt:10 Base address:0xd240
Adesso il sistema è pronto per diventare il nostro firewall. Data la natura del post io effettuerò una configurazione di base, chi vuole la può comodamente ampliare :)
In questo caso utilizzo FwBuilder per creare lo script di configurazione iptables:
#
# This is automatically generated file. DO NOT MODIFY !
#
# Firewall Builder fwb_ipt v2.1.19-1
#
#
#
#
PATH="/sbin:/usr/sbin:/bin:/usr/bin:${PATH}"
export PATH
LSMOD="/sbin/lsmod"
MODPROBE="/sbin/modprobe"
IPTABLES="/sbin/iptables"
IPTABLES_RESTORE="/sbin/iptables-restore"
IP="/sbin/ip"
LOGGER="/usr/bin/logger"
#
# Prolog script
#
#
# End of prolog script
#
log() {
echo "$1"
test -x "$LOGGER" && $LOGGER -p info "$1"
}
check_file() {
test -r "$2" || {
echo "Can not find file $2 referenced by AddressTable object $1"
exit 1
}
}
va_num=1
add_addr() {
addr=$1
nm=$2
dev=$3
type=""
aadd=""
L=`$IP -4 link ls $dev | head -n1`
if test -n "$L"; then
OIFS=$IFS
IFS=" /:,<"
set $L
type=$4
IFS=$OIFS
if test "$type" = "NO-CARRIER"; then
type=$5
fi
L=`$IP -4 addr ls $dev to $addr | grep inet | grep -v :`
if test -n "$L"; then
OIFS=$IFS
IFS=" /"
set $L
aadd=$2
IFS=$OIFS
fi
fi
if test -z "$aadd"; then
if test "$type" = "POINTOPOINT"; then
$IP -4 addr add $addr dev $dev scope global label $dev:FWB${va_num}
va_num=`expr $va_num + 1`
fi
if test "$type" = "BROADCAST"; then
$IP -4 addr add $addr/$nm dev $dev brd + scope global label $dev:FWB${va_num}
va_num=`expr $va_num + 1`
fi
fi
}
getInterfaceVarName() {
echo $1 | sed 's/\./_/'
}
getaddr() {
dev=$1
name=$2
L=`$IP -4 addr show dev $dev | grep inet | grep -v :`
test -z "$L" && {
eval "$name=''"
return
}
OIFS=$IFS
IFS=" /"
set $L
eval "$name=$2"
IFS=$OIFS
}
getinterfaces() {
NAME=$1
$IP link show | grep ": $NAME" | while read L; do
OIFS=$IFS
IFS=" :"
set $L
IFS=$OIFS
echo $2
done
}
# increment ip address
incaddr()
{
n1=$4
n2=$3
n3=$2
n4=$1
vn1=`eval "echo \\$$n1"`
R=`expr $vn1 \< 255`
if test $R = "1"; then
eval "$n1=`expr $vn1 + 1`"
else
eval "$n1=0"
incaddr XX $n4 $n3 $n2
fi
}
if $IP link ls >/dev/null 2>&1; then
echo;
else
echo "iproute not found"
exit 1
fi
MODULES_DIR="/lib/modules/`uname -r`/kernel/net/"
MODULES=`find $MODULES_DIR -name '*conntrack*'|sed -e 's/^.*\///' -e 's/\([^\.]\)\..*/\1/'`
MODULES="$MODULES `find $MODULES_DIR -name '*nat*'|sed -e 's/^.*\///' -e 's/\([^\.]\)\..*/\1/'`"
for module in $MODULES; do
if $LSMOD | grep ${module} >/dev/null; then continue; fi
$MODPROBE ${module} || exit 1
done
# Using 0 address table files
INTERFACES="eth0 lan0 lo "
for i in $INTERFACES ; do
$IP link show "$i" > /dev/null 2>&1 || {
log "Interface $i does not exist"
exit 1
}
done
# Configure interfaces
$IP -4 neigh flush dev lan0 >/dev/null 2>&1
$IP -4 addr flush dev lan0 secondary label "lan0:FWB*" >/dev/null 2>&1
add_addr 10.100.100.1 24 lan0
$IP link set lan0 up
add_addr 127.0.0.1 8 lo
$IP link set lo up
getaddr eth0 i_eth0
# Add virtual addresses for NAT rules
log 'Activating firewall script generated Thu Sep 17 23:04:29 2009 by domenico'
$IPTABLES -P OUTPUT DROP
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
ip6tables -L -n > /dev/null 2>&1 && {
ip6tables -P OUTPUT DROP
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT
}
cat /proc/net/ip_tables_names | while read table; do
$IPTABLES -t $table -L -n | while read c chain rest; do
if test "X$c" = "XChain" ; then
$IPTABLES -t $table -F $chain
fi
done
$IPTABLES -t $table -X
done
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
#
# Rule 0 (NAT)
#
echo "Rule 0 (NAT)"
#
#
$IPTABLES -t nat -A POSTROUTING -o eth0 -s 10.100.100.0/24 -j MASQUERADE
#
# Rule 0 (eth0)
#
echo "Rule 0 (eth0)"
#
# anti spoofing rule
#
$IPTABLES -N In_RULE_0
test -n "$i_eth0" && $IPTABLES -A INPUT -i eth0 -s $i_eth0 -m state --state NEW -j In_RULE_0
$IPTABLES -A INPUT -i eth0 -s 10.100.100.1 -m state --state NEW -j In_RULE_0
$IPTABLES -A INPUT -i eth0 -s 10.100.100.0/24 -m state --state NEW -j In_RULE_0
test -n "$i_eth0" && $IPTABLES -A FORWARD -i eth0 -s $i_eth0 -m state --state NEW -j In_RULE_0
$IPTABLES -A FORWARD -i eth0 -s 10.100.100.1 -m state --state NEW -j In_RULE_0
$IPTABLES -A FORWARD -i eth0 -s 10.100.100.0/24 -m state --state NEW -j In_RULE_0
$IPTABLES -A In_RULE_0 -j LOG --log-level info --log-prefix "RULE 0 -- DENY "
$IPTABLES -A In_RULE_0 -j DROP
#
# Rule 1 (lo)
#
echo "Rule 1 (lo)"
#
#
#
$IPTABLES -A INPUT -i lo -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -o lo -m state --state NEW -j ACCEPT
#
# Rule 2 (global)
#
echo "Rule 2 (global)"
#
# SSH Access to firewall is permitted
# only from internal network
#
$IPTABLES -N Cid4AB2AEFA15114.0
$IPTABLES -A OUTPUT -p tcp -m tcp --dport 22 -m state --state NEW -j Cid4AB2AEFA15114.0
test -n "$i_eth0" && $IPTABLES -A Cid4AB2AEFA15114.0 -d $i_eth0 -j ACCEPT
$IPTABLES -A Cid4AB2AEFA15114.0 -d 10.100.100.1 -j ACCEPT
$IPTABLES -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT
#
# Rule 3 (global)
#
echo "Rule 3 (global)"
#
# Firewall uses one of the machines
# on internal network for DNS
#
$IPTABLES -N RULE_3
$IPTABLES -A OUTPUT -p tcp -m tcp -d 10.100.100.0/24 --dport 53 -m state --state NEW -j RULE_3
$IPTABLES -A OUTPUT -p udp -m udp -d 10.100.100.0/24 --dport 53 -m state --state NEW -j RULE_3
$IPTABLES -A RULE_3 -j LOG --log-level info --log-prefix "RULE 3 -- ACCEPT "
$IPTABLES -A RULE_3 -j ACCEPT
#
# Rule 4 (global)
#
echo "Rule 4 (global)"
#
# All other attempts to connect to
# the firewall are denied and logged
#
$IPTABLES -N RULE_4
test -n "$i_eth0" && $IPTABLES -A OUTPUT -d $i_eth0 -m state --state NEW -j RULE_4
$IPTABLES -A OUTPUT -d 10.100.100.1 -m state --state NEW -j RULE_4
$IPTABLES -A INPUT -m state --state NEW -j RULE_4
$IPTABLES -A RULE_4 -j LOG --log-level info --log-prefix "RULE 4 -- DENY "
$IPTABLES -A RULE_4 -j DROP
#
# Rule 5 (global)
#
echo "Rule 5 (global)"
#
#
#
$IPTABLES -A INPUT -s 10.100.100.0/24 -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -s 10.100.100.0/24 -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -s 10.100.100.0/24 -m state --state NEW -j ACCEPT
#
# Rule 6 (global)
#
echo "Rule 6 (global)"
#
#
#
$IPTABLES -N RULE_6
$IPTABLES -A OUTPUT -m state --state NEW -j RULE_6
$IPTABLES -A INPUT -m state --state NEW -j RULE_6
$IPTABLES -A FORWARD -m state --state NEW -j RULE_6
$IPTABLES -A RULE_6 -j LOG --log-level info --log-prefix "RULE 6 -- DENY "
$IPTABLES -A RULE_6 -j DROP
#
#
echo 1 > /proc/sys/net/ipv4/ip_forward
#
# Epilog script
#
# End of epilog script
#
Alternativamente si può usare arno-iptables-firewall, nella modalità che ho già illustrato in un altro post.
Nel prossimo post la configurazione della SAN e del cluster.
Postate nei commenti se avete considerazioni o domande
domenico .-. www.mentularia.info
martedì 18 agosto 2009
Attacco e difesa...un esempio pratico: attacco e analisi
Supponiamo che, nonostante la "blindatura", il sistema sia stato compromesso e (la cosa peggiore che possa capitare :) ) l'attaccante sia riuscito a scalare i privilegi diventando root. [Ho volutamente evitato di inserire informazioni su come fare a... è fuori dagli scopi di questo blog :D ]
Normalmente, se un attacco è stato portato "bene" le tracce lasciate sono poche. Però spesso i sistemi non si comportano esattamente come ci si aspetterebbe. Se l'amministratore del sistema analizza con una certa frequenza i log si può accorgere di qualcosa di strano. Nel nostro caso si vedono comparire nei messages una serie di segnalazioni del tipo:
sandbox:/var/tmp# tail -f /var/log/messages
Aug 17 13:47:17 sandbox kernel: [249600.574872] netstat[8292]: segfault at 0 ip b7e8fe90 sp bfd9403c error 4 in libc-2.7.so[b7e1a000+155000]
Aug 17 13:47:25 sandbox kernel: [249608.839057] netstat[8648]: segfault at 0 ip b7e1ce90 sp bfc216cc error 4 in libc-2.7.so[b7da7000+155000]
Aug 17 13:47:25 sandbox kernel: [249608.922034] netstat[8651]: segfault at 0 ip b7e95e90 sp bfc9c73c error 4 in libc-2.7.so[b7e20000+155000]
Aug 17 13:47:25 sandbox kernel: [249608.983258] netstat[8654]: segfault at 0 ip b7e6be90 sp bf97041c error 4 in libc-2.7.so[b7df6000+155000]
tutte queste segnalazioni di segmentation fault di netstat sono tutt'altro che normali. Infatti:
sandbox:/tmp/shv6/conf# netstat -an
Segmentation fault
Questa cosa decisamente dovrebbe mettere in guardia qualsiasi amministratore.
Come è possibile che un binario che fino a ora ha sempre funzionato ora, invece, senza alcun motivo apparente va in errore (...non stiamo parlando di winzozz :D ).
Verifichiamo i processi che stanno girando sul sistema:
altro fatto strano: risulta avviato inetd che normalmente rimane non attivo sui sistemi critici:
root 7884 1 0 13:45 ? 00:00:00 /usr/sbin/inetd
root 8809 3381 0 13:54 pts/0 00:00:00 ps -ef
sandbox:/proc# date
lun ago 17 13:54:53 CEST 2009
una rapida occhiata al file di configurazione di inetd non rivela niente di rilevante.
Provando ad utilizzare lsof per verificare quali processi siano attivi si verifica un altro comportamento anomalo, cioè lsof non restituisce alcun output:
sandbox:# lsof -i:22
sandbox:# lsof
sandbox:#
In condizioni normali questi eventi sono sufficienti per convincere un amministratore a mettere offline il nodo e a tenerlo in quarantena.
Una rapida occhiata ai processi di sistema toglie ogni dubbio:
sandbox:/var/log# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Aug14 ? 00:00:15 init [2]
root 2 0 0 Aug14 ? 00:00:00 [kthreadd]
root 3 2 0 Aug14 ? 00:00:00 [migration/0]
root 4 2 0 Aug14 ? 00:00:05 [ksoftirqd/0]
root 5 2 0 Aug14 ? 00:00:00 [watchdog/0]
root 6 2 0 Aug14 ? 00:01:09 [events/0]
root 7 2 0 Aug14 ? 00:00:00 [khelper]
root 39 2 0 Aug14 ? 00:00:03 [kblockd/0]
root 41 2 0 Aug14 ? 00:00:00 [kacpid]
root 42 2 0 Aug14 ? 00:00:00 [kacpi_notify]
root 85 2 0 Aug14 ? 00:00:00 [kseriod]
root 118 2 0 Aug14 ? 00:00:00 [pdflush]
root 119 2 0 Aug14 ? 00:00:13 [pdflush]
root 120 2 0 Aug14 ? 00:00:00 [kswapd0]
root 121 2 0 Aug14 ? 00:00:00 [aio/0]
root 560 2 0 Aug14 ? 00:00:00 [ksuspend_usbd]
root 561 2 0 Aug14 ? 00:00:00 [khubd]
root 605 2 0 Aug14 ? 00:00:00 [ata/0]
root 606 2 0 Aug14 ? 00:00:00 [ata_aux]
root 706 2 0 Aug14 ? 00:00:04 [kjournald]
root 782 1 0 Aug14 ? 00:00:02 udevd --daemon
root 1117 2 0 Aug14 ? 00:00:00 [kpsmoused]
root 1395 2 0 Aug14 ? 00:00:00 [kjournald]
root 1398 2 0 Aug14 ? 00:00:00 [kjournald]
root 1400 2 0 Aug14 ? 00:00:02 [kjournald]
root 1401 2 0 Aug14 ? 00:00:05 [kjournald]
daemon 1453 1 0 Aug14 ? 00:00:00 /sbin/portmap
statd 1469 1 0 Aug14 ? 00:00:00 /sbin/rpc.statd
root 1665 1 0 Aug14 ? 00:00:03 /usr/sbin/rsyslogd -c3
root 1676 1 0 Aug14 ? 00:00:00 /usr/sbin/acpid
Debian-e 1943 1 0 Aug14 ? 00:00:01 /usr/sbin/exim4 -bd -q30m
daemon 1961 1 0 Aug14 ? 00:00:00 /usr/sbin/atd
root 1981 1 0 Aug14 ? 00:00:12 /usr/sbin/cron
root 2002 1 0 Aug14 tty2 00:00:00 /sbin/getty 38400 tty2
root 2004 1 0 Aug14 tty3 00:00:00 /sbin/getty 38400 tty3
root 2005 1 0 Aug14 tty4 00:00:00 /sbin/getty 38400 tty4
root 2008 1 0 Aug14 tty5 00:00:00 /sbin/getty 38400 tty5
root 2009 1 0 Aug14 tty6 00:00:00 /sbin/getty 38400 tty6
root 3364 1 0 Aug14 ? 00:00:00 /usr/sbin/sshd
root 7706 1 0 Aug17 tty1 00:00:00 /sbin/getty 38400 tty1
root 7884 1 0 Aug17 ? 00:00:00 /usr/sbin/inetd
root 9074 3364 0 13:31 ? 00:00:10 sshd: root@pts/0
root 9077 9074 0 13:31 pts/0 00:00:01 -bash
root 9136 9077 0 15:09 pts/0 00:00:00 ps -ef
Il comando ps restituisce 44 processi. Però andando a vedere il contenuto di /proc
sandbox:~# ls /proc/ |grep '[0-9]'|wc -l
46
I processi sono 46. Quindi ps non restituisce info almeno su due processi, le probabilità che il sistema sia compromesso sono molto elevate.
Un ultimo test taglia la testa al toro. Verifichiamo la tabella degli hash md5 che avevamo in precedenza creato:
sandbox:~# debsums -c -m /mnt/sda1/md5_hash_table
/var/lib/aspell/it.compat
/bin/ls
/usr/bin/md5sum
/usr/bin/find
/bin/login
/bin/netstat
/sbin/ifconfig
/bin/ps
/usr/bin/top
/usr/bin/pstree
Come si vede sono cambiati gli hash di alcuni file fondamentali, come netstat che, abbiamo visto, non si riesce ad eseguire.... giustamente è cambiato anche md5sum, il che fa supporre che il rootkit cerchi di bypassare questo genere di controllo, alterando gli hash del sistema operativo.
Prima di isolare il sistema, da un'altra macchina, verifichiamo se qualcosa è cambiato nel networking dato che netstat non funziona:
root@slax:~# nmap -sS -sV -p1-65535 10.41.113.99
Starting Nmap 4.60 ( http://nmap.org ) at 2009-08-18 14:30 GMT
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns_servers
Stats: 0:00:45 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 66.67% done; ETC: 14:31 (0:00:05 remaining)
Interesting ports on 10.41.113.99:
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh (protocol 2.0)
111/tcp open rpcbind 2 (rpc #100000)
37599/tcp open status 1 (rpc #100024)
37998/tcp open ssh SCS sshd 2.0.13 (protocol 1.5)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port22-TCP:V=4.60%I=7%D=8/18%Time=4A8ABB42%P=i486-Slackware-linux-gnu%r
SF:(NULL,20,"SSH-2\.0-OpenSSH_5\.1p1\x20Debian-5\r\n");
MAC Address: 08:00:27:B3:D3:4E (Cadmus Computer Systems)
Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 46.056 seconds
Sorpresa sorpresa :) una seconda istanza di un ssh su 37998. Vediamo un po':
root@slax:~# nc 10.41.113.99 37998
SSH-1.5-2.0.13
Quindi il rootkit ha installato anche una backdoor. A questo punto ogni ulteriore analisi compiuta col sistema attivo e online è inutile e potenzialmente dannosa. Inutile perchè il rootkit è fatto apposta per nascondere le proprie tracce (infatti ad una prima analisi non è possibile determinare nè dove risieda questo secondo demone ssh, nè dove sia la corrispondente configurazione), dannosa perchè l'attaccante, se il sistema è online, può ancora connettersi e rimuovere eventuali tracce.
Supponiamo, quindi, di mettere offline il sistema. Se dobbiamo raccogliere informazioni utili per una analisi forense ci sono alcune attenzioni da avere. Prima di tutto bisogna effettuare una copia del o dei dischi del sistema impattato. Conviene prendere un hd nuovo da collegare al sistema della stessa dimensione del disco presente. Il boot va effettuato in modo "pulito", cioè o da un cdrom o da una chiave usb. L'importante è non far riavviare il sistema dal proprio disco "contaminato". Questo per evitare ulteriori eventuali modifiche dei file che impediscano di stabilire una linea temporale precisa.
Effettuiamo, quindi, il boot da una live.
Prima di tutto una copia fisica. Supponiamo che il disco incriminato sia /dev/hda e il nuovo disco sia /dev/hdb:
sandbox:~# dd if=/dev/zero of=/dev/hdb
sandbox:~# dd if=/dev/hda of=/dev/hdb
Il primo dd serve a "ricoprire" di zero tutto il disco in modo da evitare che qualche informazione spuria presente su hdb vada ad inficiare la validità della copia.
Verifichiamo che le copie siano consistenti:
sandbox:~# md5sum /dev/hda
b335358b2054cb9d68325d3fa4687531 /dev/hda
sandbox:~# md5sum /dev/hdb
b335358b2054cb9d68325d3fa4687531 /dev/hdb
sandbox:~# openssl sha1 /dev/hda
SHA1(/dev/hda)= 159ef7f052e1579b527a582cfb8ad4e62cdbc94c
sandbox:~# openssl sha1 /dev/hdb
SHA1(/dev/hdb)= 159ef7f052e1579b527a582cfb8ad4e62cdbc94c
Perchè usare due algoritmi di hash? Se si stanno compiendo analisi per l'utilizzo forense è necessario tutelarsi dalla possibilità che, nel frattempo, si scopra una possibile collisione nei protocolli di hashing. Così facendo se anche uno dei protocolli dovesse venir bucato, esiste sempre l'altro che fa fede. Se non ricordo male qualcuno ha dimostrato la possibilità di generare due hash uguali per file diversi sfruttando una collisione della routine di compressione dell'MD5.
L'uguaglianza degli hash implica che i due dischi sono uguali, per quanto riguarda i contenuti, al byte.
Infine facciamo una terza copia in modo del tutto analogo al precedente, utilizzando però un file e non un supporto fisico:
sandbox:~# dd if=/dev/zero of=/tmp/dump_hd
...
sandbox:~# md5sum /tmp/dump_hd
...
In questo modo i due hd fisici rimarranno come reperti, mentre l'analisi verrà effettuata sul dump appena creato. Chiaramente se non ci sono necessità legali non c'è bisogno di questo... anche se magari avere una immagine può aiutare nel caso si corrompa l'hd.
A questo punto, per eseguire una vera e propria analisi forense ci sarebbero altre cose da fare, a noi interessa capire solo cosa sia successo al sistema.
Come dicevo in precedenza io stesso mi sono auto attaccato, però l'ho fatto alla maniera "lamer" cioè ho banalmente applicato un rootkit, senza curarmi troppo di cosa facesse. Per cui lo scopro ora in diretta :D
Lavoriamo sull'immagine precedentemente raccolta. Supponiamo di montarla su /tmp/dump
Attenzione a montare l'immagine. Bisogna assicurarsi che il fs non venga modificato, non venga modificata l'ora di accesso agli inode dei vari file, chiaramente bisogna evitare che si eseguano file infetti. In sostanza l'immagine va montata cone le opzioni ro,noatime,noexec,nodev
Importante: da ora in poi assumiamo che il boot sia stato effettuato da un sistema pulito.
Prima di tutto un controllo anti rootkit:
box:~# chkrootkit -q -r /tmp/dump
Checking `ifconfig'... INFECTED
Checking `netstat'... INFECTED
Checking `pstree'... INFECTED
Checking `top'... INFECTED
/etc/ld.so.hash
Possible t0rn v8 (or variation) rootkit installed
The following suspicious files and directories were found:
/lib/init/rw/.ramfs
Warning: Possible Showtee Rootkit installed
/usr/include/file.h /usr/include/proc.h
Possible ShKit rootkit installed
You have 3 process hidden for readdir command
You have 5 process hidden for ps command
Mi pare che sia abbastanza significativo l'output :)
Vengono segnalati 5 processi nascosti. In effetti 5 nascosti al ps, 3 al readdir, risulta la differenza di 2 che avevamo visto prima facendo il confronto tra ps e il contenuto di /proc.
Ora con l'immagine montata su un altro sistema si riesce ad accedere a quei punti del fs che erano stati "oscurati" dal rootkit. Troviamo lo script per rimuovere l'utente dai log, i tools per bypassare i normali ids... si può, quindi, avere una idea generale del funzionamento:
1) vengono installate versioni trojanized dei principali comandi di sistema.
2) si determina, mediante il check di un paricolare file (penso /lib/init/rw/.ramfs) se il rootkit è installato, in modo da evitare sovrainstallazioni
3) viene creata una backdoor utilizzando un demone ssh dedicato
4) vengono installati tutti i tools necessari a nascondere le proprie tracce
Generalmente, ma non è stato questo il caso, il trojan tende a mantenere delle copie "sane" dei file che infetta, in modo che l'attaccante possa controllare effettivamente il sistema. Per esempio il comando ls non restituisce nulla nella directory nella quale si trova il trojan, così come ps maschera i processi relativi al rootkit. Le versioni non compromesse, invece, funzionano correttamente.
Come dicevo si tratta di un caso semplice (anche perchè l'ho fatto io :D ) e sicuramente ci sarebbero molte più analisi da effettuare. Però questo articolo voleva solo fornire degli spunti e, soprattutto, far considerare che un malfunzionamento di un comando (così come un ouptup strano e non consueto) dovrebbero mettere subito in allarme qualsiasi sysadm e indurlo ad approfondire la cosa. Poi c'è un secondo aspetto: il logging. Spesso i log vengono trascurati e alle volte, come in questo caso, possono venir manomessi privando quindi il sysadm di una preziosissima fonte di informazioni. Si può rimediare mediante logging su un sistema terzo, che introduce una complessità maggiore all'attaccante.
Magari, in un futuro, proverò ad inserire un articolo più completo sulla fase di analisi di un sistema compromesso.
Come al solito, se ci sono questioni o commenti postate pure :)
venerdì 14 agosto 2009
Attacco e difesa...un esempio pratico: difesa iniziale
Casualmente sono venuto in possesso di un rootkit/trojan per linux. Voglio provare ad analizzarlo per verificare quanto sia in grado di coprire la propria presenza e quanto un sistema decentemente protetto sia in grado di resistere o di segnalare il problema.
Per fare questo mettiamo in piedi una sandbox pulita e protetta al meglio possibile. Come sempre la partenza è una Debian hardenizzata con bastille.
In particolare:
1) Un utente non root non può eseguire le utilità di amministrazione, come ifconfig, fsck... questo permette di ridurre la possibilità di exploit su programmi setuid.
2) Tutti i servizi insicuri (occhio, però, a considerare troppo sicuro ssh...) sono chiusi
3) è consentito a root di connettersi solo da locale. Viene disabilitata la connessione dall'esterno.
Per proteggersi dai rootkit è bene, oltre a usare un detector specifico, avere una tabella degli hash md5 per tutti i file installati sul sistema. Debian mette a disposizione un tool per fare questo.
sandbox:~# apt-get clean
sandbox:~# aptitude install debsums
...
sandbox:~# debsums_init
...
Finished generating md5sums!
Checking still missing md5files...
In questo modo abbiamo creato una serie di hash di tutti i pacchetti installati sul sistema. Per ogni nuovo pacchetto installato verrà creato l'hash.
Si può, a questo punto, creare una voce in crontab di root che periodicamente effettui il controllo degli hash:
0 0 * * * debsums -c | logger -t "Hash modificato" -p warning >/dev/null 2>&1
in questo modo ogni mezzanotte verrà effettuato un controllo degli hash e, in caso di variazione, nei messages di sistema comparirà una linea del tipo (se si vuole controllare anche gli hash dei file di configurazione basta dare debsums -ca invece che debsums -c):
...
Aug 14 00:00:10 sandbox Hash modificato: /var/lib/aspell/it.compat
...
Ora chiaramente c'è un problema fondamentale... un attaccante può sostituire un eseguibile, magari con una versione troianizzata, ricalcolare l'hash e inserirlo nella tabella. In questo modo il sistema non segnalerà l'anomalia.
Possiamo procedere in questa maniera:
1) creiamo uno script che estrae tutti gli hash e li ingloba in un unico file
2) spostiamo questo file su un supporto read only
3) effettuiamo il controllo degli hash confrontando quelli generati per i vari file con la tabella salvata
4) creiamo uno script che ci permetta di modificare gli hash presenti nella tabella quando, ad esempio, aggiorniamo il sistema.
Un modo più raffinato consiste nell' inserire tutte le info in un db. In tal modo (ammesso che l'attaccante non riesca anche a bucare il db...) sarà più semplice la gestione degli upgrade e della modifica dei singoli hash.
Vediamo la soluzione più grezza ;)
1.
Gli hash si trovano in /var/lib/dpkg/info all'interno della directory ci sono una serie di file, ciascun file rappresenta un pacchetto installato e, per ciascun pacchetto, il file con estensione md5sums contiene l'hash per tutti i singoli file installati.
una prima bozza di script potrebbe essere:
#!/bin/bash
# Script /usr/bin/chkhash
#
SOURCE_DIR="/var/lib/dpkg/info"
TARGET="/var/tmp/md5_hash_table"
if [ ! -e $TARGET ]; then
touch $TARGET
else
rm $TARGET && touch $TARGET
fi
find $SOURCE_DIR -name '*.md5sums' -exec cat {} \; > $TARGET
2.
Il file /var/tmp/md5_hash_table va ora spostato su un supporto protetto da scrittura. A questo proposito magari si può usare una SD che può essere protetta e sprotetta, in modo da non dover poi utilizzare enormi quantità di CD man mano che si modificano gli hash.
3. e 4. :)
supponendo che, ora, il file degli hash sia su /dev/sda1 e che questo device sia montato su /mnt/sda1 andremo a effettuare il controllo di integrità dei file direttamente dalla lista appena prodotta:
sandbox:~# debsums -m /mnt/sda1/md5_hash_table -c
/var/lib/aspell/it.compat
quindi nel crontab andremo a modificare l'istruzione:
0 0 * * * debsums -c -m /mnt/sda1/md5_hash_table | logger -t "Hash modificato" -p warning >/dev/null 2>&1
5.
Come dicevo in precedenza a seguito di un aggiornamento o anche per l'installazione di qualche nuova funzionalità e, comunque, a seguito della modifica anche di un solo byte del file, l'hash cambia. Per fare un esempio, supponiamo di avere un file "a" composto da 1000 caratteri a e un file "b" composto da 999 caratteri a e un carattere b. Proviamo a fare l'hash di ciascun file:
sandbox:~# perl -e 'print "a" x1000' > a
sandbox:~# echo -n "b" > b
sandbox:~# perl -e 'print "a" x999' >> b
sandbox:~# diff a b
1c1
< aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
---
> baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
sandbox:~# md5sum a
d4bce459cbbb478eda5d9bf3bf7e2db3 a
sandbox:~# md5sum b
1760ddef13fa66838b8356333c56ada6 b
Come si può vedere gli hash sono del tutto diversi, anche per la modifica dello 0.1% del contenuto del file.
A questo punto sono possibili due soluzioni. La prima prevede, semplicemente, di verificare tutte le variazioni negli hash che vengono riportate nei messages di sistema, individuando quali possono corrispondere a modifiche non volute o estranee. Questo sicuramente potrebbe essere un approccio "safe" però richiede anche una certa opera di analisi dei log.
Altrimenti possiamo effettuare uno script che aggiorni, dopo installazioni e/o upgrade la lista degli hash. La cosa più semplice che si possa fare è inserire nel file /etc/apt/apt.conf.d/90debsums una chiamata allo script realizzato in precedenza.
90debsums contiene le istruzioni che vengono effettuate da apt-get (e da aptitude) dopo l'installazione del pacchetto. Nel mio sistema il file ha il seguente contenuto:
DPkg::Post-Invoke { "if [ -x /usr/bin/debsums ]; then /usr/bin/debsums --generate=nocheck -sp /var/cache/apt/archives; fi"; };
Volendo integrare lo script che abbiamo scritto prima:
DPkg::Post-Invoke { "if [ -x /usr/bin/debsums ]; then /usr/bin/debsums --generate=nocheck -sp /var/cache/apt/archives && /usr/bin/chkhash; fi"; };
In questo modo ad ogni installazione, update... verrà rigenerata la lista completa di hash del sistema. A questo punto non resta che copiarla sul supporto che poi renderemo protetto da scrittura. Se si sceglie questa strada è bene non sovrascrivere direttamente la versione precedente della lista, in modo da poter eventualmente avere uno storico delle varie modifiche. Il limite di questo sistema è che se un attaccante scala i privilegi e diventa root potrebbe installare un rootkit come fosse un pacchetto, attivando quindi il processo di ricalcolo del checksum.
Il mio consiglio è quello di aggiornare periodicamente la lista degli hash, verificando ogni segnalazione che compaia nei log di sistema per capire se si tratta della modifica di un file innocuo oppure no.
Attenzione che, comunque, questo sistema non calcola l'hash di altri file critici come potrebbe essere /etc/passwd o /etc/shadow e, in genere, di tutto quello che si trova in /etc, salvo pochissimi casi.
Infine trovo sia utile utilizzare, sempre schedulandolo in crontab, anche chkrootkit che, basandosi su firme e/o meccanismi euristici riesce a determinare se i file del sistema siano stati o meno compromessi. E' bene, chiaramente, effettuare da subito la scansione in modo da avere un punto iniziale consistente:
sandbox:/var/tmp# aptitude install chkrootkit
...
sandbox:/var/tmp# chkrootkit -e
ROOTDIR is `/'
Checking `amd'... not found
Checking `basename'... not infected
Checking `biff'... not found
Checking `chfn'... not infected
Checking `chsh'... not infected
...
A questo punto il sistema è abbastanza protetto, nelle prossime puntate ci caleremo nel ruolo dell'attaccante e, nell'ultima, dell'analista forense :D
[EDIT]: ovviamente il sistema dovrebbe essere protetto anche dall'esterno, con l'utilizzo di firewall, ids... questa vuole essere solo una dimostrazione :) quindi supporremo che l'attaccante sia già entrato nel sistema :)
mercoledì 5 agosto 2009
Toc Toc... bussa e ti sarà aperto...
Spesso capita che, nonostante si cerchi di blindare al massimo un sistema, ci sia il solito furbacchione che, magari con uno 0-day pagato a peso d'oro, riesce a penetrare il sistema, con tutto quello che ne consegue. Infatti, anche mettendo le policy più stringenti sugli accessi (anche in termini di ip) il fatto che un servizio rimanga esposto alla rete 24h/24 amplifica la possibilità che il servizio stesso venga exploitato.
Anche variare le porte sulle quali ascolta il servizio può risultare di scarsa utilità se l'aggressore è motivato e deciso. Analogo discorso per gli IDS, se l'attaccante è abbastanza esperto riuscirà facilmente a bypassare i meccanismi di allarme. L'idea è quella di fare in modo che il servizio necessario sia attivo solo quando serve realmente. Facciamo un esempio concreto: supponiamo di avere un fw perimetrale. Per prima cosa è bene che il fw non esporti nessun servizio, salvo ad esempio dns/dhcp preferibilmente solo verso la rete interna. Per amministrare il fw supponiamo di utilizzare una connessione ssh. Il fatto di permettere la sola autenticazione con chiave pubblica, di limitare il range di ip che possono connettersi e di variare la porta del servizio non mi garantisce che qualche utente possa bucare il sistema anche dal lato "sicuro" (il fatto che l'interfaccia interna di un fw sia "sicura" è del tutto opinabile...).
Dunque cosa possiamo fare? La necessità è che il servizio ssh sia attivo solo quando devo amministrare il fw.
Un approccio potrebbe essere questo: bussare ad una sequenza nota di porte e, come conseguenza, ottenere l'apertura della porta sulla quale ascolta il server.
La tecnica si chiama, appunto, Port Knocking. Un demone ascolta tutte le connessioni in entrata sul sistema, quando riceve la sequenza di SYN sulle porte indicate apre la porta relativa al servizio.
Esempio: supponiamo che il servizio ssh giri sulla porta 22, le porte da bussare siano 5641, 8942, 9265 e 5476. Inviando un pacchetto SYN (cioè di richiesta connessione) sulle porte, nell'ordine impostato, il demone di cui si diceva prima provvederà ad aprire la porta 22 e a rendere accessibile il servizio. Analogamente possiamo definire una sequenza di "bussata" che provveda a chiudere la porta 22 quando non è più necessaria. Credo che il demone più usato per il Port Knocking sia knockd che dovrebbe essere presente su tutte le piattaforme linux (non ho idea per i sistemi m$). Qui c'è il sito di knockd.
Per l'esempio fatto prima il file di configurazione /etc/knockd.conf potrebbe essere
[options]
logfile = /var/log/knockd.log
[openSSH]
sequence = 5641,8942,9265,5476
seq_timeout = 10
tcpflags = syn
command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
[closeSSH]
sequence = 5476,9265,8942,5641
seq_timeout = 10
tcpflags = syn
command = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
quindi quando il demone intercetta la sequenza corretta di porte apre il servizio ssh. La sintassi della configurazione è piuttosto semplice e permette alcune interessanti variazioni. Avete presente il wake on lan? Bene si può implementare semplicemente il contrario, cioè visto che esiste l'opzione command perché non estendere la cosa implementando una cosa del tipo:
[options]
logfile = /var/log/knockd.log
[openSSH]
sequence = 5641,8942,9265,5476
seq_timeout = 10
tcpflags = syn
command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
[closeSSH]
sequence = 5476,9265,8942,5641
seq_timeout = 10
tcpflags = syn
command = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
[shutdown]
sequence = 5521,6275,4462,2631
seq_timeout = 10
tcpflags = urg
command = /sbin/shutdown -h now
Come si può vedere in questo caso per spegnere la macchina bisogna inviare 4 pacchetti, uno per porta, con il flag "urg" invece che "syn".
Alcune considerazioni:
1) occhio ai flag che si usano per identificare i pacchetti. Il fw potrebbe essere configurato per droppare i pacchetti non syn che si riferiscono a connessioni non stabilite.
2) Implementare un meccanismo di port knocking non è, di per se stesso, un sistema per mettere in sicurezza una macchina. Un attaccante potrebbe, sniffando il vostro traffico, determinare la sequenza di bussata ed utilizzarla per aprire l'ssh. Quindi questo metodo deve essere usato assieme a tutti gli altri strumenti di protezione.
3) In questi esempi ho sempre usato porte tcp. Per usare porte udp basta modificare la configurazione inserendo, dopo il numero della porta, :udp. Così, ad esempio, potrebbe essere:
[openSSH]
sequence = 5641:udp,8942,9265:udp,5476
seq_timeout = 10
tcpflags = syn
command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
chiaramente poi il campo tcpflags ha valore solo per i pacchetti inviati alle porte tcp.
4) Siccome l'invio fuori sequenza o il bussare su una porta sbagliata porta al reset (cioè se la sequenza è 5641:udp,8942,9265:udp,5476 e io busso su 5641:udp,8942,9265:udp,5477) è bene evitare porte in uso, utilizzando porte "alte" per il knocking.
Come bussare? Ci sono vari metodi, se la combinazione di porte non è troppo complessa si può usare netcat, hping o, al limite, lo stesso nmap.
Mi pare sia più o meno tutto... provate a sperimentare e fatemi sapere.
martedì 16 giugno 2009
Realizzare un personal firewall con Virtualbox - 2/2
Nella prima parte abbiamo realizzato un piccolo fw utilizzando una macchina virtuale interna all'host da proteggere.
Ci sono dei pro e dei contro nell'adottare una soluzione di questo tipo. Sicuramente se volete proteggere un pc non molto dotato dal punto di vista hw questa strada potrebbe non essere ottimale.
Tuttavia le richieste della macchina virtuale non sono così eccessive, la quantità di memoria riservata può essere abbassata a 256 MB, potendo scendere ancora se si vuole utilizzare solo come fw. In questo caso è bene, comunque, non scendere sotto i 128MB.
Facciamo un passo indietro. Come avevo scritto l'esigenza di avere una soluzione di questo tipo nasce dal fatto che non mi fido un granché dei tools di sicurezza per microsoft. Questo vale, quindi, anche per i prodotti antivirus.
Il personal fw, quindi, può essere espanso per diventare anche un proxy server per http e non solo.
La prima prova mettendo insieme squid, clamav, apache e squidguard ha dato esiti altalenanti, in paricolare risultava difficoltosa l'interazione tra squidguard e clamav. La seconda soluzione è molto ma molto più semplice :D
E' bene notare che se viene installato un programma infetto sul pc bisognerà utilizzare un antivirus in locale. Questa soluzione permette solo una protezione dalla rete, non da eventuali virus presenti su dischi esterni, chiavette usb... Pertanto è comunque consigliabile mantenere anche l'antivirus (aggiornato) su pc windows.
Infine io ho il problema di dovermi autenticare su un ulteriore proxy ISA per avere l'accesso ad internet, quindi installerò anche un proxy in grado di autenticarsi vs ISA server. Conosco 2 prodotti, ntlmap in python e cntlmap in c. La versione in c è estremamente stabile e performante, quindi userò quella. Lo schema qui sotto riporta come sarà la funzione di proxy:
Ci serve il seguente sw:
-clamav
-HAVP
Potrebbe essere necessario che il sistema abbia installato anche: il compilatore gcc, make, curl e libcurl (in debian è necessario preinstallare i seguenti pacchetti (non presenti nell'installazione minima): gcc, make, curl e libcurl4-gnutls-dev con i relativi prerequisiti.
Passiamo, quindi, all'installazione:
fwproxy:~# apt-get install clamav
...
apt-get install gcc make curl libcurl4-gnutls-dev
...
fwproxy:~# apt-get install havp
Prima di proseguire è necessario creare un tempfs montato su /dev/shm, cioè un fs allocato in memoria. Questo viene utilizzato per le transazioni di clamav e di havp, in modo da velocizzare i processi di scansione.
fwproxy:~# mkdir /var/tmpmem
fwproxy:~# mount -t tmpfs /dev/shm/ /var/tmpmem/
fwproxy:~# mkdir -p /var/tmpmem/spool/havp
fwproxy:~# chown -R havp:havp /var/tmpmem/
fwproxy:~# mount | grep tmpmem
/dev/shm on /var/tmpmem type tmpfs (rw)
fwproxy:~# umount /var/tmpmem/
La dimensione di questo fs dipende dalla memoria allocata sul sistema.
Ho smontato il fs in quanto è necessario introdurre una entry in /etc/fstab in modo che al reboot sia ricreato e rimontato. Aggiungiamo la seguente riga:
/dev/shm /var/tmpmem tmpfs rw,mand,uid=106,gid=108 0 0
Le opzioni di mount sono: lock mandatorio (come richiesto dalla documentazione) e fs di proprietà dell'utenza applicativa hapv (il gid e l'uid corrispondono all'utente hapv nel mio sistema)
Ok, ora passiamo alla configurazione:
il file da modificare è, nella mia distro, /etc/havp/havp.config. La mia configurazione è la seguente
BIND_ADDRESS 192.168.12.1
SERVERNUMBER 10
MAXSERVERS 100
SCANTEMPFILE /var/tmpmem/spool/havp/havp-XXXXXX
TEMPDIR /var/tmpmem
ENABLECLAMLIB true
PARENTPROXY localhost
PARENTPORT 4444
Ci sono molte altre voci, ma il file di configurazione è molto ben commentato. Le opzioni che ho modificato riguardano l'ip sul quale deve ascoltare il proxy (si può anche mettere in listen su tutti gli indirizzi dato che il firewall protegge l'interfaccia interna, tuttavia è meglio limitare il listen all'interfaccia interna). Ho modificato i valori di base per le connessioni concorrenti, ho indicato di usare libclamv come motore antivirus, tuttavia si possono integrare anche altri antivirus. Il file di configurazione ha già i template inseriti per altri programmi av. Infine ho indicato a havp che non si deve connettere direttamente in uscita, ma deve passare attraverso il proxy cntlm che, come dicevo, serve ad autenticarmi in uscita dal firewall ISA.
Per verificare il funzionamento provo a scaricare un file che contiene la firma di un virus da eicar e qui sotto vedete il risultato :)
Volendo poi fare le cose per bene si può anche personalizzare la pagina che viene restituita in caso di virus...
Ecco, per ora è tutto... se mi viene in mente qualche ulteriore accrocchio provvederò a postarlo.
p.s.
L'ultima versione di Virualbox (2.2.2.xxx) sembra avere dei problemi se la ram assegnata è inferiore a 256 MB. Consiglio almeno 381 MB e max 16 per il video. Se usate solo il fw senza proxy allora 256 possono bastare e se mettete al massimo 16 MB destinati alla scheda video non dovreste avere problemi :)
lunedì 15 giugno 2009
loop device
Post veloce, più che altro per mia memoria :D
Capita, per lo meno a me, di necessitare di loop device per montare, ad esempio, una iso e di ricevere un bel messaggio che mi informa che non ci sono più loop device liberi mount: could not find any free loop device
.
A seconda della versione del kernel ci sono due (almeno) possibili soluzioni per rendere disponibili ulteriori loop.
kernel < 2.6.20
Il valore massimo di loop device utilizzabile è di 256. Di default linux ne pre alloca 64. Bisogna modificare il valore options loop max_loop all'interno di /etc/modprobe.conf. Successivamente mediante il comando rmmod loop && modprobe loop viene chiuso e ricaricato il modulo loop. Se viene restituito un errore durante l'ultimo comando potrebbe esserci qualche loop in uso. In questo caso eseguendo:
fwproxy:/tmp# losetup -a
/dev/loop0: [0308]:12 (/tmp/a)
si vede quale loop è impiegato e per montare cosa. Si potrà quindi prima smontare i vari loop e poi reinserire il modulo. Questo metodo non dovrebbe essere più utilizzato, in quanto i kernel attualmente in uso dovrebbero permettere l'allocazione dinamica dei loop, pertanto basta creare lo special device con la seguente sintassi:
mknod -m 0600 /dev/loopX b 7 X
dove X indica il numero del loop da creare
venerdì 12 giugno 2009
Realizzare un personal firewall con Virtualbox - 1/2
Come mi è capitato di dire in precedenza per lavoro sono costretto ad utilizzare una macchina windows. Chiaramente la macchina deve essere adeguatamente protetta, quindi firewall, antivirus, antispy... Però questo espone a diversi problemi.
Primo: i programmi di "sicurezza" devono necessariamente essere eseguiti con privilegi superiori a quelli di un utente normale. Questo comporta che, in caso di exploit di uno di questi componenti un attaccante (uomo, virus, trojan...) può prendere completamente il controllo del sistema e, come potete facilmente intuire, mettere a repentaglio la sicurezza dell'intera LAN. Il secondo punto rilevante è costituito dal fatto che questi prodotti, per garantire il massimo livello di protezione, spesso sono a pagamento.
Infine c'è la questione relativa a come windows gestisce i processi. Una delle tecniche più diffuse (e per questo meno funzionali oggi) per introdurre un malaware in un pc windows è quello di far eseguire il processo maligno nello spazio di memoria di un processo "benigno". Questo comporta che un antivirus non riconoscerà questo programma come virus con tutto quello che ne consegue.
Linux, invece, si comporta diversamente. In particolare le tecniche di iniezione di codice non funzionano, inoltre le possibilità di attacco risultano minori e più facilmente controllabili.
L'idea, quindi, è di realizzare una macchina virtuale che gira sulla mia macchina windows. Bisogna configurare la rete in modo che sia l'interfaccia virtuale a ricevere ed inviare, mentre l'interfaccia fisica (quella sulla macchina windows) sarà connessa solo all'interfaccia virtuale. Spero sia chiaro :). Il disegno seguente dovrebbe chiarire un po' la cosa:
Io per la virtualizzazione uso, di solito, Virtualbox. Creiamo una macchina virtuale, con circa 500 MB di ram ed un paio di GB di disco. Assegnamo una interfaccia di rete, in modalità bridge e una in modalità host only.
Normalmente il flusso di informazioni passerebbe attraverso la scheda di rete If 1 e poi verrebbe processato dal sistema. Utilizzando la soluzione fw interno, invece, il flusso è quello indicato in rosso. La scheda di rete If 1 viene bypassata e i dati passano attraverso la If 3. Le informazioni vengono processate dal firewall, escono dall'If 4 e rientrano nel sistema host attraverso la If 2. La scheda If 1 non può venire disabilitata, altrimenti non funzionerà neanche la If 3 che è in bridge sulla 1. Per "disattivare" la scheda è possibile impostare un ip fuori lan, in modo che non sia utilizzabili in ingresso e in uscita.
Installiamo una Debian minimale (consiglio di partire con una netinstall), selezionando quando necessario l'installazione minima.
Una volta installato il sistema dobbiamo prima di tutto rimuovere tutto ciò che può costituire un rischio di sicurezza. Installiamo openssh che non viene installato nella configurazione minima:
fwproxy:~# apt-get install openssh-server
Chiudiamo tutti i servizi non necessari che debian avvia di default:
fwproxy:~# netstat -na
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:50478 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp 0 0 10.41.113.24:22 10.41.113.23:4217 ESTABLISHED
tcp6 0 0 :::22 :::* LISTEN
udp 0 0 0.0.0.0:32777 0.0.0.0:*
udp 0 0 0.0.0.0:782 0.0.0.0:*
udp 0 0 0.0.0.0:111 0.0.0.0:*
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 3963 /var/run/acpid.socket
unix 5 [ ] DGRAM 3946 /dev/log
unix 2 [ ] DGRAM 1926 @/org/kernel/udev/udevd
unix 2 [ ] DGRAM 5711
unix 2 [ ] DGRAM 4342
unix 2 [ ] DGRAM 3965
fwproxy:~# lsof -i:50478
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
rpc.statd 1454 statd 8u IPv4 3587 TCP *:50478 (LISTEN)
fwproxy:~# lsof -i:111
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
portmap 1443 daemon 4u IPv4 3529 UDP *:sunrpc
portmap 1443 daemon 5u IPv4 3530 TCP *:sunrpc (LISTEN)
fwproxy:~# lsof -i:25
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
exim4 1933 Debian-exim 3u IPv4 4160 TCP localhost:smtp (LISTEN)
fwproxy:~# /etc/init.d/exim4 stop
Stopping MTA: exim4_listener.
fwproxy:~# apt-get purge exim4*
...
fwproxy:~# /etc/init.d/portmap stop
fwproxy:/etc# update-rc.d -f portmap remove
Removing any system startup links for /etc/init.d/portmap ...
/etc/rc0.d/S32portmap
/etc/rc1.d/K81portmap
/etc/rc6.d/S32portmap
/etc/rcS.d/S43portmap
fwproxy:/etc/init.d# ./nfs-common stop
Stopping NFS common utilities: statd.
fwproxy:/etc/init.d# netstat -na
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 152 10.41.113.254:22 10.41.113.23:1416 ESTABLISHED
tcp6 0 0 :::22 :::* LISTEN
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 3936 /var/run/acpid.socket
unix 5 [ ] DGRAM 3919 /dev/log
unix 2 [ ] DGRAM 1926 @/org/kernel/udev/udevd
unix 2 [ ] DGRAM 5040
unix 2 [ ] DGRAM 4351
unix 2 [ ] DGRAM 3938
Non mi serviva exim (MTA, mail transport agent) ne nessun altro sistema di ricezione/recapito mail. Mediante apt-get purge ho rimosso anche i file di configurazione. Il servizio offerto da portmap è utile praticamente solo se si vuole utilizzare nfs. Siccome ci sono un sacco di buchi di sicurezza è buona norma disabilitarlo (a meno che non serva). Analogo discorso per nfs-common. Se dovete usare nfs è necessario che entrambi i servizi siano attivi.
Come si può vedere dall'output del comando netstat -na non ci sono più (a parte il demone ssh ed una connesisone) servizi in ascolto.
Chiusi i servizi passiamo all'hardening. Io utilizzo, di solito, bastille.
fwproxy:/etc/init.d# apt-get install bastille
Prima di utilizzare bastille bisogna fare un piccolo trucco. Anche se scaricato dai repository lenny la versione di bastille sembra non supportare debian 5. Per fare questo bisogna editare il file /etc/debian_version e sostituire il 5 con un 4.
Rapidamente i vari passaggi. Usando il comando bastille -c si lancia il programma con l'interfaccia curses.
La prima schermata è introduttiva. La seconda schermata richiede se si vuole restringere l'accesso a programmi amministrativi. Il default è no, però io direi di rispondere si. Non c'è motivo per il quale un utente normale dovrebbe poter usare programmi come ifconfig o fsck. La terza schermata spiega il contenuto della quarta. In sostanza, completando quanto fatto in precedenza, si chiede se si vuole disabilitare il setuid sui comandi mount/umount. Rispondendo yes si ha, come effetto, che solo root può montare fs, cdrom, floppy... cosa che sarebbe sempre da preferirsi. La stessa domanda (e risposta) vale per ping. Un utente normale non dovrebbe avere necessità di usare il ping. La domanda successiva è se si vuole o meno disabilitare i protocolli in chiaro. Yes, ovviamente :)
Proseguendo il programma ci chiede se vogliamo imporre la scadenza della password (dipende...in linea di massima si), se si vuole limitare a root l'uso di cron (si, assolutamente), se si vuole impostare una umask di default (si,077 come valore nella schermata successiva). Successivamente ci viene chiesto se disabilitare il login di root sui tty, cioè in pratica impedire che root si possa connettere direttamente. La mia politica è che root non deve potersi loggare mai direttamente, ma che si possa diventare root mediante switch user (su, sudo,...). Al passo successivo è possibile inserire una password su grub. Io lo sconsiglio. Ci sono poi una serie di altre pagine, potete scegliere valori diversi dal default ma io vi consiglierei di lasciare tutto così come è. Occhio a questa domanda "Would you like to run the packet filtering script?" qui dovete rispondere no (il fw lo mettiamo a parte, non usiamo il bastille firewall).
A questo punto, terminata l'applicazione di Bastille, abbiamo il sistema con l'interfaccia eth0 esposta verso la wan e l'interfaccia eth1 esposta solo verso il server da proteggere (la macchina host).
Installiamo il firewall, in debian il pacchetto si chiama arno-iptables-firewall, non ha una gui di installazione/configurazione, ma si configura con debconf.
Durante l'installazione il sistema ci chiede se vogliamo configurare il fw con debconf, rispondiamo si (altrimenti, per chi è meno pigro di me e vuole sperimentare la potenza di iptables, si possono inserire a mano le regole).
Primo passo: indicare l'interfaccia esterna. E' quella che si affaccia sulla rete non sicura, è l'interfaccia in bridge (eth0 nel mio caso)
Secondo passo: se la macchina (l'host windows) da proteggere esporta dei servizi TCP verso l'esterno (web server e quant'altro) allora quando richiesto vanno inserite le porte che devono essere raggiungibili dall'esterno. Nel mio caso lascio tutto in bianco dato che non devo esportare servizi.
Terzo passo: analogamente al secondo passo, ma per i servizi UDP
Quarto passo: definizione dell'interfaccia interna. E' l'interfaccia che sta sulla rete sicura, nel caso in esame è l'interfaccia host only, eth1.
Quinto passo: definizione della rete interna. Bisogna indicare quali sono le sottoreti sicure. Ad esempio 192.168.12.0/24. Questa è la lan che ho definito come sicura.
Fine, se premete "si" viene applicato subito il fw, altrimenti se volete rivedere la configurazione premete "no".
Una volta avviato il fw viene stampata la lista delle regole/opzioni. Nel mio caso:
Arno's Iptables Firewall Script v1.8.8o
-------------------------------------------------------------------------------
Sanity checks passed...OK
Stopping (user) plugins (if used)...
Checking/probing Iptables modules:
Module check done...
Configuring /proc/.... settings:
Enabling anti-spoof with rp_filter
Enabling SYN-flood protection via SYN-cookies
Disabling the logging of martians
Disabling the acception of ICMP-redirect messages
Setting the max. amount of simultaneous connections to 16384
Setting default conntrack timeouts
Enabling protection against source routed packets
Enabling reduction of the DoS'ing ability
Setting Default TTL=64
Disabling ECN (Explicit Congestion Notification)
Enabling support for dynamic IP's
Flushing route table
/proc/ setup done...
Setting up firewall chains
Setting default INPUT/FORWARD policy to DROP
Using loglevel "info" for syslogd
Setting up firewall rules:
-------------------------------------------------------------------------------
Accepting packets from the local loopback device
Enabling setting the maximum packet size via MSS
Enabling mangling TOS
Logging of stealth scans (nmap probes etc.) enabled
Logging of packets with bad TCP-flags enabled
Logging of INVALID TCP packets disabled
Logging of INVALID UDP packets disabled
Logging of INVALID ICMP packets disabled
Logging of fragmented packets enabled
Logging of access from reserved addresses enabled
Setting up (antispoof) INTERNAL net(s): 192.168.12.0/24
Reading custom rules from /etc/arno-iptables-firewall/custom-rules
Checking for (user) plugins in /usr/share/arno-iptables-firewall/plugins...
UPnP plugin v0.12
Loaded 1 plugin(s)...
Setting up INPUT policy for the external net (INET):
Enabling support for DHCP-assigned-IP (DHCP client)
Logging of explicitly blocked hosts enabled
Logging of denied local output connections enabled
Packets will NOT be checked for private source addresses
Denying the whole world to send ICMP-requests(ping)
Logging of dropped ICMP-request(ping) packets enabled
Logging of dropped other ICMP packets enabled
Logging of possible stealth scans enabled
Logging of (other) connection attempts to PRIVILEGED TCP ports enabled
Logging of (other) connection attempts to PRIVILEGED UDP ports enabled
Logging of (other) connection attempts to UNPRIVILEGED TCP ports enabled
Logging of (other) connection attempts to UNPRIVILEGED UDP ports enabled
Logging of other IP protocols (non TCP/UDP/ICMP) connection attempts enabled
Logging of ICMP flooding enabled
Setting up OUTPUT policy for the external net (INET):
Allowing all (other) ports/protocols
Applying INET policy to external interface: eth0 (without an external subnet specified)
Setting up INPUT policy for internal (LAN) interface(s): eth1
Allowing ICMP-requests(ping)
Allowing all (other) ports/protocols
Setting up FORWARD policy for internal (LAN) interface(s): eth1
Logging of denied LAN->INET FORWARD connections enabled
Setting up LAN->INET policy:
Allowing ICMP-requests(ping)
Allowing all (other) ports/protocols
Security is ENFORCED for external interface(s) in the FORWARD chain
Jun 12 18:21:35 All firewall rules applied.
********
ATTENZIONE
********
da qui in avanti potreste perdere la connettività internet fino a completamento dell'installazione/configurazione
Adesso che il fw è configurato dobbiamo far girare su eth1 (interfaccia interna) un server dhcp che dia l'ip alla macchina host.
fwproxy:~# apt-get install dhcp3-server
Il tentativo di avvio automatico a seguito dell'installazione ovviamente fallisce, in quanto bisogna prima configurare il servizio. Il mio primo semplicissimo file di configurazione del servizio dhcpd contiene :
fwproxy:~# vi /etc/dhcp3/dhcpd.conf
...
subnet 192.168.12.0 netmask 255.255.255.0 {
range 192.168.12.10 192.168.12.20;
option routers 192.168.12.1;
option domain-name-servers 192.168.12.1 ;
}
...
E' necessario che la scheda interna (quella che sta sulla reta 192.168.12) abbia ip statico (altrimenti non funziona il dhcpd...), pertanto ho editato il file /etc/network/interfaces nella sequente maniera. Si noti che il gateway della scheda interna corrisponde all'ip della scheda esterna. Questo garantisce il corretto flusso dei pacchetti:
#eth0 interfaccia esterna, verso la lan 10.41.113.*
allow-hotplug eth0
iface eth0 inet static
address 10.41.113.23
netmask 255.255.255.0
network 10.41.113.0
broadcast 10.41.113.255
gateway 10.41.113.3
# dns-* options are implemented by the resolvconf package, if installed
dns-nameservers 10.41.35.54
#eth1 interfaccia interna verso la lan 192.168.12.*
auto eth1
iface eth1 inet static
address 192.168.12.1
netmask 255.255.255.0
network 192.168.12.0
broadcast 192.168.12.255
gateway 10.41.113.23
infine ho modificato il file di configurazione di default di dhcpd /etc/default/dhcp3-server:
INTERFACES="eth1"
indicando così che il server dhcpd deve girare solo sulla eth1.
A questo punto, dopo un reboot, dovrebbe funzionare tutto. Testiamo dal fw se è pingabile l'host protetto (la macchina windows) e se è raggiungibile la lan esterna (il gw 10.41.113.3):
C:\>ping 192.168.12.1
Pinging 192.168.12.1 with 32 bytes of data:
Reply from 192.168.12.1: bytes=32 time<1ms ttl="64" bytes="32" ttl="64" sent =" 2," received =" 2," lost =" 0" minimum =" 0ms," maximum =" 0ms," average =" 0ms">ping 10.41.113.3
Pinging 10.41.113.3 with 32 bytes of data:
Reply from 10.41.113.3: bytes=32 time=1ms TTL=254
Reply from 10.41.113.3: bytes=32 time=1ms TTL=254
Ping statistics for 10.41.113.3:
Packets: Sent = 2, Received = 2, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 1ms, Maximum = 1ms, Average = 1ms
Control-C
^C
C:\>
La configurazione delle schede di rete finale diventa, quindi:
Lato FW:
fwproxy:~# ifconfig
eth0 Link encap:Ethernet HWaddr 08:00:27:4b:97:f9
inet addr:10.41.113.23 Bcast:10.41.113.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fe4b:97f9/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:71391 errors:29 dropped:0 overruns:0 frame:0
TX packets:22338 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:38669375 (36.8 MiB) TX bytes:3468754 (3.3 MiB)
Interrupt:11 Base address:0xc020
eth1 Link encap:Ethernet HWaddr 08:00:27:cf:1f:0a
inet addr:192.168.12.1 Bcast:192.168.12.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fecf:1f0a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:26474 errors:2 dropped:0 overruns:0 frame:0
TX packets:27757 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:3536356 (3.3 MiB) TX bytes:31437076 (29.9 MiB)
Interrupt:10 Base address:0xc240
eth0 = If 3
eth1 = If 4
Lato HOST:
C:\>ipconfig
Windows IP Configuration
Ethernet adapter Local Area Connection:
Connection-specific DNS Suffix . :
IP Address. . . . . . . . . . . . : 10.10.10.23
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 10.10.10.3
Ethernet adapter Local Area Connection 3:
Connection-specific DNS Suffix . :
IP Address. . . . . . . . . . . . : 192.168.12.10
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.12.1
Ethernet adapter Local Area Connection = If 1
Ethernet adapter Local Area Connection 3 = If 2
A questo punto il firewall è correttamente configurato. Si tenga conto che con questa configurazione i servizi come messenger, skype... potrebbero non funzionare. Potrebbe essere necessario aprire delle porte sul fw. Per fare questo o si edita a mano il file delle regole oppure si usa il comando dpkg-reconfigure arno-iptables-firewall e, quando richiesto, si inseriscono le porte tcp/udp necessarie.
Nella prossima puntata aggiungeremo le funzioni di proxy.
venerdì 22 maggio 2009
Montare e lavorare fs ext2/ext3 su Win
Mi capita spesso, siccome per lavoro uso win e per le mie cose linux, di dover accedere ad un disco usb ricordandomi troppo tardi che ha solo partizioni ext3. La cosa diventa particolarmente seccante se non si ha sotto mano una macchina linux per aprire tali fs.
Esistono diverse possibilità per montare fs diversi da fat/ntfs sui sistemi m$, alcuni sono piuttosto complicati e permettono di montare qualsiasi fs (mediante, ad esempio, una emulazione a livello user space). Io vi presento, invece, una soluzione che permette di leggere e scriver su ext2 e 3. Il mio consiglio è di operare in sola lettura, come è noto alle volte i sistemi m$ tendono ad essere troppo aggressivi in scrittura. La soluzione proposta è di utilizzare Ext2 IFS for Windows. La home del progetto è qui. L'installazione è semplice, bisogna prima scaricare l'installer dalla sezione download quindi rispondere ad alcune semplici domande...come sempre :D
Alcuni consigli:
1) aprire i fs sempre e soltanto (a meno che non sia necessario fare altrimenti) in lettura
2) non abilitare (anche se nelle faq dicono di si io onestamente ho avuto alcuni piccoli problemi) il supporto per i file di dimensione => 2 GB.
3) leggere, appunto, le faq
Buon lavoro... come sempre, se ci sono problemi, commenti... scrivete o commentate.
venerdì 15 maggio 2009
Gestione scheda wifi
Ho visto che molte visite sul mio blog giungono da richieste su google riguardanti le schede atheros e in generale il wifi. Scrivo quindi questo post con alcune indicazioni per la gestione e l'utilizzo della scheda wifi.
La gestione delle schede wifi, con linux, non avviene utilizzando un unico set di comandi, come avviene per le schede cablate, ma (in attesa dell'implementazione completa nel kernel dello stack mac80211) possiamo identificare due modalità generali, che dipendono dal tipo di driver utilizzato. Se si utilizza come driver la suite madwifi non tutte le modalità operative sono attivabili mediante il comando iwconfig.
Controllare se la scheda wifi funziona
Pare una banalità, ma il fatto che l'output di iwconfig mostri il nome dell'interfaccia non vuole assolutamente dire che il driver funzioni (chi ha giocato con i driver atheros ne dovrebbe sapere qualcosa... :) ). Per i vari esempi ho usato tre diverse schede wifi (... di più non en ho ): una atheros con driver wifi, una broadcom e una chiavetta usb dlink con driver rt73. Testiamo rapidamente se i driver funzionano:
atheros:
prova ~ # iwlist ath0 scan
ath0 Scan completed :
Cell 01 - Address: XX:XX:XX:XX:XX:XX
ESSID:"Belkin54g"
Mode:Master
Frequency:2.437 GHz (Channel 6)
Quality=17/70 Signal level=-78 dBm Noise level=-95 dBm
Encryption key:on
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 22 Mb/s
6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Extra:bcn_int=100
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : TKIP
Pairwise Ciphers (1) : TKIP
Authentication Suites (1) : PSK
Preauthentication Supported
Cell 02 - Address: XX:XX:XX:XX:XX:XX
........
broadcom:
omero:~# iwlist wlan0 scan
wlan0 Scan completed :
Cell 01 - Address: XX:XX:XX:XX:XX:XX
ESSID:"Belkin54g"
Mode:Master
Channel:6
Frequency:2.437 GHz (Channel 6)
Quality=36/100 Signal level=-71 dBm Noise level=-67 dBm
Encryption key:on
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : TKIP
Pairwise Ciphers (1) : TKIP
Authentication Suites (1) : PSK
Preauthentication Supported
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 22 Mb/s
6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Extra:tsf=000000e776542027
Cell 02 - Address: XX:XX:XX:XX:XX:XX
..............
rt73:
prova ~ # iwlist rausb0 scan
rausb0 Scan completed :
Cell 01 - Address: XX:XX:XX:XX:XX:XX
ESSID:"Belkin54g"
Mode:Managed
Channel:6
Encryption key:on
Bit Rates:0 kb/s
Cell 02 - Address: XX:XX:XX:XX:XX:XX
...........
Funzionano tutte e 3 (notare anche che i diversi driver danno livelli di informazione diversi).
Vediamo, quindi, i vari scenari:
Modalità standard
La modalità standard è, appunto, la modalità che normalmente si usa per connettersi ad un ap. Può essere managed se ci si connette ad un ap, oppure ad-hoc se ci si connette ad un altro pc. La modalità managed è alle volte indicata come infrastructure.
Per verificare lo stato di una scheda wifi si utilizza il comando iwconfig. L'output per una scheda atheros è qualcosa di simile a:
prova ~ # iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wifi0 no wireless extensions.
ath0 IEEE 802.11g ESSID:"" Nickname:""
Mode:Managed Channel:0 Access Point: Not-Associated
Bit Rate:0 kb/s Tx-Power:17 dBm Sensitivity=1/1
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=0/70 Signal level=-96 dBm Noise level=-96 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
In questo caso la scheda è in modalità Managed come si può vedere. ath0 è il nome del VAP, cioè dell'interfaccia virtuale che poi trasmette attraverso la "vera" interfaccia, la wifi0.
Con una broadcom, invece:
omero:~# iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wmaster0 no wireless extensions.
wlan0 IEEE 802.11 ESSID:""
Mode:Managed Frequency:2.412 GHz Access Point: Not-Associated
Tx-Power=20 dBm
Retry min limit:7 RTS thr:off Fragment thr=2352 B
Encryption key:off
Link Quality:0 Signal level:0 Noise level:0
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
con wlan0 (e non wmaster0 come si potrebbe pensare) che riveste lo stesso ruolo di wifi0 visto prima.
Un terzo esempio, chiave usb wifi che utilizza i driver rt73:
prova ~ # iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
rausb0 RT73 WLAN ESSID:""
Mode:Managed Frequency=2.412 GHz Bit Rate=54 Mb/s
RTS thr:off Fragment thr:off
Encryption key:off
Link Quality=0/100 Signal level:-121 dBm Noise level:-143 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
In questo caso si lavora direttamente sull'interfaccia rausb0.
Modalità Monitor
La modalità monitor è una sorta di equivalente della modalità promiscua nelle schede di rete cablata. Consente, in sostanza, di intercettare tutto il traffico wifi che viene trasmesso ad una data frequenza (canale). Programmi come Kismet utilizzano la modalità monitor.
Per porre in modalità monitor la scheda di rete si devono usare comandi diversi, a seconda dei driver in uso.
atheros:
ci sono due diversi modi:
ponendo in monitor mode l'interfaccia ath0:
prova ~ # airmon-ng stop ath0
Interface Chipset Driver
wifi0 Atheros madwifi-ng
ath0 Atheros madwifi-ng VAP (parent: wifi0) (VAP destroyed)
prova ~ # airmon-ng start wifi0
Interface Chipset Driver
wifi0 Atheros madwifi-ng
ath0 Atheros madwifi-ng VAP (parent: wifi0) (monitor mode enabled)
prova ~ # iwconfig ath0
ath0 IEEE 802.11g ESSID:"" Nickname:""
Mode:Monitor Frequency:2.457 GHz Access Point: 00:15:AF:B2:4B:24
Bit Rate:0 kb/s Tx-Power:17 dBm Sensitivity=1/1
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=0/70 Signal level=-96 dBm Noise level=-96 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
oppure sfruttare la possibilità di creare più VAP sulla stessa interfaccia fisica:
prova ~ # airmon-ng start wifi0
Interface Chipset Driver
wifi0 Atheros madwifi-ng
ath0 Atheros madwifi-ng VAP (parent: wifi0)
ath1 Atheros madwifi-ng VAP (parent: wifi0) (monitor mode enabled)
prova ~ # iwconfig ath0
ath0 IEEE 802.11g ESSID:"" Nickname:""
Mode:Managed Channel:0 Access Point: Not-Associated
Bit Rate:0 kb/s Tx-Power:17 dBm Sensitivity=1/1
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=0/70 Signal level=-96 dBm Noise level=-96 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
prova ~ # iwconfig ath1
ath1 IEEE 802.11g ESSID:"" Nickname:""
Mode:Monitor Frequency:2.457 GHz Access Point: 00:15:AF:B2:4B:24
Bit Rate:0 kb/s Tx-Power:17 dBm Sensitivity=1/1
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=0/70 Signal level=-96 dBm Noise level=-96 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
In questo secondo caso avremo due interfacce, una utilizzabile in modalità monitor e una in modalità normale.
Tenere ben presente che quando si usa airmon-ng il comando start ha come parametro una interfaccia fisica mentre il comando stop ha come parametro un VAP.
Qualora una interfaccia non funzioni (o la si voglia eliminare) è sempre possibile distruggerla:
prova ~ # wlanconfig ath1 destroy
Se non funziona più ath0 (...capitato più di una volta...) si può distruggerla (avendo cura di distruggere anche tutte le altre athX) e ricrearla:
prova ~ # wlanconfig ath0 destroy
prova ~ # iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wifi0 no wireless extensions.
prova ~ # wlanconfig ath0 create wlandev wifi0 wlanmode sta
ath0
prova ~ # iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wifi0 no wireless extensions.
ath0 IEEE 802.11g ESSID:"" Nickname:""
Mode:Managed Channel:0 Access Point: Not-Associated
Bit Rate:0 kb/s Tx-Power:17 dBm Sensitivity=1/1
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=0/70 Signal level=-96 dBm Noise level=-96 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
prova ~ # ifconfig ath0 up
prova ~ # iwlist ath0 scan
ath0 Scan completed :
Cell 01 - Address: XX:XX:XX:XX:XX:XX
ESSID:"Belkin54g"
Mode:Master
Frequency:2.437 GHz (Channel 6)
Quality=18/70 Signal level=-77 dBm Noise level=-95 dBm
Encryption key:on
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 22 Mb/s
6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
36 Mb/s; 48 Mb/s; 54 Mb/s
Extra:bcn_int=100
IE: IEEE 802.11i/WPA2 Version 1
Group Cipher : TKIP
Pairwise Ciphers (1) : TKIP
Authentication Suites (1) : PSK
Preauthentication Supported
Cell 02 - Address: XX:XX:XX:XX:XX:XX
Ho verificato che il primo modo non funziona correttamente con tutte le versioni dei driver madwifi, inoltre non sfrutta la proprietà piuttosto interessante dei VAP multipli. Del resto quando funziona il primo metodo non funziona il secondo. Bisogna provare :)
Più sotto ci sono delle informazioni utili per utilizzare VAP multipli
broadcom:
Anche in questo caso utilizziamo la suite aircrack. Occhio, però, che la sintassi è uguale ma il tipo di interfaccia da indicare non è la stessa:
omero:~# iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wmaster0 no wireless extensions.
wlan0 IEEE 802.11 ESSID:""
Mode:Managed Frequency:2.412 GHz Access Point: Not-Associated
Tx-Power=20 dBm
Retry min limit:7 RTS thr:off Fragment thr=2352 B
Encryption key:off
Link Quality:0 Signal level:0 Noise level:0
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
eth1 no wireless extensions.
omero:~# airmon-ng start wlan0
Interface Chipset Driver
wlan0 Broadcom 43xx b43 - [phy0]
(monitor mode enabled on mon0)
omero:~# iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wmaster0 no wireless extensions.
wlan0 IEEE 802.11 ESSID:""
Mode:Managed Frequency:2.412 GHz Access Point: Not-Associated
Tx-Power=20 dBm
Retry min limit:7 RTS thr:off Fragment thr=2352 B
Encryption key:off
Link Quality:0 Signal level:0 Noise level:0
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
eth1 no wireless extensions.
mon0 IEEE 802.11 Mode:Monitor Frequency:2.412 GHz Tx-Power=20 dBm
Retry min limit:7 RTS thr:off Fragment thr=2352 B
Encryption key:off
Link Quality:0 Signal level:0 Noise level:0
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
Per verificare se la modalità monitor funziona, sia per atherso che per b43, si utilizza il comando airodump-ng utilizzando come parametro l'interfaccia in modalità monitor (ath1, mon0, ...):
omero:~# airodump-ng interfaccia_in_monitor_mode
rt73:
In questo caso è indifferente utilizzare il comando iwconfig oppure airmon-ng per impostare la modalità monitor
prova ~ # iwconfig rausb0 mode monitor
prova ~ # iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
rausb0 RT73 WLAN ESSID:""
Mode:Monitor Frequency=2.447 GHz Bit Rate=54 Mb/s
RTS thr:off Fragment thr:off
Encryption key:off
Link Quality=0/100 Signal level:-121 dBm Noise level:-143 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
oppure
prova ~ # airmon-ng start rausb0
Interface Chipset Driver
wifi0 Atheros madwifi-ng
rausb0 Ralink USB rt73 (monitor mode enabled)
prova ~ # iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wifi0 no wireless extensions.
rausb0 RT73 WLAN ESSID:""
Mode:Monitor Frequency=2.457 GHz Bit Rate=54 Mb/s
RTS thr:off Fragment thr:off
Encryption key:off
Link Quality=0/100 Signal level:-121 dBm Noise level:-143 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
In questo caso non vengono creati VAP ma è la scheda stessa a essere messa in monitor mode
Qualunque sia il modo utilizzato utilizzando airodump di può verificare se funziona la modalità monitor.
Modalità master
Potremmo dire che si tratta della modalità access point. In effetti la scheda funzionerà come si trattasse di un access point :)
atheros:
L'eventuale VAP in modalità master deve essere sempre ath0, altrimenti non funzionerà (almeno con le versioni dei driver che ho provato), quindi prima di tutto distruggere tutti i VAP.
prova ~ # iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wifi0 no wireless extensions.
wlanconfig wlassistant
prova ~ # wlanconfig ath0 create wlandev wifi0 wlanmode master
ath0
prova ~ # iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wifi0 no wireless extensions.
rausb0 RT73 WLAN ESSID:""
Mode:Monitor Frequency=2.457 GHz Bit Rate=54 Mb/s
RTS thr:off Fragment thr:off
Encryption key:off
Link Quality=0/100 Signal level:-121 dBm Noise level:-143 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
ath0 IEEE 802.11g ESSID:"" Nickname:""
Mode:Master Channel:0 Access Point: Not-Associated
Bit Rate:0 kb/s Tx-Power:17 dBm Sensitivity=1/1
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=0/70 Signal level=-96 dBm Noise level=-96 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
broadcom: il driver b43 utilizza lo stack mac80211. Non è così immediato porre in master mode l'interfaccia, se siete interessati: qui è spiegato bene come fare.
rt73: non mi risulta che questi driver supportino il master mode.
Testare, con la atheros, il modo ap è relativamente semplice (usarlo come ap, invece, richiede un po' di configurazione)
prova ~ # iwconfig ath0
ath0 IEEE 802.11g ESSID:"" Nickname:""
Mode:Master Channel:0 Access Point: Not-Associated
Bit Rate:0 kb/s Tx-Power:17 dBm Sensitivity=1/1
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=0/70 Signal level=-96 dBm Noise level=-96 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
prova ~ # iwconfig ath0 essid pippo-pippo
prova ~ # iwconfig ath0
ath0 IEEE 802.11g ESSID:"pippo-pippo" Nickname:""
Mode:Master Channel:0 Access Point: Not-Associated
Bit Rate:0 kb/s Tx-Power:17 dBm Sensitivity=1/1
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=0/70 Signal level=-96 dBm Noise level=-96 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
prova ~ # iwconfig ath0 channel 11
prova ~ # ifconfig ath0 10.0.0.50 netmask 255.255.255.0 up
Diamo il nome pippo-pippo a questo ap di test, assegnamo un canale e un ip.
Da un altro pc:
omero:~# iwlist wlan0 scan essid pippo-pippo
wlan0 Scan completed :
.....
Cell 02 - Address: 06:15:AF:B2:4B:24
ESSID:"pippo-pippo"
Mode:Master
Channel:11
Frequency:2.462 GHz (Channel 11)
Quality=58/100 Signal level=-50 dBm Noise level=-65 dBm
Encryption key:off
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 6 Mb/s; 9 Mb/s
11 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s; 36 Mb/s
48 Mb/s; 54 Mb/s
Extra:tsf=00000000073d79b4
Vediamo se è possibile associarsi:
omero:~# iwconfig wlan0 essid pippo-pippo
omero:~# ifconfig wlan0 10.0.0.100/24 up
omero:~# ping 10.0.0.50
PING 10.0.0.50 (10.0.0.50) 56(84) bytes of data.
64 bytes from 10.0.0.50: icmp_seq=1 ttl=64 time=3.11 ms
64 bytes from 10.0.0.50: icmp_seq=2 ttl=64 time=0.154 ms
^C
Perfetto :)
Ricapitolando: le modalità di funzionamento di una scheda wifi sono: managed (ad-hoc quando si tratta di pc - pc), monitor e master. La modalità master non funziona bene o non funziona proprio con i driver che implementano lo stack mac80211 (nel nostro caso i driver rt73 e, parzialmente, broadcom) mentre funziona con i driver che implementano lo stack ieee80211.
Ultima annotazione, riguardo i VAP multipli.
E' possibile creare un VAP in modalità master e uno in modalità managed. E' importante ricordare che l'interfaccia in modalità master sia la prima. Nell'esempio qui sotto faccio "internamente" la verifica del funzionamento dell'interfaccia in modalità master:
prova ~ # iwconfig
lo no wireless extensions.
eth0 no wireless extensions.
wifi0 no wireless extensions.
rausb0 RT73 WLAN ESSID:""
Mode:Monitor Frequency=2.457 GHz Bit Rate=54 Mb/s
RTS thr:off Fragment thr:off
Encryption key:off
Link Quality=0/100 Signal level:-121 dBm Noise level:-143 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
ath0 IEEE 802.11g ESSID:"pippo-pippo" Nickname:""
Mode:Master Frequency:2.462 GHz Access Point: 06:15:AF:B2:4B:24
Bit Rate:0 kb/s Tx-Power:17 dBm Sensitivity=1/1
Retry:off RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
Link Quality=47/70 Signal level=-49 dBm Noise level=-96 dBm
Rx invalid nwid:41 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0
prova ~ # wlanconfig ath1 create wlandev wifi0 wlanmode sta
ath1
prova ~ # iwconfig ath1 essid pippo-pippo
prova ~ # ifconfig ath1 10.0.0.111/24 up
prova ~ # ping 10.0.0.50
PING 10.0.0.50 (10.0.0.50) 56(84) bytes of data.
64 bytes from 10.0.0.50: icmp_seq=1 ttl=64 time=0.059 ms
64 bytes from 10.0.0.50: icmp_seq=2 ttl=64 time=0.054 ms
wlanconfig è un comando molto utile, consiglio di leggere il man :) Dimenticavo, wlanconfig è disponibile solo con la suite madwifi-ng e, almeno per Debian, solo se si installa il pacchetto dai sorgenti.
Spero sia utile questa breve panoramica. Per approfondimenti lasciate un commento o scrivetemi una mail.





