Python code for MAC address change

07 dicembre, 2018

Ogni interfaccia di rete ha un identificativo univoco denominato MAC address (Media Access Control) assegnato dal produttore. Quest'ultimo è assegnato a livello hardware ma è spesso possibile modificarlo a livello software.

Nel livello più basso del modello di rete l'indirizzo MAC è sostanzialmente utilizzato per far comunicare due interfacce di rete collegate a una rete. Oltre al suo uso classico nell'ambito networking, un indirizzo MAC viene utilizzato anche per altri scopi:

  • I server DHCP lo usano per impostare reservation di determinati indirizzi ip
  • Alcune reti consentono l'accesso solo a MAC address specificati (MAC address filtering, MAC authentication)
  • Per il suo essere univoco, può essere utilizzato per il device tracking

Il cambio del MAC address o MAC spoofing di un'interfaccia di rete non è necessariamente un'operazione malevola, ma in alcuni casi si. Cambiando MAC address è infatti possibile, per esempio, presentarsi con un MAC valido alle ACL di un router, oppure saltare in una specifica VLAN per effettuare successivamente uno sniffing.

Di seguito uno script python per la modifica del MAC address di un'interfaccia di rete in ambiente Linux.

#!/usr/bin/env python

import subprocess
import optparse


def get_arguments():
    parser = optparse.OptionParser()
    parser.add_option("-i", "--interface", dest="interface", help="Interfaccia da selezionare per il cambio MAC address")
    parser.add_option("-m", "--mac", dest="new_mac", help="Nuovo MAC address nel formato 00:00:00:00:00:00")

    (options, arguments) = parser.parse_args()
    if not options.interface:
        parser.error("[-] Specifica una interfaccia, usa --help per maggiori informazioni")
    elif not options.new_mac:
        parser.error("[-] Specifica un mac address, usa --help per maggiori informazioni")
    return options


def change_mac(interface, new_mac):
    print("[+] Cambio MAC address per l'interfaccia " + interface)

    subprocess.call(["ifconfig", interface, "down"])
    subprocess.call(["ifconfig", interface, "hw", "ether", new_mac])
    subprocess.call(["ifconfig", interface, "up"])


options = get_arguments()
change_mac(options.interface, options.new_mac)

E' possibile utilizzare il codice salvandolo in un file .py e richiamandolo come segue:

python mac_changer.py [opzioni]

Le opzioni da parsare allo script sono -i nomeinterfaccia e -m indirizzomac.

es.: python mac_changer.py -i eth0 -m 00:11:22:33:44:55

 

Ip reale su log Apache con reverse proxy Nginx

26 novembre, 2018

In una infrastruttura web che espone siti e servizi usando un reverse proxy Nginx davanti ai web server Apache, generalmente, accade che le chiamate fatte al server web hanno come sorgente il reverse proxy. Questo comporta che i file di log del server web registreranno come ip client sempre e solo l'ip del reverse proxy. Tutto questo anche se, Nginx, ha tra i suoi header HTTP X-Forwarded-For.

HTTP X-Forwarded-For contiene l'ip reale del client, ma, Apache di default non preleva i dati da questo header. Per abilitare questa funzione è necessario installare sul web server Apache il modulo mod_rpaf:

apt-get install libapache2-mod-rpaf

Dopo l'installazione del modulo, quest'ultimo va configurato inserendo il seguente codice all'interno del file /etc/apache2/mods-available/rpaf.conf

<IfModule mod_rpaf.c>
	RPAFenable On
	RPAFsethostname On
	RPAFproxy_ips xxx.xxx.xxx.xxx (indirizzo ip del reverse proxy)
</IfModule>

Salvato il file è necessario riavviare il web server Apache.

E' possibile anche forzare il passaggio degli header inserendo i seguenti parametri nel virtual host del reverse proxy Nginx:

proxy_set_header   Host             $host;
proxy_set_header   X-Real-IP        $remote_addr;
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

Python + Cron: creation of a hosts monitoring

07 aprile, 2014

In questo articolo vedremo i vari step per arrivare all’implementazione di un tool che, per conto nostro, si preoccupi di testare la raggiungibilità dei server e dei servizi di cui siamo amministratori. Partiamo innanzitutto dal presupposto di avere installata una distribuzione Linux, io ho utilizzato una Debian 7.4 (Wheezy). Il nostro obiettivo finale sarà quello di ricevere una email nel caso in cui uno dei nostri server non sia raggiungibile; per fare questo abbiamo bisogno di un paio di strumenti che consentano alla nostra Debian di inviare email. Il primo è un MUA (mail user agent), ovvero un client di posta. Debian è dotata di un MUA di nome Mail che è un client utilizzabile da riga di comando (proprio quello che fa al caso nostro). Il secondo strumento è un MTA (mail transfer agent), il daemon smtp che realmente si prende in carico il compito di inviare il messaggio. Esistono moltissimi MTA, come ad esempio Postfix, SendMail, ecc., io ho scelto Ssmtp perchè in modalità satellite funziona molto bene ed è semplicissimo da configurare.

