(Dato che alcune persone me l’hanno chiesto mi sembra utile ripetere qua parte del “trucco” che avevo utilizzato per il bonding.)

Può capitarci spesso questa situazione: abbiamo il nostro sistema Linux collegato ad internet normalmente e con una VPN aperta. La route di default di sistema punta al gateway “normale” verso internet.

Diciamo che abbiamo quindi l’interfaccia TAP verso la nostra vpn ed è tutto configurato sul server della vpn per nattare il traffico in uscita cioè possiamo impostare, se vogliamo, il server della VPN come gateway di default.
Vogliamo però uscire su internet normalmente e utilizzare la vpn solo per alcune applicazioni.

Come fare a far uscire sulla vpn solo il traffico di una specifica applicazione?

Per riconoscere i pacchetti in uscita da un determinato processo ci servirebbe la funzionalità di mark by pid che però, purtroppo, non è più supportata in iptables da diversi anni (io mi sto attualmente occupando di re-implementarla). Fortunatamente possiamo sfruttare un workaround sfruttando i gruppi.

Iniziamo con il creare un gruppo apposito per tutti i programmi che vogliamo far uscire sulla VPN:
addgroup vpn
A questo punto diciamo a iptables di marcare i pacchetti in uscita dal sistema con un “mark” specifico. I mark di iptables potete immaginarli come delle etichette che vengono messe su tutti i pacchetti che soddisfano i nostri target. Useremo queste etichette per riconoscere i pacchetti speciali e utilizzare il routing corretto.
iptables -t mangle -A OUTPUT -m owner --gid-owner vpn -j MARK --set-mark 42
Il marcatore scelto (in questo caso 42) è del tutto arbitrario.
In questo modo abbiamo “etichettato” tutti i pacchetti in uscita da processi con GID (Group ID) pari a quello del gruppo vpn.

Ora possiamo procedere a definire una tabella di routing alternativa a quella di default. Non tutti sanno infatti che su Linux non esiste un’unica tabella di routing, ma ne possono essere definite diverse e poi utilizzarle a seconda del contesto.
ip rule add fwmark 42 table 42
In questo modo abbiamo “creato” la tabella di routing numero 42, che si attiverà per tutti i pacchetti con fwmark (cioè la nostra “etichettta”) pari a 42.

Passiamo quindi a aggiungere in questa tabella l’operazione di routing che dovrà essere svolta alternativa a quella standard:
ip route add default via 10.0.0.1 dev tap0 table 42
Tutto ciò supponendo che il server della nostra vpn sia 10.0.0.1 e l’interfaccia sia tap0.

Ci manca ancora una cosa però. A causa del workaround che abbiamo scelto i pacchetti in uscita avranno ancora come sorgente l’ip dell’interfaccia utilizzata per il routing di default. Per questo motivo dobbiamo sostituirlo con il nostro indirizzo della vpn:
iptables -t nat -A POSTROUTING -m mark --mark 42 -j SNAT --to-source 10.0.0.2
(Supponendo che l’ip del nostro client della vpn sia 10.0.0.2)
In questo modo guardiamo tutti i pacchetti con l’etichetta 42 e mettiamo a posto l’indirizzo sorgente.

Ora abbiamo tutto pronto. Come facciamo però a fare in modo che un processo utilizzi il GID (Group ID) che abbiamo scelto per la regola?
Su Linux è possibile lanciare un programma con un GID specifico utilizzando il comando sg (set group):
sg vpn -c "programma_che_fa_uso_della_rete"
Se l’utente con cui avviate sg non è parte del gruppo vpn, dovrete lanciare il comando da root. Per aggiungere il vostro utente al gruppo vpn:
adduser vostro_utente vpn
Come ultima nota vi ricordo che quando lanciate un programma in questo modo, anche le richieste DNS viaggeranno all’interno della VPN, assicuratevi quindi di utilizzare come server DNS dei server raggiungibili sia dalla vpn che da fuori! In alternativa inserite due server DNS in /etc/resolv.conf per gestire entrambi i casi separatamente.


Mi è capitato spesso di avere una macchina  che deve esporre dei servizi in rete su alcune porte tcp/udp che però volevo evitare di mostrare al “mondo”.
Ad esempio può essere che voglio aprire un server ssh. Indipendentemente dal servizio e dalla porta, può essere poco raccomandabile lasciarlo lì aperto “a tutti”.
Potremmo allora pensare di aggiungere una regola sul firewall (iptables) per abilitare l’accesso solo da daterminati ip sorgenti. Peccato che molto spesso gli indirizzi sorgente possono cambiare (indirizzi ip dinamici e altro).

