
Iniettore di opzioni DHCP
Hai mai desiderato intercettare richieste DHCP e inserire qualche opzione DHCP extra, all’insaputa del mittente? Probabilmente no. Tuttavia, se mai dovesse servire, dhcpoptinj (si spera) ti aiuterà.
Ci possono essere molte ragioni per modificare le richieste DHCP, anche se è probabile che tu debba cercare un metodo molto migliore per risolvere il tuo problema. Forse non hai accesso al server/client DHCP e devi modificare le loro opzioni DHCP, forse il software DHCP è difficile da configurare (o non supporta ciò che vuoi fare), forse hai una configurazione molto complessa e/o insolita, o forse vuoi solo sperimentare l’invio di opzioni esotiche o malformate? C’è una piccola possibilità che dhcpoptinj possa effettivamente essere utile.
dhcpoptinj attende l’arrivo dei pacchetti in una coda netfilter. Si assicura che un pacchetto sia effettivamente un pacchetto BOOTP/DHCP e, in tal caso, procede a iniettare le opzioni. Ricalcola il checksum dell’intestazione IPv4, disabilita il checksum UDP (per una implementazione più semplice) e restituisce il pacchetto a netfilter.
Hai bisogno di una regola iptables per intercettare i pacchetti e inviarli a dhcpoptinj. Supponiamo di avere due interfacce collegate in bridge, eth0 ed eth1. Supponiamo di voler intercettare tutte le richieste BOOTP provenienti da eth0 e iniettare l’opzione informazioni agente relay (82/0x52). Inventiamo un payload stupido: una sotto-opzione ID circuito agente con il valore “Fjas”.
Aggiungi una regola alla tabella mangle di iptables: sudo iptables -t mangle -A PREROUTING -m physdev --physdev-in eth0 -p udp --dport 67 -j NFQUEUE --queue-num 42.
Quindi esegui dhcpoptinj (eseguiamolo in primo piano con output di debug extra):
sudo dhcpoptinj -d -f -q 42 -o'52 01 04 46 6A 61 73'. Nota che dhcpoptinj deve essere eseguito da un utente con la capacità CAP_NET_ADMIN. Non è necessario, e non dovresti, eseguire dhcpoptinj come root. Invece, puoi ad esempio concedere la capacità CAP_NET_ADMIN al binario (usando setcap) e limitare i diritti di esecuzione a un utente o gruppo specifico. Questo è un metodo usato per eseguire wireshark come non-root, quindi troverai diverse guide che ti aiutano a realizzarlo.
Ora invia un pacchetto DHCP all’interfaccia eth0 e osservalo (usando uno strumento come wireshark) mentre viene modificato quando raggiunge l’interfaccia bridge. Dovrebbe avere l’opzione iniettata alla fine dell’elenco delle opzioni. Se catturi il pacchetto DHCP in arrivo con Wireshark, apparirà non modificato anche se in realtà è stato alterato.
Nota il formato dell’argomento per l’opzione -o: deve essere una stringa esadecimale che inizia con il codice dell’opzione DHCP seguita dal payload dell’opzione. La lunghezza dell’opzione (il byte che di solito segue il codice dell’opzione) viene calcolata automaticamente e non deve essere specificata. La stringa esadecimale può essere delimitata da caratteri non esadecimali per migliorare la leggibilità. Tutte le opzioni devono avere un payload, tranne la speciale opzione di riempimento (codice 0).
La struttura dell’opzione insensata usata in questo esempio (prima la struttura dell’opzione DHCP, poi la specifica struttura della sotto-opzione dell’opzione informazioni agente relay) è la seguente:
| Codice | Lunghezza | Dati |
|---|---|---|
| 52 | (auto) | 01 04 46 6A 61 73 ("Fjas") |
| Sotto-opt. | Lunghezza | Dati |
|---|---|---|
| 01 | 4 | 46 6A 61 73 ("Fjas") |
Nota che dhcpoptinj non si preoccupa di ciò che scrivi nei payload delle opzioni, né verifica se il codice dell’opzione esiste. Tuttavia, ti vieta di usare il codice opzione 255 (l’opzione di terminazione). dhcpoptinj inserisce questa opzione automaticamente come ultima opzione.
dhcpoptinj -f -d -q42 -r -o'0C 66 6A 61 73 65 68 6F 73 74' -o'52 01 04 46 6A 61 73' -o 320A141E28
3 DHCP option(s) to inject (with a total of 25 bytes): 12 (0x0C) (Hostname), 82 (0x52) (Relay Agent Information), 50 (0x32) (Address Request)
Existing options will be removed
Initialising netfilter queue
Initialising signal handler
Initialisation completed. Waiting for packets to mangle on queue 42
Received 416 bytes
Inspecting 328-byte DHCP packet from B6:40:FE:41:30:DC to 255.255.255.255:67
Mangling packet
Found option 53 (0x35) (DHCP message type) DHCPREQUEST (copying)
Found option 54 (0x36) (DHCP Server Id) with 4-byte payload 0A 14 1E 01 (copying)
Found option 50 (0x32) (Address Request) with 4-byte payload 0A 14 1E 28 (removing)
Found option 12 (0x0C) (Hostname) with 12-byte payload 33 31 36 64 65 39 31 34 64 61 62 34 (removing)
Found option 55 (0x37) (Parameter List) with 13-byte payload 01 1C 02 03 0F 06 77 0C 2C 2F 1A 79 2A (copying)
Found END option (removing)
Injecting option 12 (0x0C) (Hostname) with 9-byte payload 66 6A 61 73 65 68 6F 73 74
Injecting option 82 (0x52) (Relay Agent Information) with 6-byte payload 01 04 46 6A 61 73
Injecting option 50 (0x32) (Address Request) with 4-byte payload 0A 14 1E 28
Inserting END option
Padding with 10 byte(s) to meet minimal BOOTP payload size
Sending mangled packet
dhcpoptinj è presente in Debian/Ubuntu. Il pacchetto deb è sotto controllo sorgente su salsa. Si consiglia di installare dhcpoptinj dal pacchetto deb anziché seguire la procedura di installazione manuale descritta di seguito, perché include anche una pagina man, regole di completamento bash, file di esempio, ecc.
Hai bisogno di cmake e libnetfilter_queue (e un compilatore C che supporti C99). Si spera che tu stia usando un sistema Debian-like, nel qual caso puoi eseguire il seguente comando per installarli: sudo apt-get install cmake libnetfilter-queue-dev.
git clone git://github.com/misje/dhcpoptinjcd dhcpoptinjmkdir build && cd buildcmake .. (oppure cmake -DCMAKE_BUILD_TYPE=Debug .. se vuoi una build di debug)make -j4sudo make installsudo make uninstall dalla tua directory di buildLa directory di build con tutto il suo contenuto può essere rimossa in sicurezza. Se non hai usato una directory di build, puoi eliminare tutta la spazzatura di cmake eseguendo git clean -dfx. Nota, tuttavia, che questo rimuove tutto nella directory del progetto che non è sotto controllo sorgente.
dhcptopinj tenterà di analizzare /etc/dhcpoptinj.conf o il file passato con -c/--conf-file. La sintassi del file di configurazione è:
Gli spazi bianchi sono opzionali. Qualsiasi carattere dopo e incluso # è considerato un commento. Le opzioni DHCP sono elencate una per una come opzione=01:02:03. Le virgolette attorno alla stringa esadecimale dell’opzione sono opzionali e i byte possono essere separati da un numero qualsiasi di caratteri non esadecimali.
Le opzioni version, help e conf-file non sono accettate in un file di configurazione.
Esempio:
# Esegui in primo piano:
foreground
# Abilita output di debug:
debug
# Sovrascrivi hostname a "fjasehost":
option = '0C 66 6A 61 73 65 68 6F 73 74'
# Invia ID agente "Fjas":
option = "52:01:04:46:6A:61:73"
# Sovrascrivi richiesta di indirizzo per chiedere 10.20.30.40:
option=320A141E28
# Usa coda 12:
queue = 12
remove-existing-opt # Rimuovi le opzioni prima di inserirle
Questo readme dovrebbe averti aiutato a iniziare. Dai anche un’occhiata alla pagina man (nel pacchetto deb) e all’output di aiuto (dhcpoptinj -h), che dovrebbe coprire tutto ciò che l’utility ha da offrire.
Per bug e suggerimenti, per favore apri una issue.
dhcpoptinj è semplice e si spera che rimanga tale. Tuttavia, le seguenti sono funzionalità mancanti che si spera verranno aggiunte un giorno:
Impossibile associare il gestore della coda ad AF_INET: Operazione non consentita
Molto probabilmente non hai la capacità CAP_NET_ADMIN o c’è un altro processo (forse un’altra istanza di dhcpoptinj?) associato allo stesso numero di coda netfilter.
Perdita di memoria in caso di uscita non normale.
Questa non è considerata una perdita. Tuttavia, non dovrebbe esserci perdita di memoria in caso di uscita normale (catturando SIGTERM, SIGINT o SIGHUP).
Quando crei regole iptables da usare con dhcpoptinj, le seguenti opzioni possono essere utili:
--queue-bypass
Non scartare i pacchetti, ma lasciali passare se dhcpoptinj non è in esecuzione (o non sta ascoltando sul numero di coda corretto).
Se hai suggerimenti, per favore lascia una issue e ti risponderò. Sei il benvenuto a contribuire e le pull request sono molto apprezzate.
Se trovi dhcpoptinj utile, mi piacerebbe sapere per cosa lo stai usando. Aggiorna la pagina wiki e descrivi il tuo utilizzo.
Ho scelto di usare GPL per questo progetto. Se non è adatto a te, contattami e possiamo concordare una licenza diversa.