N.B. Si dice modalità satellite quando un MTA non fa da server smtp ma si occupa soltanto di trasferire il messaggio ad un altro server smtp che poi lo invierà al destinatario. Ho scelto questa modalità perchè il nostro scopo è solo quello di inviare dei messaggi, non di implementare un server di posta.

Per installare Ssmtp su debian utilizziamo il comodissimo APT:

root@ibm:/home/draven#apt-get install ssmtp

Dopo averlo installato lo configuriamo editando il file /etc/ssmtp/ssmtp.conf. Questo file dovrà contenere le informazioni del reale server smtp che utilizzeremo per l’invio, un pò come quando si configura un client di posta elettronica, io ho utilizzato un mio account Gmail e quindi nel .conf ho scritto quanto segue:

root@ibm:/home/draven#nano /etc/ssmtp/ssmtp.conf
 
root=ilmioindirizzo@gmail.com
mailhub=smtp.gmail.com:587
AuthUser=ilmiousername
AuthPass=lamiapassword
UseSTARTTLS=YES
UseTLS=YES
AuthMethod=LOGIN

A questo punto la nostra Debian è in grado di inviare email. Passiamo ora alla creazione dello script che farà i test verso i nostri server. Lo script è in Python, un linguaggio di programmazione che per funzionare ha bisogno di un interprete e, anche qui la Debian ci aiuta perchè l’interprete Python è un pacchetto già installato sulla distribuzione. Il formato degli script python è .py, quindi creiamo un file nella posizione che vogliamo, con il nome che vogliamo e con estensione .py:

root@ibm:/home/draven#nano srvmon.py

All’interno del file che io ho chiamato srvmon.py andiamo a scrivere il nostro tool:

#! /usr/bin/env python
 
from os import system
from urllib2 import urlopen
from socket import socket
from sys import argv
from time import strftime
 
def tcp_test(server_info):
    cpos = server_info.find(':')
    try:
        sock = socket()
        sock.connect((server_info[:cpos], int(server_info[cpos+1:])))
        sock.close
        return True
    except:
        return False
 
def http_test(server_info):
    try:
        data = urlopen(server_info).read()
        return True
    except:
        return False
 
def server_test(test_type, server_info):
    if test_type.lower() == 'tcp':
        return tcp_test(server_info)
    elif test_type.lower() == 'http':
        return http_test(server_info)
 
def send_error(test_type, server_info, email_address):
    subject = '%s: %s %s errore' % (strftime("%d/%m/%Y %H:%M:%S"), test_type.upper(), server_info)
    message = 'Il test di tipo %s verso %s e' fallito, l'host e' down!' % (test_type.upper(), server_info)
    system('echo "%s" | mail -s "%s" %s' % (message, subject, email_address))
 
if __name__ == '__main__':
    if len(argv) != 4:
        print('Numero di argomenti errato.')
    elif not server_test(argv[1], argv[2]):
        send_error(argv[1], argv[2], argv[3])

Analizziamo questo script:

  1. nella prima parte vengono richiamate delle librerie usate all’interno dello script.
  2. il blocco tcp_test è la funzione che si occuperà di effettuare test tcp su una porta e un host passati come parametri.
  3. il blocco http_test è la funzione che si occuperà di effettuare test su protocollo http.
  4. il blocco server_test è la funzione che prende in carico i parametri passati allo script, li controlla e decide che tipo di test effettuare.
  5. il blocco send_error costruisce il messaggio da inviare e invoca il programma mail.
  6. l’ultimo blocco è di controllo, restituisce un errore se i parametri passati allo script non sono esatti, altrimenti richiama la funzione send_error.

A questo punto possiamo provare ad utilizzare manualmente lo script; nel caso in cui voglio effettuare un test tcp verso un host, i parametri da inviare allo script sono i seguenti:

root@ibm:/home/draven#python srvmon.py tcp drav.it:22 miamail@mioisp.it

oppure

root@ibm:/home/draven#python srvmon.py http http://www.drav.it miamail@mioisp.it

Nel primo caso, richiamo lo script e gli passo come parametri:
protocollo = tcp
host = drav.it
porta = 22
email del destinatario della notifica = miamail@mioisp.it

Nel secondo caso, il concetto è lo stesso ma, il test che eseguo è una richiesta http sulla porta 80 verso un host.

Ora quello che realmente ci interessa è automatizzare questo processo, per farlo utilizzeremo cron, una utility che nei sistemi operativi Unix Like si occupa di schedulare e automatizzare dei processi. Per modificare il cron e fargli avviare il nostro script digitiamo:

root@ibm:/home/draven#crontab -e

all’interno di cron inseriamo tante righe quanti sono gli host che vogliamo far controllare al nostro script, in questo modo:

*/5 * * * * python /home/draven/srvmon.py tcp host1:22 miamail@mioisp.it
*/5 * * * * python /home/draven/srvmon.py tcp host2:23 miamail@mioisp.it
*/5 * * * * python /home/draven/srvmon.py tcp host3:25 miamail@mioisp.it
ecc.

Fatto questo il cron avvierà ogni 5 minuti il controllo di tutti gli host che abbiamo inserito e lo script ci invierà una email nel caso in cui il test dell’host fallirà.

Home ← Discussioni più vecchie