Il port-knocking permette di risolvere queste ed altre situazioni.

Supponiamo appunto di avere la porta del servizio ssh (la 22) che vogliamo aprire solo per certe persone, però non sappiamo i loro indirizzi ip. Con la tecnica del port-knocking possiamo avviare un demone che resta “in ascolto” sulle interfacce di rete per tutte le richieste di connessione a basso livello. Quando questo demone vede delle richieste di connessione ad alcune porte (anche “chiuse”) in successione con una certa sequenza, lancia un comando.

Richieste a porte in successione alla fine è una sorta di codice segreto per sbloccare una porta “bussando” su altre ben definite.

Un caso tipico potrebbe essere questo: diciamo al demone che quando vede delle richieste di connessione alle porte  77,98,1044,1066 (esattamente in quest’ordine e fatte entro un certo tempo massimo l’una dall’altra), decide di guardare l’indirizzo ip di chi ha “bussato” e sbloccare solo per lui la porta di ingresso sulla 22 (lanciando una regola di iptables).
Altra cosa molto utile è richiudere la porta appena aperta dopo alcuni secondi. In questo modo l’utente remoto che deve collegarsi “bussa” e si collega, poi richiudendo la porta la connessione oramai stabilita con ftp non cadrà (dato che supponiamo che sul server ci sia una regola iptables per mantenere sempre attive le connessioni stabilite) e altre persone, anche con lo stesso indirizzo sorgente (dentro la stessa NAT dell’utente magari) non potranno collegarsi.

Per prima cosa dobbiamo procurarci il demone, che si chiama knockd. Nelle maggiori distribuzioni lo trovate facilmente nei repository. Lo stesso pacchetto comprende al suo interno anche il “client”, anche se per client potreste usare normalmente netcat o altro (basta solo “bussare” alla fine :D).

Il file di configurazione si trova in /etc/knockd.conf

La configurazione di default dovrebbe essere qualcosa di simile:

[openSSH]
	sequence    = 7000,8000,9000
	seq_timeout = 5
	command     = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
	tcpflags    = syn

[closeSSH]
	sequence    = 9000,8000,7000
	seq_timeout = 5
	command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
	tcpflags    = syn

Questa configurazione significa che quando knockd vede dei pacchetti syn (richiesta di connessione) sulle porte 7000,8000,9000 (in questo preciso ordine), “bussando” in un massimo di 5 secondi, allora viene lanciato il comando “command”.
Quel comando iptables specifica che vengano accettate tutte le connessioni provenienti dall’indirizzo IP di chi ha “bussato” e dirette alla porta tcp 22 (solitamente adibita al protocollo SSH).

Nella sezione seguente, chiamata “[closeSSH]” viene fatto esattamente l’opposto in corrispondenza della sequenza di porte 9000,8000,7000.

Di default il demone knockd non si avvierà se non modificate prima il file /etc/default/knockd impostando:

START_KNOCKD=0

Sempre nello stesso file possiamo specificare su quale interfaccia di rete dovrà lavorare knockd (di default penso le utilizzi tutte):

KNOCKD_OPTS="-i eth0"

Per “bussare” sulle porte utilizzando il client apposito incluso nel pacchetto di knockd ci basterà lanciare un comando tipo questo:

knock 1.2.3.4 7000 8000 9000

Ma usare knock non è obbligatorio. Se siamo su un pc dove non lo abbiamo a portata di mano possiamo anche optare per una soluzione del genere:

 for i in 7000 8000 9000; do nc 1.2.3.4 $i & done;

In questo modo vengono lanciate in background varie istanze di netcat in successione.

Una volta collegati ad ssh si suppone che il firewall iptables sulla macchina che configuriamo sia già impostato per accettare in ingresso connessioni stabilite, di modo che quando la porta viene chiusa la connessione non cade.
Solitamente questo lo si fa con una regola tipo (che comunque dovreste già avere se avete la policy di iptables in DROP):

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

Nella configurazione che abbiamo visto prima la porta viene aperta e chiusa con una combinazione. Una soluzione più furba potrebbe essere di farla chiudere “automaticamente” qualche secondo dopo che la sequenza è stata lanciata e si è aperta

Un esempio di config per fare cio è il seguente:

[openBITS]
        sequence = 9132,4367,8371,1321,5239
        seq_timeout = 30
        tcpflags = syn
        start_command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
        cmd_timeout = 60
        stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT

In questo modo avremo 30 secondi per “bussare” ed una volta aperta la porta, lo resterà per soli 60 secondi.

