Servitore DHCP + Mysql in Python

Servitore DHCP + Mysql in Python

U scopu di stu prughjettu era:

  • Amparate nantu à DHCP in una reta IPv4
  • Amparate Python (un pocu più cà da zero 😉)
  • rimpiazzamentu di u servitore DB2DHCP (a mo furchetta), uriginale ccà, chì diventa sempre più difficiuli di assemblà per u novu OS. È ùn mi piace micca chì hè un binariu chì ùn ci hè manera di "cambià avà"
  • ottene un servitore DHCP chì funziona cù a capacità di selezziunà l'indirizzu IP di l'abbonatu utilizendu a mac di l'abbonatu o cambià a combinazione mac + portu (Opzione 82)
  • scrive una altra bicicletta (Oh! questa hè a mo attività preferita)
  • riceve cumenti nantu à u vostru club-handedness in Habrahabr (o megliu ancu, un invitu) 😉

Risultatu : funziona 😉 Testatu nantu à FreeBSD è Ubuntu OS. Teoricamente, u codice pò esse dumandatu à travaglià sottu ogni OS, perchè Sembra chì ùn ci hè micca ligami specifichi in u codice.
Attentu! Ci hè assai più à vene.

Link à u repository per dilettanti "toccu vivu".

U prucessu di stallà, cunfigurà è aduprà u risultatu di "studià l'hardware" hè assai più bassu, è dopu un pocu di teoria nantu à u protocolu DHCP. Per mè stessu. È per a storia 😉

Un pocu di teoria

Cosa hè DHCP