Per debugging e controllare altro potete sempre visionare il file di log di knockd su /var/log/knockd.log

Come altri spunti interessanti vi avverto che è possibile anche specificare se la porta su cui bussare sia TCP o UDP (per complicare la sequenza) ed è anche possibile verificare la presenza/assenza di determinati flag tcp. In ogni caso trovate altre informazioni sulla pagina ufficiale o nella documentazione.


Disclaimer: L’autore non si assume nessuna responsabilità in merito all’utilizzo illecito delle istruzioni tecniche riportate qui di seguito.

Navigare ed essere collegati, al giorno d’oggi, diventa sempre più importante e si discute di rendere la connessione ad Internet un diritto fondamentale umano. Essere collegati ad una rete unica che collega l’intero pianeta e permette a miliardi di persone di comunicare in ogni momento è semplicemente fantastico, tuttavia a livello utente il discorso “banda” si fa spesso sentire, specie a “livello programmatore” direi 🙂 ..

Bonding di rete

Navigare in rete con 1Mbit/s (125kB/s) può essere ancora accettabile, quando andiamo intorno ai 50kB/s la faccenda inizia a diventare fastidiosa, specialmente se dobbiamo fare una videochiamata o scaricare degli aggiornamenti.
Un caso poco frequente ma che aiuta a far comprendere il seguito è questo:
Immaginiamo di avere un computer con due schede di rete da 10Mb/s ed un router/switch/hub con tante porte da 100Mb/s. Trasmettere e ricevere con un ordine di grandezza in meno per la velocità potrebbe rivelarsi alquanto fastidioso. In alcune situazioni potrebbe dover servire giusto poco più di 10Mb/s e sarebbe alquanto triste non poterli avere.

Fortunatamente all’interno dei moduli di Linux, ne esiste uno chiamato bonding, che permette di ovviare a problemi come questo.

Con il modulo del kernel bonding, è infatti possibile riunire più interfacce di rete in un gruppo, trattandole astrattamente come se fossero una interfaccia unica con un nuovo nome, come ad esempio bond0. Tutto il traffico diretto a bond0 verrà inviato al modulo bonding, che deciderà come dividerlo sulle interfacce del gruppo, idem il viceversa. Una delle politiche per “dividere” il traffico più comuni (e che utilizzerò qua nel seguito) è quella di round-robin, cioè la equa suddivisione del traffico inviando e ricevendo un equo numero di pacchetti da ogni interfaccia. In realtà il modulo bonding permette anche altre configurazioni, che risultano molto utili per server di produzione, dove anche se una interfaccia si guasta o è in sovraccarico, il modulo bonding decide autonomamente di utilizzare una interfaccia di “backup” per risolvere il problema. Quest’ultimo aspetto non sarà comunque di nostro interesse ora.
Dal punto di vista di protocollo di rete, quando più schede vengono unite in una unica bond0, l’indirizzo mac e ip che prima erano diversi per ogni interfaccia, diventano uno solo, associato a bond0. Le interfacce che mettiamo in bonding cessano di avere ip o mac address associati.
Dal punto di vista “teorico” e poi in base a quanto appena detto nella “pratica”, risulta evidente che non sarà possibile utilizzare il bonding con schede collegate a due reti diverse, cioè a reti che utilizzano indirizzi diversi, o comunque in generale dove gli stessi pacchetti non possono arrivare su entrambe le interfacce indistintamente. Vedremo in seguito che questo problema può essere comunque aggirato con un po’ di “fatica”.
Supponiamo ad esempio che le due schede sul nostro computer siano eth0 e eth1; con le poche righe di codice seguenti sarà possibile riunirle in una unica interfaccia bond0 che avrà dunque il doppio della banda: 20Mb/s

modprobe bonding mode=0 miimon=100

ifconfig eth0 down
ifconfig eth1 down

ifconfig bond0 hw ether 00:11:22:33:44:55
ifconfig bond0 192.168.55.55 up

ifenslave bond0 eth0
ifenslave bond0 eth1

Rivediamo i passi: nel modprobe viene abilitato il modulo di bonding, specificando il mode, cioè la politica per dividere i pacchetti. In questo caso 0 è la mode per abilitare il round-robin sopra citato. Dopo aver caricato il modulo, la prima cosa da fare è disattivare le due interfacce di rete eth0  e eth1. A questo punto possiamo configurare la nostra interfaccia bond0, che è stata creata nel momento in cui abbiamo abilitato il modulo di bonding. Come primo passo impostiamo il suo mac address e poi il suo indirizzo IP. Come abbiamo detto prima infatti, le schede unite con bonding cessano di avere ip e mac address e solo la scheda virtuale che le riunisce avrà un indirizzo IP ed un mac address. Assicuriamoci che gli indirizzi impostati siano validi per la nostra rete.
A questo punto l’interfaccia di bonding è pronta, resta solo da dirgli quali interfacce riunire. Questo viene fatto mediante il comando ifenslave, il cui nome richiama il fatto che vengono aggiunte interfacce “schiave”.

Una cosa divertente che si nota da questo esempio, è che l’aggiunta di interfacce da mettere in bonding può essere fatta in tempo reale utilizzando il comando ifenslave! Può sembrare banale, ma la cosa è invece molto interessante. Pensate all’esempio precedente e supponiamo di collegare una scheda di rete usb da 10Mb/s al computer mentre sta lavorando con eth0 e eth1 in bonding. Posto che il kernel riconosca la scheda usb ci basterà collegarla e digitare:

 ifenslave bond0

per vedere subito la velocità delle nostre connessioni aumentare, ed il tutto senza interrompere nessuna connessione in corso!

È sottointeso che tutti i comandi precedenti vanno eseguiti da utente root.

Attenzione! Tutte le volte che facciamo bonding dobbiamo assicurarci di non avere l’opzione rp_filter attivata sul kernel. Se attivata, questa opzione fa sì che il kernel tracci le connessioni in ingresso e rifiuti connessioni dirette ad un indirzzo diverso da quello dell’interfaccia su cui viene ricevuta la connessione. Su alcune distribuzioni (ad esempio ArchLinux) l’rp_filter è disattivato di default, su altre (ad esempio Ubuntu) è attivato di default.. quindi ci conviene controllare.
Possiamo disabilitare l’rp_filter per tutto il sistema con:

echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

Oppure possiamo disabilitarlo sulle singole interfacce, facendo riferimento all’esempio di prima:

echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter

Interfacce virtuali wireless

Passiamo a parlare d’altro ora.

Vi è mai capitato di avere a disposizione due o più reti wireless, ad esempio da 10Mb/s ciascuna e avere la copertura di entrambe dal punto in cui vi trovate con il vostro pc/portatile?
Sarebbe bello riunirle insieme in qualche modo per ottenere il doppio della banda come prima!
Iniziamo con questo esempio: dal vostro portatile riuscite a connettervi a due access point che però hanno appunto un “collo di bottiglia” da 10Mb/s nella banda a disposizione ciascuno. La rete a cui sono collegati questi due access point ha però una ampiezza di banda molto più elevata!

Ok, le reti wireless sono due, però alla fine la rete è la stessa: ci verranno dati indirizzi IP nella stessa sottorete e tutto il resto. Allora ci serve solo capire come collegarci ad entrambe.

Avete mai visto che ci sono access points in grado di mostrarvi due reti wireless anche se in realtà la scheda fisica è la stessa (ad esempio questo accade con la fonera, per chi la conosce)? Beh, anche il contrario è possibile, cioè sostanzialmente è possibile suddividere una interfaccia wireless in un insieme di schede wireless virtuali e far collegare ciascuna di esse ad una rete diversa.

Per fare questo avete bisogno di due cose: una scheda wireless che supporta le “virtual interfaces” (VLANs o VIF) ed un kernel linux 2.6.37 (la cosa dovrebbe funzionare anche da kernel precedenti ma c’era qualche dettaglio ancora non funzionante).
Per quanto riguarda la scheda wireless che supporta le VLANs, questo è vero per praticamente tutte le schede Atheros (quelle che utilizzano i driver ath5k e ath9k) e forse anche per altre schede (in via teorica controllando con il comando “iw list” si dovrebbe riuscire a capire se una scheda può farlo).
C’è un piccolo prezzo da pagare per avere queste VLANs: se ci stiamo collegando a reti protette (come nella maggior parte dei casi), sarà necessario caricare il modulo ath5k o ath9k con un parametro nohwcrypt=1. Perché? Il discorso è che la scheda wireless effettua “in hardware” la cifratura dei dati trasmessi e ricevuti. Questo inizia a diventare un problema se deve farlo per due reti,che quasi sicuramente devono cifrare i dati in modo diverso. Dunque il prezzo da pagare è che le cifrature non potranno essere fatte sulla scheda ma dal nostro processore.

Supponiamo di avere una scheda che usa driver ath5k, vediamo quali passi seguire (sono gli stessi anche per le schede con driver ath9k):

modprobe -r ath5k

modprobe ath5k nohwcrypt=1

Così abbiamo disattivato il driver della scheda e lo abbiamo riabilitato con l’opzione per disabilitare la cifratura hardware.