Questu hè un protokollu di rete chì permette à un dispositivu di scopre u so indirizzu IP (è altri parametri cum'è gateway, DNS, etc.) da un servitore DHCP. I pacchetti sò scambiati cù u protocolu UDP. U principiu generale di u funziunamentu di u dispusitivu quandu dumandà i paràmetri di a rete hè u seguente:

  1. U dispusitivu (cliente) manda una dumanda di trasmissione UDP (DHCPDISCOVER) in tutta a reta cù a dumanda "bene, qualcunu mi dà un indirizzu IP". Inoltre, di solitu (ma micca sempre) a dumanda si trova da u portu 68 (fonte), è a destinazione hè u portu 67 (destinazione). Certi dispositi mandanu ancu pacchetti da u portu 67. L'indirizzu MAC di u dispositivu cliente hè inclusu in u pacchettu DHCPDISCOVER.
  2. Tutti i servitori DHCP situati nantu à a reta (è ci ponu esse parechji di elli) formanu una offerta DHCPOFFER cù paràmetri di rete per u dispusitivu chì hà mandatu DHCPDISCOVER, è ancu emette nantu à a reta. L'identificazione di quale hè destinatu stu pacchettu hè basatu annantu à l'indirizzu MAC di u cliente furnitu prima in a dumanda DHCPDISCOVER.
  3. U cliente accetta pacchetti cù pruposte per i paràmetri di a rete, selezziunate u più attraente (i criterii ponu esse sfarenti, per esempiu, u tempu di consegna di pacchetti, u numeru di rotte intermedie), è face una "richiesta ufficiale" DHCPREQUEST cù i paràmetri di a rete. da u servitore DHCP li piace. In questu casu, u pacchettu va à un servitore DHCP specificu.
  4. U servitore chì hà ricivutu u DHCPREQUEST manda un pacchettu in formatu DHCPACK, in quale torna una volta lista i paràmetri di a rete destinati à stu cliente.

Servitore DHCP + Mysql in Python

Inoltre, ci sò pacchetti DHCPINFORM chì venenu da u cliente, è u scopu di quale hè di informà à u servitore DHCP chì u "cliente hè vivu" è utilizeghja i paràmetri di a rete emessi. In l'implementazione di stu servitore, sti pacchetti sò ignorati.

Formatu di pacchettu

In generale, un quadru di pacchettu Ethernet pare cusì cusì:

Servitore DHCP + Mysql in Python

In u nostru casu, cunsideremu solu i dati direttamente da u cuntenutu di u pacchettu UDP, senza l'intestazione di u protocolu di a capa OSI, vale à dì a struttura DHCP:

DHCP DISCOVER

Dunque, u prucessu di ottene un indirizzu IP per un dispositivu principia cù u cliente DHCP chì manda una dumanda di trasmissione da u portu 68 à 255.255.255.255:67. In questu pacchettu, u cliente include u so indirizzu MAC, è ancu ciò chì esattamente vole riceve da u servitore DHCP. A struttura di u pacchettu hè descritta in a tabella sottu.

Tabella di struttura di pacchetti DHCPDISCOVER

A pusizione in u pacchettu
Nome di valore
Esempiu:
Introduzione
Byte
Spiegazione

1
Richiesta di Boot
1
hex socket
1
Tipu di messagiu. 1 - dumanda da u cliente à u servitore, 2 - a risposta da u servitore à u cliente

2
Tipu di hardware
1
hex socket
1
Tipu di indirizzu hardware, in questu protokollu 1 - MAC

3
L'indirizzi hardware di a lunghezza
6
hex socket
1
Lunghezza di l'indirizzu MAC di u dispusitivu

4
U lupu
1
hex socket
1
Numero di rotte intermedie

5
ID di transazzione
23:cf:de:1d
hex socket
4
Identificatore unicu di transazzione. Generatu da u cliente à u principiu di una operazione di dumanda

7
Secondu passatu
0
hex socket
4
Tempu in seconde da u principiu di u prucessu di ottene un indirizzu

9
Bandiere di stivali
0
hex socket
2
Certi bandieri chì ponu esse stallati per indicà i paràmetri di u protocolu

11
Indirizzu IP di u cliente
0.0.0.0
Linea
4
Indirizzu IP di u cliente (se ci hè)

15
U vostru indirizzu IP di u cliente
0.0.0.0
Linea
4
Indirizzu IP offertu da u servitore (se dispunibule)

19
U prossimu indirizzu IP di u servitore
0.0.0.0
Linea
4
Indirizzu IP di u servitore (se cunnisciutu)

23
L'indirizzu IP di l'agente di relay
172.16.114.41
Linea
4
Indirizzu IP di l'agente di relay (per esempiu, un switch)

27
Indirizzu MAC di u cliente
14:d6:4d:a7:c9:55
hex socket
6
Indirizzu MAC di u mittente di u pacchettu (cliente)

31
Padding di indirizzu hardware di u cliente
 
hex socket
10
Sede riservata. Di solitu pienu di zeri

41
Nome d'ospite di u servitore
 
Linea
64
Nome di u servitore DHCP. Di solitu ùn hè micca trasmessu

105
Nome di u schedariu di boot
 
Linea
128
Nome di u schedariu nantu à u servitore utilizatu da stazioni senza discu quandu u booting

235
Biscotti magichi
63: 82: 53: 63
hex socket
4
Numeru "Magic", secondu chì, incl. pudete stabilisce chì stu pacchettu appartene à u protocolu DHCP

Opzioni DHCP. Pò andà in ogni ordine

236
U numeru d'opzione
53
Dec
1
Opzione 53, chì specifica u tipu di pacchettu DHCP

1 - DHCPDISCOVER
3 - DHCPREQUEST
2 - DHCPOFFER
5 - DHCPACK
8 - DHCPINFORM

 
Lunghezza di l'opzione
1
Dec
1

 
Valore di l'opzione
1
Dec
1

 
U numeru d'opzione
50
Dec
1
Chì indirizzu IP vole riceve u cliente?

 
Lunghezza di l'opzione
4
Dec
1

 
Valore di l'opzione
172.16.134.61
Linea
4

 
U numeru d'opzione
55
 
1
Paràmetri di rete dumandati da u cliente. A cumpusizioni pò varià

01 - Mascara di rete
03 - Gateway
06 - DNS
oc - Hostname
0f - nome di duminiu di a reta
1c - indirizzu di a dumanda di broadcast (broadcast)
42 - Nome di u servitore TFTP
79 - Strada statica senza classi

 
Lunghezza di l'opzione
8
 
1

 
Valore di l'opzione
01:03:06:0c:0f:1c:42:79
 
8

 
U numeru d'opzione
82
Dec
 
Opzione 82, chì trasmette l'indirizzu MAC di u dispusitivu ripetitore è qualchi valori supplementari.

A maiò spessu, questu hè u portu di u cambiamentu nantu à quale u cliente finale DHCP corre. Questa opzione cuntene paràmetri supplementari. U primu byte hè u numeru di "suboption", u sicondu hè a so lunghezza, dopu u so valore.

In questu casu, in l'opzione 82, i subopzioni sò nidificati:
Agent Circuit ID = 00:04:00:01:00:04, induve l'ultimi dui byte sò u portu di u cliente DHCP da quale a dumanda hè vinuta

Agent Remote ID = 00:06:c8:be:19:93:11:48 - Indirizzu MAC di u dispusitivu ripetitore DHCP

 
Lunghezza di l'opzione
18
Dec
 

 
Valore di l'opzione
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
hex socket
 

 
A fine di u pacchettu
255
Dec
1
255 simbulizeghja a fine di u pacchettu

DHCPOFFER

Appena u servitore riceve u pacchettu DHCPDISCOVER è s'ellu vede chì pò offre à u cliente qualcosa da quellu dumandatu, allora genera una risposta per questu - DHCPDISCOVER. A risposta hè mandata à u portu "da induve hè vinutu", per broadcast, perchè in questu mumentu, u cliente ùn hà ancu un indirizzu IP, per quessa pò accettà u pacchettu solu s'ellu hè mandatu da broadcast. U cliente ricunnosce chì questu hè un pacchettu per ellu da u so indirizzu MAC in u pacchettu, è ancu u numeru di transazzione chì genera à u mumentu chì u primu pacchettu hè creatu.

Tabella di struttura di pacchetti DHCPOFFER

A pusizione in u pacchettu
Nome di valore (cumune)
Esempiu:
Introduzione
Byte
Spiegazione

1
Richiesta di Boot
1
hex socket
1
Tipu di messagiu. 1 - dumanda da u cliente à u servitore, 2 - a risposta da u servitore à u cliente

2
Tipu di hardware
1
hex socket
1
Tipu di indirizzu hardware, in questu protokollu 1 - MAC

3
L'indirizzi hardware di a lunghezza
6
hex socket
1
Lunghezza di l'indirizzu MAC di u dispusitivu

4
U lupu
1
hex socket
1
Numero di rotte intermedie

5
ID di transazzione
23:cf:de:1d
hex socket
4
Identificatore unicu di transazzione. Generatu da u cliente à u principiu di una operazione di dumanda

7
Secondu passatu
0
hex socket
4
Tempu in seconde da u principiu di u prucessu di ottene un indirizzu

9
Bandiere di stivali
0
hex socket
2
Certi bandieri chì ponu esse stallati per indicà i paràmetri di u protocolu. In questu casu, 0 significa u tipu di dumanda Unicast

11
Indirizzu IP di u cliente
0.0.0.0
Linea
4
Indirizzu IP di u cliente (se ci hè)

15
U vostru indirizzu IP di u cliente
172.16.134.61
Linea
4
Indirizzu IP offertu da u servitore (se dispunibule)

19
U prossimu indirizzu IP di u servitore
0.0.0.0
Linea
4
Indirizzu IP di u servitore (se cunnisciutu)

23
L'indirizzu IP di l'agente di relay
172.16.114.41
Linea
4
Indirizzu IP di l'agente di relay (per esempiu, un switch)

27
Indirizzu MAC di u cliente
14:d6:4d:a7:c9:55
hex socket
6
Indirizzu MAC di u mittente di u pacchettu (cliente)

31
Padding di indirizzu hardware di u cliente
 
hex socket
10
Sede riservata. Di solitu pienu di zeri

41
Nome d'ospite di u servitore
 
Linea
64
Nome di u servitore DHCP. Di solitu ùn hè micca trasmessu

105
Nome di u schedariu di boot
 
Linea
128
Nome di u schedariu nantu à u servitore utilizatu da stazioni senza discu quandu u booting

235
Biscotti magichi
63: 82: 53: 63
hex socket
4
Numeru "Magic", secondu chì, incl. pudete stabilisce chì stu pacchettu appartene à u protocolu DHCP

Opzioni DHCP. Pò andà in ogni ordine

236
U numeru d'opzione
53
Dec
1
Opzione 53, chì definisce u tipu di pacchettu DHCP 2 - DHCPOFFER

 
Lunghezza di l'opzione
1
Dec
1

 
Valore di l'opzione
2
Dec
1

 
U numeru d'opzione
1
Dec
1
Opzione per offre à u cliente DHCP una maschera di rete

 
Lunghezza di l'opzione
4
Dec
1

 
Valore di l'opzione
255.255.224.0
Linea
4

 
U numeru d'opzione
3
Dec
1
Opzione per offre à u cliente DHCP un gateway predeterminatu

 
Lunghezza di l'opzione
4
Dec
1

 
Valore di l'opzione
172.16.12.1
Linea
4

 
U numeru d'opzione
6
Dec
1
Opzione per offre DHCP à u cliente DNS

 
Lunghezza di l'opzione
4
Dec
1

 
Valore di l'opzione
8.8.8.8
Linea
4

 
U numeru d'opzione
51
Dec
1
A vita di i paràmetri di a rete emessi in seconde, dopu chì u cliente DHCP deve dumandà di novu

 
Lunghezza di l'opzione
4
Dec
1

 
Valore di l'opzione
86400
Dec
4

 
U numeru d'opzione
82
Dec
1
Opzione 82, ripete ciò chì hè ghjuntu in DHCPDISCOVER

 
Lunghezza di l'opzione
18
Dec
1

 
Valore di l'opzione
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Dec
18

 
A fine di u pacchettu
255
Dec
1
255 simbulizeghja a fine di u pacchettu

DHCPREQUEST

Dopu chì u cliente riceve DHCPOFFER, forma un pacchettu chì dumanda i paràmetri di a rete micca à tutti i servitori DHCP in a reta, ma solu à unu specificu, chì l'offerta DHCPOFFER "piace" u più. I criteri "cum'è" ponu esse sfarenti è dipendenu da l'implementazione DHCP di u cliente. U destinatariu di a dumanda hè specificatu cù l'indirizzu MAC di u servitore DHCP. Inoltre, un pacchettu DHCPREQUEST pò esse mandatu da u cliente senza prima generà DHCPDISCOVER, se l'indirizzu IP di u servitore hè digià statu ottenutu prima.

DHCPREQUEST Tabella di struttura di pacchetti

A pusizione in u pacchettu
Nome di valore (cumune)
Esempiu:
Introduzione
Byte
Spiegazione

1
Richiesta di Boot
1
hex socket
1
Tipu di messagiu. 1 - dumanda da u cliente à u servitore, 2 - a risposta da u servitore à u cliente

2
Tipu di hardware
1
hex socket
1
Tipu di indirizzu hardware, in questu protokollu 1 - MAC

3
L'indirizzi hardware di a lunghezza
6
hex socket
1
Lunghezza di l'indirizzu MAC di u dispusitivu

4
U lupu
1
hex socket
1
Numero di rotte intermedie

5
ID di transazzione
23:cf:de:1d
hex socket
4
Identificatore unicu di transazzione. Generatu da u cliente à u principiu di una operazione di dumanda

7
Secondu passatu
0
hex socket
4
Tempu in seconde da u principiu di u prucessu di ottene un indirizzu

9
Bandiere di stivali
8000
hex socket
2
Certi bandieri chì ponu esse stallati per indicà i paràmetri di u protocolu. In questu casu, "broadcast" hè stabilitu

11
Indirizzu IP di u cliente
0.0.0.0
Linea
4
Indirizzu IP di u cliente (se ci hè)

15
U vostru indirizzu IP di u cliente
172.16.134.61
Linea
4
Indirizzu IP offertu da u servitore (se dispunibule)

19
U prossimu indirizzu IP di u servitore
0.0.0.0
Linea
4
Indirizzu IP di u servitore (se cunnisciutu)

23
L'indirizzu IP di l'agente di relay
172.16.114.41
Linea
4
Indirizzu IP di l'agente di relay (per esempiu, un switch)

27
Indirizzu MAC di u cliente
14:d6:4d:a7:c9:55
hex socket
6
Indirizzu MAC di u mittente di u pacchettu (cliente)

31
Padding di indirizzu hardware di u cliente
 
hex socket
10
Sede riservata. Di solitu pienu di zeri

41
Nome d'ospite di u servitore
 
Linea
64
Nome di u servitore DHCP. Di solitu ùn hè micca trasmessu

105
Nome di u schedariu di boot
 
Linea
128
Nome di u schedariu nantu à u servitore utilizatu da stazioni senza discu quandu u booting

235
Biscotti magichi
63: 82: 53: 63
hex socket
4
Numeru "Magic", secondu chì, incl. pudete stabilisce chì stu pacchettu appartene à u protocolu DHCP

Opzioni DHCP. Pò andà in ogni ordine

236
U numeru d'opzione
53
Dec
3
Opzione 53, chì definisce u tipu di pacchettu DHCP 3 - DHCPREQUEST

 
Lunghezza di l'opzione
1
Dec
1

 
Valore di l'opzione
3
Dec
1

 
U numeru d'opzione
61
Dec
1
ID di u cliente: 01 (per Ehernet) + indirizzu MAC di u cliente

 
Lunghezza di l'opzione
7
Dec
1

 
Valore di l'opzione
01:2c:ab:25:ff:72:a6
hex socket
7

 
U numeru d'opzione
60
Dec
 
"Identificatore di classa di venditore". In u mo casu, informa a versione di u cliente DHCP. Forse altri apparecchi tornanu qualcosa di sfarente. Windows per esempiu raporta MSFT 5.0

 
Lunghezza di l'opzione
11
Dec
 

 
Valore di l'opzione
udhcp 0.9.8
Linea
 

 
U numeru d'opzione
55
 
1
Paràmetri di rete dumandati da u cliente. A cumpusizioni pò varià

01 - Mascara di rete
03 - Gateway
06 - DNS
oc - Hostname
0f - nome di duminiu di a reta
1c - indirizzu di a dumanda di broadcast (broadcast)
42 - Nome di u servitore TFTP
79 - Strada statica senza classi

 
Lunghezza di l'opzione
8
 
1

 
Valore di l'opzione
01:03:06:0c:0f:1c:42:79
 
8

 
U numeru d'opzione
82
Dec
1
Opzione 82, ripete ciò chì hè ghjuntu in DHCPDISCOVER

 
Lunghezza di l'opzione
18
Dec
1

 
Valore di l'opzione
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Dec
18

 
A fine di u pacchettu
255
Dec
1
255 simbulizeghja a fine di u pacchettu

DHCPACK

Cum'è cunferma chì "sì, hè ghjustu, questu hè u vostru indirizzu IP, è ùn daraghju micca à nimu" da u servitore DHCP, un pacchettu in formatu DHCPACK da u servitore à u cliente serve. Hè mandatu broadcast cum'è altri pacchetti. Ancu s'ellu, in u codice quì sottu per un servitore DHCP implementatu in Python, solu in casu, duplicà ogni dumanda di broadcast mandendu un pacchettu à un IP cliente specificu, se hè digià cunnisciutu. Inoltre, u servitore DHCP ùn importa micca se u pacchettu DHCPACK hà righjuntu u cliente. Se u cliente ùn riceve micca DHCPACK, dopu un pocu tempu si ripete solu DHCPREQUEST

Tabella di struttura di pacchetti DHCPACK

A pusizione in u pacchettu
Nome di valore (cumune)
Esempiu:
Introduzione
Byte
Spiegazione

1
Richiesta di Boot
2
hex socket
1
Tipu di messagiu. 1 - dumanda da u cliente à u servitore, 2 - a risposta da u servitore à u cliente

2
Tipu di hardware
1
hex socket
1
Tipu di indirizzu hardware, in questu protokollu 1 - MAC

3
L'indirizzi hardware di a lunghezza
6
hex socket
1
Lunghezza di l'indirizzu MAC di u dispusitivu

4
U lupu
1
hex socket
1
Numero di rotte intermedie

5
ID di transazzione
23:cf:de:1d
hex socket
4
Identificatore unicu di transazzione. Generatu da u cliente à u principiu di una operazione di dumanda

7
Secondu passatu
0
hex socket
4
Tempu in seconde da u principiu di u prucessu di ottene un indirizzu

9
Bandiere di stivali
8000
hex socket
2
Certi bandieri chì ponu esse stallati per indicà i paràmetri di u protocolu. In questu casu, "broadcast" hè stabilitu

11
Indirizzu IP di u cliente
0.0.0.0
Linea
4
Indirizzu IP di u cliente (se ci hè)

15
U vostru indirizzu IP di u cliente
172.16.134.61
Linea
4
Indirizzu IP offertu da u servitore (se dispunibule)

19
U prossimu indirizzu IP di u servitore
0.0.0.0
Linea
4
Indirizzu IP di u servitore (se cunnisciutu)

23
L'indirizzu IP di l'agente di relay
172.16.114.41
Linea
4
Indirizzu IP di l'agente di relay (per esempiu, un switch)

27
Indirizzu MAC di u cliente
14:d6:4d:a7:c9:55
hex socket
6
Indirizzu MAC di u mittente di u pacchettu (cliente)

31
Padding di indirizzu hardware di u cliente
 
hex socket
10
Sede riservata. Di solitu pienu di zeri

41
Nome d'ospite di u servitore
 
Linea
64
Nome di u servitore DHCP. Di solitu ùn hè micca trasmessu

105
Nome di u schedariu di boot
 
Linea
128
Nome di u schedariu nantu à u servitore utilizatu da stazioni senza discu quandu u booting

235
Biscotti magichi
63: 82: 53: 63
hex socket
4
Numeru "Magic", secondu chì, incl. pudete stabilisce chì stu pacchettu appartene à u protocolu DHCP

Opzioni DHCP. Pò andà in ogni ordine

236
U numeru d'opzione
53
Dec
3
Opzione 53, chì definisce u tipu di pacchettu DHCP 5 - DHCPACK

 
Lunghezza di l'opzione
1
Dec
1

 
Valore di l'opzione
5
Dec
1

 
U numeru d'opzione
1
Dec
1
Opzione per offre à u cliente DHCP una maschera di rete

 
Lunghezza di l'opzione
4
Dec
1

 
Valore di l'opzione
255.255.224.0
Linea
4

 
U numeru d'opzione
3
Dec
1
Opzione per offre à u cliente DHCP un gateway predeterminatu

 
Lunghezza di l'opzione
4
Dec
1

 
Valore di l'opzione
172.16.12.1
Linea
4

 
U numeru d'opzione
6
Dec
1
Opzione per offre DHCP à u cliente DNS

 
Lunghezza di l'opzione
4
Dec
1

 
Valore di l'opzione
8.8.8.8
Linea
4

 
U numeru d'opzione
51
Dec
1
A vita di i paràmetri di a rete emessi in seconde, dopu chì u cliente DHCP deve dumandà di novu

 
Lunghezza di l'opzione
4
Dec
1

 
Valore di l'opzione
86400
Dec
4

 
U numeru d'opzione
82
Dec
1
Opzione 82, ripete ciò chì hè ghjuntu in DHCPDISCOVER

 
Lunghezza di l'opzione
18
Dec
1

 
Valore di l'opzione
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Dec
18

 
A fine di u pacchettu
255
Dec
1
255 simbulizeghja a fine di u pacchettu

rimarchevuli

A stallazione hè veramente custituita da installà i moduli python necessarii per u travagliu. Si assume chì MySQL hè digià stallatu è cunfiguratu.

FreeBSD

pkg install python3 python3 -m assurepip pip3 install mysql-connector

Ubuntu

sudo apt-get install python3 sudo apt-get install pip3 sudo pip3 install mysql-connector

Creemu una basa di dati MySQL, caricate u dump pydhcp.sql in questu, è cunfigurà u schedariu di cunfigurazione.

Cunfigurazione

Tutti i paràmetri di u servitore sò in un schedariu xml. File di riferimentu:

1.0 0.0.0.0 255.255.255.255 192.168.0.71 8600 1 255.255.255.0 192.168.0.1 host locale prova prova pydhcp option_8.8.8.8_hex:sw_port82:1:20 option_22_hex:sw_port82:2:16 option_18_hex:sw_mac:82:26 40 selezziunate ip, maschera, router, dns da l'utilizatori induve upper (mac) = upper ('{option_3_AgentRemoteId_hex}') è upper (port) = upper ('{option_1_AgentCircuitId_port_hex}') selezziunate ip, maschera, router, dns da l'utilizatori induve upper (mac) = upper ('{sw_mac}') è upper (port) = upper ('{sw_port82}') selezziunate ip, maschera, router, dns da l'utilizatori induve upper (mac) = upper ('{ClientMacAddress}') inserisci in a storia (id, dt, mac, ip, cumentu) valori (null, now (), '{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')

Avà in più detail nantu à i tags:

A sezione dhcpserver descrive i paràmetri basi per inizià u servitore, vale à dì:

  • host - quale indirizzu IP ascolta u servitore in u portu 67
  • broadcast - quale ip hè u broadcast per DHCPOFFER è DHCPACK
  • DHCPServer - quale hè l'ip di u servitore DHCP
  • LeaseTime tempu di affittu di l'indirizzu IP emessu
  • ThreadLimit - quanti fili sò in esecuzione simultaneamente per processà i pacchetti UDP in entrata in u portu 67. Hè suppostu per aiutà à i prughjetti di alta carica 😉
  • defaultMask,defaultRouter,defaultDNS - ciò chì hè offertu à l'abbonatu per difettu se una IP si trova in a basa di dati, ma paràmetri supplementari ùn sò micca specificati per questu

sezione mysql:

host, username, password, basename - tuttu parla per sè stessu. Una struttura di basa di dati apprussimata hè publicata GitHub

Sezione di dumanda: e dumande per riceve OFFERTA / ACK sò descritte quì:

  • offer_count - u numeru di linii cù richieste chì tornanu un risultatu cum'è ip, mask, router, dns
  • offer_n - stringa di dumanda. Se u ritornu hè viotu, allora eseguisce a seguente dumanda di offerta
  • history_sql - una dumanda chì scrive, per esempiu, à a "storia d'autorizazione" per un abbonatu

E dumande ponu include qualsiasi variabili da a sezione d'opzioni o opzioni da u protocolu DHCP.

Sezione Opzioni. Questu hè induve diventa più interessante. Quì pudemu creà variàbili chì pudemu usà più tardi in a sezione di dumanda.

Per esempiu:

option_82_hex:sw_port1:20:22

, sta linea di cumanda piglia tutta a linea chì hè vinuta in l'opzione di dumanda DHCP 82, in formatu hex, in u intervallu da 20 à 22 bytes inclusivi è a mette in a nova variabile sw_port1 (cambià u portu da induve a dumanda hè vinuta)

option_82_hex:sw_mac:26:40

, definisce a variabile sw_mac, pigliendu l'hex da u range 26:40

Pudete vede tutte l'opzioni pussibuli chì ponu esse aduprate in e dumande principiendu u servitore cù u -d switch. Videremu qualcosa cum'è questu logu:

--un pacchettu DHCPINFORM hè ghjuntu à u portu 67, da 0025224ad764, b'x91xa5xe0xa3xa5xa9-x8fx8a', ('172.30.114.25', 68) {'ClientMacAddress': '0025224ad764': '00ad7': '91ad5': '0ad3': '5ad9', b'x8xa8xe43xa0.0.0.0xa5.0xa0025224-x764fx172.30.128.13a' , ('00', 00) {'ClientMacAddress': '172.30.114.25ad308': '6ad1': '82ad12': '12ad53', b'x53xa55xe55xa60xa60xa61-x61fx82a' Jxd82d', 'HType': 'Ethernet', 'HostName': b'x82xa12xe01xa06xa00xa04-x00fx01a', 'ReqListDNS': True, 'ReqListDomainName': True, 'ReqListPerfowmRouterDiscover': True, 'ReqListRouter:'ReqListRouter,':' TrueS, 'ReqListRouter':' ReqListSubnetMask ': True, 'ReqListVendorSpecInfo': 00, 'RequestedIpAddress': '06', 'Vendor': b'MSFT 02', 'chaddr': '08ad00', 'ciaddr': '.06': '. flags ': b'x00x1', 'giaddr': '9', 'gpoz': 2, 'hlen': 82, 'hops': 12010600040001000602080006001, 'htype': 'MAC', 'magic_cookie': b' cx589Sc ', 'op': 'DHCPINFORM', 'option2': 82, 'option18': 82, 'option12': 01, 'option06': 00, 'option04': 00, 'option01': 00, 'option_06_byte' : b'x02x08x00x06x00x1x9x2x768x0.0.0.0x001x589' b'x2x1x06eXx89exb8xad', 'option_3_hex': '897', 'option_8_hex': '0.0.0.0:XNUMX option_XNUMX_str': "b'xXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXxXNUMXeXxXNUMXexbXNUMXxad'", 'result': False, 'secs': XNUMX, 'siaddr' : 'XNUMX', 'sw_mac': 'XNUMXeXNUMXebXNUMXad', 'sw_portXNUMX': 'XNUMX', 'xidbyte': b'

In cunsiquenza, pudemu chjappà qualsiasi variabile in {} è serà utilizatu in a query SQL.

Fighjemu per a storia chì u cliente hà ricevutu l'indirizzu IP:

Servitore DHCP + Mysql in Python

Servitore DHCP + Mysql in Python

U principiu di u servitore

./pydhcpdb.py -d -c config.xml

- d modalità di output di cunsola DEBUG
- c <filename> schedariu di cunfigurazione

Debriefing

È avà più dettagli nantu à l'implementazione di u servitore in Python. Hè un dulore. Python hè statu amparatu nantu à a mosca. Parechji mumenti sò fatti in u stilu di "wow, in qualchì modu l'aghju fattu travaglià". Ùn hè micca ottimizatu in tuttu, è lasciatu in questa forma principalmente per via di poca sperienza in u sviluppu di Python. Ampararaghju nantu à l'aspetti più interessanti di l'implementazione di u servitore in "codice".

Analizzatore di file di cunfigurazione XML

U modulu standard di Python xml.dom hè utilizatu. Sembra simplice, ma durante l'implementazione ci era una mancanza di documentazione chjara è esempi nantu à a reta cù stu modulu.

    tree = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") per elem in mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("host")[0].firstChild.data gconfig["mysql_username"]=elem.getElementsByTagName("username")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("password")[0].firstChild.data gconfig["mysql_basename"] =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") per elem in dconfig: gconfig["broadcast"]=elem.getElementsByTagName("broadcast")[0]. firstChild.data gconfig["dhcp_host"]=elem.getElementsByTagName("host")[0].firstChild.data gconfig["dhcp_LeaseTime"]=elem.getElementsByTagName("LeaseTime")[0].firstChild.data gconfig[" dhcp_ThreadLimit"]=int(elem.getElementsByTagName("ThreadLimit")[0].firstChild.data) gconfig["dhcp_Server"]=elem.getElementsByTagName("DHCPServer")[0].firstChild.data gconfig"]["Madhcp_Server"] =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig["dhcp_defaultRouter"] defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("query") per elem in qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[1].firstChild.data per num in range(int(gconfig["offerta_count"])): gconfig["offerta_"+str(num+1)]=elem.getElementsByTagName("offerta_"+str(num+0))[0].firstChild.data gconfig ["history_sql"]=elem.getElementsByTagName("history_sql")[XNUMX].firstChild.data options=tree.getElementsByTagName("opzioni") per l'elem in opzioni: node=elem.getElementsByTagName("opzione") per l'opzioni in node : optionsMod.append (options.firstChild.data)

Multithreading

Curiosamente, u multithreading in Python hè implementatu assai chjaramente è simplicemente.

def PacketWork(data,addr): ... # implementazione di l'analisi di u pacchettu in entrata è risponde à questu ... mentri True: data, addr = udp_socket.recvfrom (1024) # aspittendu u pacchettu UDP thread = threading.Thread ( target=PacketWork , args=(data,addr,)).start() # cum'è ghjuntu - lanciamu a funzione PacketWork definita prima in u fondu cù paràmetri mentre threading.active_count() >gconfig["dhcp_ThreadLimit"]: tempu. sleep(1) # se u numeru Ci hè più fili chì sò digià in esecuzione cà in i paràmetri, aspittemu finu à chì ci sò menu menu

Riceve / mandà pacchettu DHCP

Per intercepte i pacchetti UDP chì passanu per a carta di rete, avete bisognu di "aumentà" u socket:

udp_socket = socket.socket (socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) udp_socket.bind((gconfig["dhcp_host"],67))

, induve e bandiere sò:

  • AF_INET - significa chì u furmatu di l'indirizzu serà IP: portu. Ci pò ancu esse AF_UNIX - induve l'indirizzu hè datu da u nome di u schedariu.
  • SOCK_DGRAM - significa chì ùn accettemu micca un "pacchettu crudu", ma quellu chì hà digià passatu per u firewall, è cun un pacchettu parzialmente tagliatu. Quelli. ricevemu solu un pacchettu UDP senza u cumpunente "fisicu" di u pacchettu UDP. Sè vo aduprate a bandiera SOCK_RAW, allora avete ancu bisognu di analizà stu "wrapper".

Invià un pacchettu pò esse cum'è una trasmissione:

                    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #switch the socket to broadcast mode rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))

, è à l'indirizzu "da induve vene u pacchettu":

                        udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # cambia u socket à u modu multi-ascoltatore rz=udp_socket.sendto (packetack, addr)

, induve SOL_SOCKET significa u "livellu di protocolu" per l'opzioni di impostazione,

, opzione SO_BROADCAST chì u pacchettu di cascu hè "broadcast"

  L'opzione ,SO_REUSEADDR cambia u socket in u modu "assai ascoltatori". In teoria, ùn hè micca necessariu in questu casu, ma in unu di i servitori FreeBSD nantu à quale aghju pruvatu, u codice ùn hà micca travagliatu senza questa opzione.

Analisi di un pacchettu DHCP

Hè quì chì mi piaceva assai Python. Ci hè chì fora di a scatula permette di esse abbastanza flexible cù u bytecode. Permettenu di esse traduttu assai facilmente in valori decimali, strings è hex - i.e. questu hè ciò chì avemu bisognu di capiscenu a struttura di u pacchettu. Cusì, per esempiu, pudete ottene una gamma di bytes in HEX è solu bytes:

    res["xidhex"]=data[4:8].hex() res["xidbyte"]=data[4:8]

, imballate i bytes in una struttura:

res["flags"]=pack('BB',data[10],data[11])

Get IP da struttura:

res["ciaddr"]=socket.inet_ntoa(pack('BBBB',data[12],data[13],data[14],data[15]));

Et vice versa :

res=res+socket.inet_pton (socket.AF_INET, gconfig["dhcp_Server"])

Hè tuttu per avà 😉

Source: www.habr.com

Add a comment