iw phy phy0 interface add wlan1 type station

In questo modo abbiamo aggiunto un’altra interfaccia oltre alla già presente wlan0. Il mac address della interfaccia generata wlan1 sarà uguale a quello dell’altra. La cosa non ci piace ovviamente e vogliamo che le due schede abbiano due mac address differenti, di modo da apparire esattamente come se fossero due schede di due computer diversi. Per ovviare al problema possiamo usare ifconfig come prima:

ifconfig wlan1 hw ether 00:11:22:33:44:55

Oppure se vogliamo evitare di doverci inventare un mac address al volo possiamo usare macchanger (non è incluso di default in quasi nessuna distribuzione Linux):

macchanger -A wlan1

In questo modo il mac address impostato sarà casuale (ma non così casuale da rendere evidente che si tratti di un mac address falso).

Ok, abbiamo le nostre due interfacce virtuali wireless. Supponiamo che le reti necessitino autenticazione WPA.

iwconfig wlan0 essid “Rete1”
wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant_rete1.conf &
dhclient wlan0
iwconfig wlan1 essid “Rete2”
wpa_supplicant -Dwext -iwlan1 -c/etc/wpa_supplicant_rete2.conf  &
dhclient wlan1

Ora saremo collegati ad entrambe le reti. Nota: su altre distribuzioni potrebbe essere necessario utilizzare dhcpcd al posto di dhclient.

Ed ora come prima procediamo al bonding delle interfacce:

modprobe bonding mode=0 miimon=100

ifconfig wlan0 down
ifconfig wlan1 down

ifconfig bond0 hw ether 00:11:22:33:44:55
ifconfig bond0 192.168.55.55 up

ifenslave bond0 wlan0
ifenslave bond0 wlan1

Esattamente come prima.

Questo esempio non l’ho provato personalmente e potrebbe esserci qualche problema con wpa_supplicant quando le interfacce vengono spente. Tuttavia ho voluto comunque mostrarlo giusto per dare un’idea di quello che bisogna fare e per introdurre al prossimo passo.

Ricordiamoci sempre:

echo 0 > /proc/sys/net/ipv4/conf/wlan0/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/wlan1/rp_filter

Reti wireless completamente separate o rete unica limitata

Come detto prima, il fatto di avere una linea a monte veloce e solo “colli di bottiglia” sugli access points è una cosa abbastanza rara. Solitamente se siamo in una situazione del genere è perché dal nostro computer possiamo collegarci a due reti wireless diverse, collegate a due linee completamente separate tra loro e con indirizzi diversi (magari nella stessa sottorete locale 192.168.0.x, però comunque i dati dell’una non transitano sull’altra e viceversa).
Situazione leggermente diversa ma completamente analoga dal punto di vista tecnico è invece quando siamo collegati ad un unico access point che ci immette in una rete dove la banda è limitata per ogni indirizzo ip o mac address e non possiamo ricevere i pacchetti degli altri host. In una rete del genere, a differenza del caso precedente, non possiamo fare bonding perché comunque riunendo le interfacce in una unica l’ip e il mac address sarebbero unici, rendendo vana l’operazione di bonding (permane la limitazione di banda).

Un modo leggermente complicato ma funzionante che ho personalmente escogitato a seguito di una serie di tentativi è quello che vi spiegherò qui di seguito.

L’idea principale è: ok, non possiamo in nessun modo fare bonding sulla rete perché sono separate tra di loro e hanno indirizzi diversi etc.., però se io in qualche modo riesco a collegarmi ad entrambe e quindi ad aprire una VPN su ciascuna delle due, e la VPN è di tipo TAP (simula completamente il protocollo ethernet), ed è unificata come indirzzi etc.. Posso in linea teorica mettere in bonding non le interfacce wireless ma le interfacce TAP della VPN e aumentare la banda. Ovviamente questo ha il “costo” di dover avere un server OpenVPN raggiungibile da entrambe le reti. Se le reti sono collegate entrambe ad Internet ci basta avere un server OpenVpn accessibile direttamente da Internet.

Riprendiamo l’esempio di prima e supponiamo che le reti “Rete1” e “Rete2”  siano totalmente scorrelatte tra loro. Se troviamo un modo per aprire un processo di openvpn su wlan0 (che si collega a “Rete1”) e un altro processo di openvpn (che si collega a “Rete2”) avremo due interfacce di tipo TAP chiamate ad esempio tap0 e tap1.
Le vpn avviate sono due istanze della stessa.

Il fatto di mettere in bonding tap0 e tap1 implica che esse perderanno il proprio ip della vpn (ad esempio 10.0.0.2 e 10.0.0.3) per conferire un unico indirizzo a bond0 (ad esempio 10.0.0.4) ed un unico mac address. Questo non è un problema dal momento che stiamo usando interfacce di tipo TAP, infatti TAP simula ethernet e dunque la situazione dal punto di vista del bonding sarà esattamente la stessa del primo esempio che abbiamo visto con la rete cablata!

Come detto prima lo stesso esempio è valido anche per reti a banda limitata. Supponiamo ci sia una rete chiamata “Rete1” a cui ci colleghiamo con entrambe le interfacce wifi. La limitazione ci viene applicata in base all’ip e/o mac address oppure anche a livello di certificato/password di autenticazione. Nessun problema:in ogni caso ci colleghiamo due volte con le due interfacce alla stessa rete ed abbiamo due ip e due mac address distinti (chi controlla la rete wireless non riuscirà a capire che la connessione avviene dallo stesso computer) e apriamo due VPN, poi mettiamo in bonding le interfacce della VPN e abbiamo raddoppiato la banda! Magari la rete ci limita tanto ma ha grande banda in realtà.. Dunque nessuno ci vieta di creare 30 interfacce wireless virtuali e 30 vpn, una per ciascuna interfaccia wireless virtuale, e poi mettere in bonding le 30 vpn. In linea teorica possiamo proseguire all’infinito, supposto che il server della VPN abbia ovviamente più banda di quella che ci viene limitata.. Se il serve della vpn è collegato ad internet con una linea da 1Mb/s, sicuramente in ogni caso con questo metodo non potremo superare quella velocità. Comunque dimenticando questo piccolo dettaglio (se come server VPN usiamo un server hostato in qualche serverfarm avremo probabilmente una linea da 100Mb/s) il numero di interfacce wifi virtuali è potenzialmente illimitato!
Ovviamente dopo un certo numero di interfacce inizieremo ad avere un carico del sistema esagerato e forse non riusciremo più ad aumentare la banda a causa del casino di pacchetti in gioco.. Però non ho dati per confermarlo.

È vero: sembra tutto molto facile, però c’è un dettaglio su cui ho puntato poco l’attenzione. Abbiamo detto che per poter fare tutta questa bellezza è necessario avviare diversi processi di openvpn che “escano” ciascuno su una interfaccia wireless diversa. La cosa non è per niente banale, infatti nella configurazione di OpenVpn non è possibile specificare una interfaccia di rete da cui collegarsi (come in nessun altro programma, a meno che utilizzi socket raw), inoltre per come sono strutturate le tabelle di routing, esiste sempre una ed una sola regola per decidere come indirizzare il traffico, la così detta “route default”, quindi tutti gli openvpn andrebbero ad uscire dalla stessa scheda, lasciando inutilizzate le altre. Non è quello che vogliamo noi!

Ma non disperate, c’è un hack anche per questo!

In iptables, il gestore delle tabelle di netfilter (il modulo del kernel Linux che si occupa della rete, firewalling etc..), esiste una “tabella” chiamata “mangle” che permette di applicare dei marcatori a dei pacchetti sotto alcune condizioni. Inoltre tramite il comando “ip”, che gestisce il routing del sistema, è possibile creare delle tabelle di routing “alternative” se il pacchetto in arrivo è stato marcato dalla tabella mangle.
Uno dei metodi che supporta iptables per marcare i pacchetti è quello di guardare il GID (Group ID), cioè il gruppo a cui appartiene il processo che ha originato il pacchetto.

Beh ma allora è fatta! I passi che dovremo seguire sono questi: avviamo ogni processo di OpenVpn con un gruppo diverso (il comando sg cioè “Set Group” permette di impostare il gruppo a cui appartiene un certo processo da eseguire), poi impostiamo iptables mangle di modo che quando vede un pacchetto in uscita proveniente da un certo gruppo assegna un certo marcatore. Infine facciamo in modo (mediante il comando ip per gestire le tabelle di routing), che quando c’è un pacchetto in uscita con un certo marcatore applicato, venga utilizzata una certa regola di routing e che esca quindi su una certa interfaccia di rete specifica! È fatta! Possiamo far uscire ogni processo di OpenVpn da una interfaccia virtuale diversa! Ricordiamoci alla fine di tutto di impostare il gateway di default nuovo che sarà il server della vpn (che deve essere abilitato per fare masquerading). Ovviamente ci sono tanti altri piccoli dettagli in più, li vediamo ora.

Riassumiamo i vari comandi principali da eseguire nel caso di due interfacce virtuali, due gruppi wifi0 e wifi1 esistenti nel sistema:

modprobe -r ath5k
modprobe ath5k nohwcrypt=1

iw phy phy0 interface add wlan1 type station

echo 0 > /proc/sys/net/ipv4/wlan0/rp_filter
echo 0 > /proc/sys/net/ipv4/wlan1/rp_filter

macchanger -A wlan1

ifconfig wlan0 up
iwconfig wlan0 essid “Rete”
wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant.conf &
dhcpcd -p wlan0
killall dhcpcd

ifconfig wlan1 up
iwconfig wlan1 essid “Rete”
wpa_supplicant -Dwext -iwlan1 -c/etc/wpa_supplicant.conf &
dhcpcd -p wlan1
killall dhcpcd

iptables -t mangle -A OUTPUT -m owner –gid-owner wifi0 -j MARK –set-mark 1
iptables -t mangle -A OUTPUT -m owner –gid-owner wifi1 -j MARK –set-mark 2

iptables -t nat -A POSTROUTING -o wlan0 -m mark –mark 01 -j SNAT –to-source  IP_DI_WLAN0
iptables -t nat -A POSTROUTING -o wlan1 -m mark –mark 02 -j SNAT –to-source  IP_DI_WLAN1

ip rule add fwmark 1 table 1
ip rule add fwmark 2 table 2

ip route add default via GATEWAY__DEFAULT_DI_WLAN0 dev wlan0 table 1
ip route add default via GATEWAY__DEFAULT_DI_WLAN1 dev wlan1 table 2

sg wifi0 -c “openvpn –config /etc/openvpn/client.conf” –ifconfig 10.0.0.2 255.255.255.0″
sg wifi0 -c “openvpn –config /etc/openvpn/client.conf” –ifconfig 10.0.0.3 255.255.255.0″

modprobe bonding miimon=100 mode=0

ifconfig tap0 down
ifconfig tap1 down

ifconfig bond0 hw ether 00:22:13:72:A1:5A
ifconfig bond0 10.0.0.4 up

ifenslave bond0 tap0
ifenslave bond0 tap1

route del default dev wlan0
route del default dev wlan1

route add default gw 10.0.0.1 dev bond0
echo “nameserver 208.67.222.222” > /etc/resolv.conf

Ancora come prima sorridiamo all’idea che utilizzando questa configurazione non solo aumentiamo la banda, ma possiamo garantirci sempre la connettività se una delle due reti dovesse “cadere” e possiamo inoltre aggiungere altre in tempo reale con relativamente poche operazioni!

Per altri dettagli sul modulo bonding vi rimando a questa pagina di documentazione.


DNS tunneling

05Feb11

Qualche volta può capitare di trovarsi, per vari motivi, collegati ad una rete wifi o cablata che è in qualche modo connessa ad Internet, ma non ci potete accedere direttamente.

Se sulla stessa rete c’è un server DNS, oppure vi è permesso in generale effettuare connessioni su Internet ma solo verso server DNS, iodine potrebbe fare al caso vostro. Iodine è infatti un programma, composto da una parte server-side e una parte client-side che vi permette di stabilire un tunnel di scambio dati, basato sull’invio e la recezione di richieste DNS. Le possibilità sono due:

Rete che permette connessioni verso server DNS arbitrari

Cioè stiamo parlando di una rete in cui i dati che voi mandate su internet vengono filtrati e accettati solo se sono diretti alla porta UDP 53 di qualche server, oppure se una volta analizzati risultano richieste di tipo DNS.

In questo caso la questione è abbastanza semplice. Andiamo su un nostro server con indirizzo pubblico e lanciamo

iodined -f 10.0.0.1 dominio.test

Ci sarà richiesta una password, che sarà poi utilizzata per autenticarci nel tunnel (è una protezione molto blanda, non fateci troppo affidamento); il “dominio.test” in questo caso non ha rilevanza e può essere qualunque cosa (purché poi lo si usi uguale sul client), vederemo nel prossimo esempio a cosa serve.
Sul server sarà creata una interfaccia di tipo TUN con nome “dns0”, che avrà indirizzo 10.0.0.1 come specificato dal parametro passato

A questo punto andiamo sul client e lanciamo il programma che si collegherà a iodoned sul nostro serve e farà viaggiare i pacchetti sulle richieste DNS

iodine -f 123.456.789.10 dominio.test

Dove 123.456.789.10 è l’ip del nostro server, che in questo caso farà da “finto” server dns. Ci sarà richiesta la password e inseriamo la stessa di prima. Il programma procederà poi a calcolare la dimensione dei pacchetti da utilizzare per la comunicazione andando a tentativi.
Ovviamente anche sul client avremo una interfaccia “dns0” con il relativo ip, probabilmente successivo a quello del server, quindi 10.0.0.2

Io in diversi test la rete 10.0.0.0 l’avevo già occupata, e per non fare confusione ho utilizzato la 172.16.0.0

Rete che permette connessioni verso un unico server DNS

Siete in una rete da cui non potete in nessun modo accedere ad internet, però con qualche colpo di nslookup vi accorgete che il DNS della rete locale/DNS predefinito assegnato dal dhcp, vi risolve qualunque indirizzo.
Anche qui iodine vi da una comoda mano, ma questa volta bisogna aggiungere alcuni dettagli.

Questa volta il tunnel funzionerà in modo diverso: non vi collegherete infatti direttamente all’altro capo, ma dovrete passare sempre per l’intermediario che è il server DNS della rete locale.

Supponiamo di avere un dominio mydomain.com , possiamo andare nel pannello di amministrazione del nostro dominio impostiamo che ad esempio tutte le richieste dirette a test.mydomain.com  e i relativi sottodomini vadano inoltrate a un certo server, che le gestirà.
Questo è possibile realizzarlo mediante un record di tipo “NS” nella tabella dei record del nostro dominio.

Magari abbiamo due record di questo tipo:

myserver       A       123.456.789.10
test       NS       myserver.mydomain.com.

In questo modo, se chiediamo al server DNS nella nostra rete locale di risolvere l’indirizzo aaaaaa.test.mydomain.com, lui andrà a vedere i record del dominio mydomain.com e noterà che test.mydomain.com viene affidato tramite NS ad un altro server, quindi contatta infine il server myserver.mydomain.com per richiedergli quale sia l’indirizzo associato a aaaaaa.test.mydomain.com .
Ovviamente nelle risposte il server potrà inserire tante informazioni, e dentro lì “nasconderà” i dati da inviare al client dall’altra parte del tunnel.

Supponiamo allora di aver impostato i nostri record del dns come mostrato sopra. A questo puto ci basterà rifare lo stesso comando dato prima sul server, con l’opportuno dominio:

iodined -f 10.0.0.1 test.mydomain.com

E allo stesso modo sul client:

iodine -f 123.456.789.10 test.mydomain.com

È importante in questo caso ricordare che appena possibile il DNS della nostra rete locale tenterà di fare la cache di quello che può, quindi se sbagliamo a impostare i record DNS e glieli facciamo risolvere, anche se poi li sistemiamo lui probabilmente avrà in cache ancora quelli errati.

Qualche volta non si capisce niente se sta funzionando o meno il tunnel, quindi i creatori di iodine hanno messo a punto una comoda pagina, in cui se inserite il vostro dominio di tunnel, loro tenteranno di collegarvisi e comparirà sulla pagina stessa se è funzionante o no. Eccola: http://code.kryo.se/iodine/check-it/

Suggerimenti

Uscire su Internet

“Sì, ok ho fatto tutto, ma ora? Posso solo fare il ping del mio host remoto, non posso uscire su Internet!”

Beh, poco ci vuole, basta che sul server preparate una NAT:

echo “1” > /proc/sys/net/ipv4/ip_forward

iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE

Se avete la policy DROP sulla chain FORWARD di iptables dovete aggiungere anche:

iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT

iptables -A FORWARD -d 10.0.0.0/24 -j ACCEPT

Mentre invece sul client dovremo prima aggiungere una regola statica di routing per il DNS della rete locale (altrimenti salta il tunnel quando cambiamo le route) e poi togliere la default e aggiungere la nuova:

route add IP_DNS_RETE_LOCALE gw GATEWAY_LOCALE

route add default gw 10.0.0.1

Abbiamo ipotizzato fino ad ora che il server DNS della rete locale risolva qualunque cosa, quindi non vi servirà cambiarlo, se volete farlo allora è consigliabile specificare l’ip del server dns della rete locale a iodine.

Sicurezza

La sicurezza della password per accedere al tunnel, come già detto è molto blanda. Se non ci sono eccessivi cali di prestazioni vi consiglio di non seguire quanto detto prima per uscire su internet e mettere una VPN sul vostro server ed uscire su internet una volta effettuato l’accesso a quella.

Versioni incompatibili

Fate molta attenzione alle versioni di iodine su server e client, se sono release di date molto diverse potrebbe non funzionare nulla!
Per controllare la versione lanciate (ovviamente):

iodine -v



Progetta un sito come questo con WordPress.com
Comincia ora