Învățarea Python (puțin mai mult decât de la zero 😉)
înlocuirea serverului DB2DHCP (furculița mea), original aici, care devine din ce în ce mai greu de asamblat pentru noul sistem de operare. Și nu-mi place că este un binar care nu există nicio modalitate de a „schimba chiar acum”
obținerea unui server DHCP funcțional, cu capacitatea de a selecta adresa IP a abonatului folosind combinația mac a abonatului sau comutator mac+port (Opțiunea 82)
scriind o altă bicicletă (Oh! aceasta este activitatea mea preferată)
primirea de comentarii despre statutul tău de club pe Habrahabr (sau mai bine zis, o invitație) 😉
Rezultat: funcționează 😉 Testat pe FreeBSD și Ubuntu OS. Teoretic, codul poate fi solicitat să funcționeze sub orice sistem de operare, deoarece Se pare că nu există legături specifice în cod.
Cu grija! Mai sunt multe de urmat.
Link către depozitul pentru amatori "atinge viu".
Procesul de instalare, configurare și utilizare a rezultatului „studiului hardware-ului” este mult mai scăzut, iar apoi puțină teorie despre protocolul DHCP. Pentru mine. Și pentru istorie 😉
Puțină teorie
Ce este DHCP
Acesta este un protocol de rețea care permite unui dispozitiv să-și afle adresa IP (și alți parametri precum gateway, DNS etc.) de la un server DHCP. Pachetele sunt schimbate folosind protocolul UDP. Principiul general de funcționare a dispozitivului la solicitarea parametrilor de rețea este următorul:
Dispozitivul (clientul) trimite o cerere de difuzare UDP (DHCPDISCOVER) în întreaga rețea cu solicitarea „ei bine, cineva să-mi dea o adresă IP”. Mai mult, de obicei (dar nu întotdeauna) cererea apare de la portul 68 (sursă), iar destinația este portul 67 (destinația). Unele dispozitive trimit și pachete de la portul 67. Adresa MAC a dispozitivului client este inclusă în pachetul DHCPDISCOVER.
Toate serverele DHCP situate în rețea (și pot fi mai multe dintre ele) formează o ofertă DHCPOFFER cu setări de rețea pentru dispozitivul care a trimis DHCPDISCOVER și, de asemenea, o difuzează în rețea. Identificarea cui este destinat acest pachet se bazează pe adresa MAC a clientului furnizată mai devreme în cererea DHCPDISCOVER.
Clientul acceptă pachete cu propuneri de setări de rețea, îl selectează pe cel mai atractiv (criteriile pot fi diferite, de exemplu, ora livrării pachetelor, numărul de rute intermediare) și face o „cerere oficială” DHCPREQUEST cu setările de rețea de pe serverul DHCP care îi place. În acest caz, pachetul ajunge la un anumit server DHCP.
Serverul care a primit DHCPREQUEST trimite un pachet în format DHCPACK, în care listează din nou setările de rețea destinate acestui client
În plus, există pachete DHCPINFORM care provin de la client și al căror scop este de a informa serverul DHCP că „clientul este în viață” și utilizează setările de rețea emise. În implementarea acestui server, aceste pachete sunt ignorate.
Format pachet
În general, un cadru de pachet Ethernet arată cam așa:
În cazul nostru, vom lua în considerare doar datele direct din conținutul pachetului UDP, fără antete de protocol layer OSI, și anume structura DHCP:
DHCPDISCOVER
Deci, procesul de obținere a unei adrese IP pentru un dispozitiv începe cu clientul DHCP care trimite o solicitare de difuzare de la portul 68 la 255.255.255.255:67. În acest pachet, clientul include adresa sa MAC, precum și ce anume dorește să primească de la serverul DHCP. Structura pachetului este descrisă în tabelul de mai jos.
Tabelul structurii pachetelor DHCPDISCOVER
Poziție în pachet
Nume valoare
Exemplu
idee
Octet
clarificare
1
Solicitare de pornire
1
Hex
1
Tipul mesajului. 1 - cerere de la client la server, 2 - răspuns de la server la client
2
Tip hardware
1
Hex
1
Tipul adresei hardware, în acest protocol 1 - MAC
3
Lungimea adreselor hardware
6
Hex
1
Lungimea adresei MAC a dispozitivului
4
Hamei
1
Hex
1
Numărul de rute intermediare
5
ID tranzacție
23:cf:de:1d
Hex
4
Identificator unic de tranzacție. Generat de client la începutul unei operațiuni de solicitare
7
A trecut al doilea
0
Hex
4
Timp în secunde de la începutul procesului de obținere a unei adrese
9
Steaguri de boot
0
Hex
2
Anumite steaguri care pot fi setate pentru a indica parametrii protocolului
11
Adresa IP a clientului
0.0.0.0
rând
4
Adresa IP a clientului (dacă există)
15
Adresa IP a clientului dvs
0.0.0.0
rând
4
Adresa IP oferită de server (dacă este disponibilă)
19
Următoarea adresă IP a serverului
0.0.0.0
rând
4
Adresa IP a serverului (dacă este cunoscută)
23
Adresa IP a agentului de retransmisie
172.16.114.41
rând
4
Adresa IP a agentului de releu (de exemplu, un comutator)
27
Adresa MAC a clientului
14:d6:4d:a7:c9:55
Hex
6
Adresa MAC a expeditorului pachetului (client)
31
Complet cu adrese hardware client
Hex
10
Loc rezervat. De obicei umplute cu zerouri
41
Nume gazdă server
rând
64
Nume server DHCP. De obicei nu se transmite
105
Numele fișierului de pornire
rând
128
Numele fișierului pe server folosit de stațiile fără disc la pornire
235
Prajituri magice
63: 82: 53: 63
Hex
4
Număr „magic”, conform căruia, incl. puteți determina că acest pachet aparține protocolului DHCP
Opțiuni DHCP. Poate merge în orice ordine
236
Numărul opțiunii
53
decembrie
1
Opțiunea 53, care specifică tipul de pachet DHCP
Numărul opțiunii
50
decembrie
1
Ce adresă IP dorește să primească clientul?
Lungimea opțiunii
4
decembrie
1
Valoarea opțiunii
172.16.134.61
rând
4
Numărul opțiunii
55
1
Parametrii rețelei solicitați de client. Compoziția poate varia
01 — Mască de rețea
03 - Gateway
06 - DNS
oc — Nume gazdă
0f - nume de domeniu al rețelei
1c - adresa cererii de difuzare (difuzare)
42 - Nume server TFTP
79 - Rută statică fără clasă
Lungimea opțiunii
8
1
Valoarea opțiunii
01:03:06:0c:0f:1c:42:79
8
Numărul opțiunii
82
decembrie
Opțiunea 82, care transmite adresa MAC a dispozitivului repetitor și câteva valori suplimentare.
Cel mai adesea, acesta este portul switch-ului pe care rulează clientul DHCP final.Această opțiune conține parametri suplimentari.Primul octet este numărul „subopțiunii”, al doilea este lungimea acestuia, apoi valoarea sa.
În acest caz, în opțiunea 82, subopțiunile sunt imbricate:
ID circuit agent = 00:04:00:01:00:04, unde ultimii doi octeți sunt portul client DHCP de la care a venit cererea
Agent Remote ID = 00:06:c8:be:19:93:11:48 - adresa MAC a dispozitivului repetitor DHCP
Sfârșitul pachetului
255
decembrie
1
255 simbolizează sfârșitul pachetului
DHCPOFFER
Imediat ce serverul primește pachetul DHCPDISCOVER și dacă vede că poate oferi clientului ceva din cel solicitat, atunci generează un răspuns pentru acesta - DHCPDISCOVER. Răspunsul este trimis în portul „de unde a venit”, prin difuzare, pentru că în acest moment, clientul nu are încă o adresă IP, prin urmare poate accepta pachetul doar dacă este trimis prin difuzare. Clientul recunoaște că acesta este un pachet pentru el după adresa sa MAC din interiorul pachetului, precum și prin numărul tranzacției pe care îl generează în momentul creării primului pachet.
Tabelul structurii pachetelor DHCPOFFER
Poziție în pachet
Numele valorii (comun)
Exemplu
idee
Octet
clarificare
1
Solicitare de pornire
1
Hex
1
Tipul mesajului. 1 - cerere de la client la server, 2 - răspuns de la server la client
2
Tip hardware
1
Hex
1
Tipul adresei hardware, în acest protocol 1 - MAC
3
Lungimea adreselor hardware
6
Hex
1
Lungimea adresei MAC a dispozitivului
4
Hamei
1
Hex
1
Numărul de rute intermediare
5
ID tranzacție
23:cf:de:1d
Hex
4
Identificator unic de tranzacție. Generat de client la începutul unei operațiuni de solicitare
7
A trecut al doilea
0
Hex
4
Timp în secunde de la începutul procesului de obținere a unei adrese
9
Steaguri de boot
0
Hex
2
Anumite steaguri care pot fi setate pentru a indica parametrii protocolului. În acest caz, 0 înseamnă tipul de solicitare Unicast
11
Adresa IP a clientului
0.0.0.0
rând
4
Adresa IP a clientului (dacă există)
15
Adresa IP a clientului dvs
172.16.134.61
rând
4
Adresa IP oferită de server (dacă este disponibilă)
19
Următoarea adresă IP a serverului
0.0.0.0
rând
4
Adresa IP a serverului (dacă este cunoscută)
23
Adresa IP a agentului de retransmisie
172.16.114.41
rând
4
Adresa IP a agentului de releu (de exemplu, un comutator)
27
Adresa MAC a clientului
14:d6:4d:a7:c9:55
Hex
6
Adresa MAC a expeditorului pachetului (client)
31
Complet cu adrese hardware client
Hex
10
Loc rezervat. De obicei umplute cu zerouri
41
Nume gazdă server
rând
64
Nume server DHCP. De obicei nu se transmite
105
Numele fișierului de pornire
rând
128
Numele fișierului pe server folosit de stațiile fără disc la pornire
235
Prajituri magice
63: 82: 53: 63
Hex
4
Număr „magic”, conform căruia, incl. puteți determina că acest pachet aparține protocolului DHCP
Opțiuni DHCP. Poate merge în orice ordine
236
Numărul opțiunii
53
decembrie
1
Opțiunea 53, care definește tipul de pachet DHCP 2 - DHCPOFFER
Lungimea opțiunii
1
decembrie
1
Valoarea opțiunii
2
decembrie
1
Numărul opțiunii
1
decembrie
1
Opțiunea de a oferi clientului DHCP o mască de rețea
Lungimea opțiunii
4
decembrie
1
Valoarea opțiunii
255.255.224.0
rând
4
Numărul opțiunii
3
decembrie
1
Opțiune de a oferi clientului DHCP un gateway implicit
Lungimea opțiunii
4
decembrie
1
Valoarea opțiunii
172.16.12.1
rând
4
Numărul opțiunii
6
decembrie
1
Opțiunea de a oferi DHCP clientului DNS
Lungimea opțiunii
4
decembrie
1
Valoarea opțiunii
8.8.8.8
rând
4
Numărul opțiunii
51
decembrie
1
Durata de viață a parametrilor de rețea emiși în secunde, după care clientul DHCP trebuie să îi solicite din nou
Lungimea opțiunii
4
decembrie
1
Valoarea opțiunii
86400
decembrie
4
Numărul opțiunii
82
decembrie
1
Opțiunea 82, repetă ceea ce a venit în DHCPDISCOVER
Lungimea opțiunii
18
decembrie
1
Valoarea opțiunii
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
decembrie
18
Sfârșitul pachetului
255
decembrie
1
255 simbolizează sfârșitul pachetului
DHCPREQUEST
După ce clientul primește DHCPOFFER, el formează un pachet care solicită parametri de rețea nu tuturor serverelor DHCP din rețea, ci doar unuia anume, a cărui ofertă DHCPOFFER i-a „placut” cel mai mult. Criteriile „like” pot fi diferite și depind de implementarea DHCP a clientului. Destinatarul cererii este specificat folosind adresa MAC a serverului DHCP. De asemenea, un pachet DHCPREQUEST poate fi trimis de client fără a genera mai întâi DHCPDISCOVER, dacă adresa IP a serverului a fost deja obținută anterior.
Tabelul structurii pachetelor DHCPREQUEST
Poziție în pachet
Numele valorii (comun)
Exemplu
idee
Octet
clarificare
1
Solicitare de pornire
1
Hex
1
Tipul mesajului. 1 - cerere de la client la server, 2 - răspuns de la server la client
2
Tip hardware
1
Hex
1
Tipul adresei hardware, în acest protocol 1 - MAC
3
Lungimea adreselor hardware
6
Hex
1
Lungimea adresei MAC a dispozitivului
4
Hamei
1
Hex
1
Numărul de rute intermediare
5
ID tranzacție
23:cf:de:1d
Hex
4
Identificator unic de tranzacție. Generat de client la începutul unei operațiuni de solicitare
7
A trecut al doilea
0
Hex
4
Timp în secunde de la începutul procesului de obținere a unei adrese
9
Steaguri de boot
8000
Hex
2
Anumite steaguri care pot fi setate pentru a indica parametrii protocolului. În acest caz, „difuzare” este setat
11
Adresa IP a clientului
0.0.0.0
rând
4
Adresa IP a clientului (dacă există)
15
Adresa IP a clientului dvs
172.16.134.61
rând
4
Adresa IP oferită de server (dacă este disponibilă)
19
Următoarea adresă IP a serverului
0.0.0.0
rând
4
Adresa IP a serverului (dacă este cunoscută)
23
Adresa IP a agentului de retransmisie
172.16.114.41
rând
4
Adresa IP a agentului de releu (de exemplu, un comutator)
27
Adresa MAC a clientului
14:d6:4d:a7:c9:55
Hex
6
Adresa MAC a expeditorului pachetului (client)
31
Complet cu adrese hardware client
Hex
10
Loc rezervat. De obicei umplute cu zerouri
41
Nume gazdă server
rând
64
Nume server DHCP. De obicei nu se transmite
105
Numele fișierului de pornire
rând
128
Numele fișierului pe server folosit de stațiile fără disc la pornire
235
Prajituri magice
63: 82: 53: 63
Hex
4
Număr „magic”, conform căruia, incl. puteți determina că acest pachet aparține protocolului DHCP
Opțiuni DHCP. Poate merge în orice ordine
236
Numărul opțiunii
53
decembrie
3
Opțiunea 53, care definește tipul de pachet DHCP 3 - DHCPREQUEST
Lungimea opțiunii
1
decembrie
1
Valoarea opțiunii
3
decembrie
1
Numărul opțiunii
61
decembrie
1
ID client: 01 (pentru Ehernet) + adresa MAC a clientului
Lungimea opțiunii
7
decembrie
1
Valoarea opțiunii
01:2c:ab:25:ff:72:a6
Hex
7
Numărul opțiunii
60
decembrie
„Identificatorul clasei furnizorului”. În cazul meu, raportează versiunea client DHCP. Poate că alte dispozitive returnează ceva diferit. Windows, de exemplu, raportează MSFT 5.0
Lungimea opțiunii
11
decembrie
Valoarea opțiunii
udhcp 0.9.8
rând
Numărul opțiunii
55
1
Parametrii rețelei solicitați de client. Compoziția poate varia
01 — Mască de rețea
03 - Gateway
06 - DNS
oc — Nume gazdă
0f - nume de domeniu al rețelei
1c - adresa cererii de difuzare (difuzare)
42 - Nume server TFTP
79 - Rută statică fără clasă
Lungimea opțiunii
8
1
Valoarea opțiunii
01:03:06:0c:0f:1c:42:79
8
Numărul opțiunii
82
decembrie
1
Opțiunea 82, repetă ceea ce a venit în DHCPDISCOVER
Lungimea opțiunii
18
decembrie
1
Valoarea opțiunii
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
decembrie
18
Sfârșitul pachetului
255
decembrie
1
255 simbolizează sfârșitul pachetului
DHCPACK
Ca confirmare că „da, așa e, aceasta este adresa ta IP și nu o voi da nimănui” de pe serverul DHCP, un pachet în format DHCPACK de la server la client servește. Este transmis difuzat la fel ca alte pachete. Deși, în codul de mai jos pentru un server DHCP implementat în Python, pentru orice eventualitate, dublez orice solicitare de difuzare trimițând un pachet către un anumit IP client, dacă este deja cunoscut. Mai mult decât atât, serverului DHCP nu îi pasă deloc dacă pachetul DHCPACK a ajuns la client. Dacă clientul nu primește DHCPACK, atunci după un timp el repetă pur și simplu DHCPREQUEST
Tabelul structurii pachetelor DHCPACK
Poziție în pachet
Numele valorii (comun)
Exemplu
idee
Octet
clarificare
1
Solicitare de pornire
2
Hex
1
Tipul mesajului. 1 - cerere de la client la server, 2 - răspuns de la server la client
2
Tip hardware
1
Hex
1
Tipul adresei hardware, în acest protocol 1 - MAC
3
Lungimea adreselor hardware
6
Hex
1
Lungimea adresei MAC a dispozitivului
4
Hamei
1
Hex
1
Numărul de rute intermediare
5
ID tranzacție
23:cf:de:1d
Hex
4
Identificator unic de tranzacție. Generat de client la începutul unei operațiuni de solicitare
7
A trecut al doilea
0
Hex
4
Timp în secunde de la începutul procesului de obținere a unei adrese
9
Steaguri de boot
8000
Hex
2
Anumite steaguri care pot fi setate pentru a indica parametrii protocolului. În acest caz, „difuzare” este setat
11
Adresa IP a clientului
0.0.0.0
rând
4
Adresa IP a clientului (dacă există)
15
Adresa IP a clientului dvs
172.16.134.61
rând
4
Adresa IP oferită de server (dacă este disponibilă)
19
Următoarea adresă IP a serverului
0.0.0.0
rând
4
Adresa IP a serverului (dacă este cunoscută)
23
Adresa IP a agentului de retransmisie
172.16.114.41
rând
4
Adresa IP a agentului de releu (de exemplu, un comutator)
27
Adresa MAC a clientului
14:d6:4d:a7:c9:55
Hex
6
Adresa MAC a expeditorului pachetului (client)
31
Complet cu adrese hardware client
Hex
10
Loc rezervat. De obicei umplute cu zerouri
41
Nume gazdă server
rând
64
Nume server DHCP. De obicei nu se transmite
105
Numele fișierului de pornire
rând
128
Numele fișierului pe server folosit de stațiile fără disc la pornire
235
Prajituri magice
63: 82: 53: 63
Hex
4
Număr „magic”, conform căruia, incl. puteți determina că acest pachet aparține protocolului DHCP
Opțiuni DHCP. Poate merge în orice ordine
236
Numărul opțiunii
53
decembrie
3
Opțiunea 53, care definește tipul de pachet DHCP 5 - DHCPACK
Lungimea opțiunii
1
decembrie
1
Valoarea opțiunii
5
decembrie
1
Numărul opțiunii
1
decembrie
1
Opțiunea de a oferi clientului DHCP o mască de rețea
Lungimea opțiunii
4
decembrie
1
Valoarea opțiunii
255.255.224.0
rând
4
Numărul opțiunii
3
decembrie
1
Opțiune de a oferi clientului DHCP un gateway implicit
Lungimea opțiunii
4
decembrie
1
Valoarea opțiunii
172.16.12.1
rând
4
Numărul opțiunii
6
decembrie
1
Opțiunea de a oferi DHCP clientului DNS
Lungimea opțiunii
4
decembrie
1
Valoarea opțiunii
8.8.8.8
rând
4
Numărul opțiunii
51
decembrie
1
Durata de viață a parametrilor de rețea emiși în secunde, după care clientul DHCP trebuie să îi solicite din nou
Lungimea opțiunii
4
decembrie
1
Valoarea opțiunii
86400
decembrie
4
Numărul opțiunii
82
decembrie
1
Opțiunea 82, repetă ceea ce a venit în DHCPDISCOVER
Lungimea opțiunii
18
decembrie
1
Valoarea opțiunii
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
decembrie
18
Sfârșitul pachetului
255
decembrie
1
255 simbolizează sfârșitul pachetului
Instalare
Instalarea constă de fapt în instalarea modulelor python necesare pentru lucru. Se presupune că MySQL este deja instalat și configurat.
FreeBSD
pkg instalează python3 python3 -m assurepip pip3 instalează conectorul mysql
Creăm o bază de date MySQL, încărcăm dump-ul pydhcp.sql în ea și configurăm fișierul de configurare.
configurație
Toate setările serverului sunt într-un fișier xml. Fișier de referință:
1.0 0.0.0.0 255.255.255.255 192.168.0.71 8600 1 255.255.255.0 192.168.0.1 gazdă locală Test Test 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 selectați ip, masca, router, dns de la utilizatori unde upper(mac)=upper('{option_3_AgentRemoteId_hex}') și upper(port)=upper('{option_1_AgentCircuitId_port_hex}') selectați ip, mască, router, dns de la utilizatori unde upper(mac)=upper('{sw_mac}') și upper(port)=upper('{sw_port82}') selectați ip, mască, router, dns de la utilizatori unde upper(mac)=upper('{ClientMacAddress}') inserați în istoric (id, dt, mac, ip, comentariu) valori (null, now(), '{ClientMacAddress}','{RequestedIpAddress}', 'DHCPACK/INFORM')
Acum, mai detaliat despre etichete:
Secțiunea dhcpserver descrie setările de bază pentru pornirea serverului, și anume:
gazdă - ce adresă IP ascultă serverul pe portul 67
broadcast - care ip este difuzarea pentru DHCPOFFER și DHCPACK
DHCPServer - care este ip-ul serverului DHCP
Durata de închiriere LeaseTime a adresei IP emise
ThreadLimit - câte fire rulează simultan pentru a procesa pachetele UDP primite pe portul 67. Se presupune că va ajuta la proiectele cu încărcare mare 😉
defaultMask,defaultRouter,defaultDNS - ce este oferit abonatului în mod implicit dacă se găsește un IP în baza de date, dar nu sunt specificați parametri suplimentari pentru acesta
secțiunea mysql:
gazdă, nume de utilizator, parolă, nume de bază - totul vorbește de la sine. O structură aproximativă a bazei de date este postată pe GitHub
Secțiunea de interogări: solicitările pentru primirea OFERTE/ACK sunt descrise aici:
offer_count — numărul de linii cu solicitări care returnează un rezultat precum ip,mask,router,dns
offer_n — șir de interogare. Dacă returnarea este goală, atunci execută următoarea cerere de ofertă
history_sql - o interogare care scrie, de exemplu, în „istoricul autorizațiilor” pentru un abonat
Cererile pot include orice variabile din secțiunea de opțiuni sau opțiuni din protocolul DHCP.
Secțiunea de opțiuni. Aici devine mai interesant. Aici putem crea variabile pe care le putem folosi mai târziu în secțiunea de interogare.
De exemplu:
option_82_hex:sw_port1:20:22
, această linie de comandă preia întreaga linie care a venit în opțiunea de solicitare DHCP 82, în format hex, în intervalul de la 20 la 22 de octeți inclusiv și o pune în noua variabilă sw_port1 (portul de comutare de unde a venit cererea)
option_82_hex:sw_mac:26:40
, definiți variabila sw_mac, luând hex din intervalul 26:40
Puteți vedea toate opțiunile posibile care pot fi utilizate în interogări pornind serverul cu comutatorul -d. Vom vedea ceva ca acest jurnal:
În consecință, putem include orice variabilă în {} și va fi folosită în interogarea SQL.
Să înregistrăm pentru istoric că clientul a primit adresa IP:
Pornirea serverului
./pydhcpdb.py -d -c config.xml
— d modul de ieșire consolei DEBUG
- c <nume fișier> fișier de configurare
Rezumat
Și acum mai multe detalii despre implementarea serverului în Python. Este o durere. Python a fost învățat din mers. Multe momente sunt făcute în stilul „wow, cumva l-am făcut să funcționeze”. Nu este deloc optimizat și lăsat în această formă în principal din cauza experienței reduse în dezvoltarea Python. Mă voi opri asupra celor mai interesante aspecte ale implementării serverului în „cod”.
Analizor de fișiere de configurare XML
Este utilizat modulul standard Python xml.dom. Pare simplu, dar în timpul implementării a existat o lipsă vizibilă a documentației clare și a exemplelor în rețea folosind acest modul.
arbore = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") pentru elem în mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("gazdă")[0].firstChild.data gconfig["mysql_username"]=elem.getElementsByTagName("username")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("parola")[0].firstChild.data gconfig["mysql_basename"] =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") pentru elem în dconfig: gconfig["broadcast"]=elem.getElementsByTagName("broadcast")[0]. firstChild.data gconfig["dhcp_host"]=elem.getElementsByTagName("gazdă")[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"Maskp_default] =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"](Nameelem.DNSget"] defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("interogare") pentru elem în qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[1].firstChild.data pentru num în interval(int(gconfig["ofer_count"])): gconfig["offer_"+str(num+1)]=elem.getElementsByTagName("offer_"+str(num+0))[0].firstChild.data gconfig ["history_sql"]=elem.getElementsByTagName("history_sql")[XNUMX].firstChild.data options=tree.getElementsByTagName("opțiuni") pentru elem în opțiuni: node=elem.getElementsByTagName("opțiune") pentru opțiuni în nod : optionsMod.append(options.firstChild.data)
Multithreading
În mod ciudat, multithreadingul în Python este implementat foarte clar și simplu.
def PacketWork(data,addr): ... # implementarea analizării pachetului de intrare și a răspunsului la acesta ... în timp ce True: data, addr = udp_socket.recvfrom(1024) # așteptând firul de pachete UDP = threading.Thread( target=PacketWork , args=(data,addr,)).start() # așa cum a venit - lansăm funcția PacketWork definită anterior în fundal cu parametrii în timp ce threading.active_count() >gconfig["dhcp_ThreadLimit"]: time. sleep(1) # dacă numărul Există mai multe fire care rulează deja decât în setări, așteptăm până când sunt mai puține dintre ele
Primiți/trimiteți pachet DHCP
Pentru a intercepta pachetele UDP care vin prin placa de rețea, trebuie să „ridicați” soclul:
AF_INET - înseamnă că formatul adresei va fi IP: port. Poate exista și AF_UNIX - unde adresa este dată de numele fișierului.
SOCK_DGRAM - înseamnă că nu acceptăm un „pachet brut”, ci unul care a trecut deja prin firewall și cu un pachet parțial tăiat. Acestea. primim doar un pachet UDP fără componenta „fizică” a pachetului de pachete UDP. Dacă utilizați flag-ul SOCK_RAW, atunci va trebui să analizați și acest „wrapper”.
Trimiterea unui pachet poate fi ca o difuzare:
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #switch the socket to broadcast mode rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))
, și la adresa „de unde a venit coletul”:
udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # comută socket-ul în modul multi-ascultător rz=udp_socket.sendto(packetack, addr)
, unde SOL_SOCKET înseamnă „nivelul de protocol” pentru setarea opțiunilor,
, opțiunea SO_BROADCAST că pachetul de cască este „difuzat”
Opțiunea ,SO_REUSEADDR comută soclul în modul „mulți ascultători”. În teorie, nu este necesar în acest caz, dar pe unul dintre serverele FreeBSD pe care am testat, codul nu a funcționat fără această opțiune.
Analizarea unui pachet DHCP
Aici mi-a plăcut foarte mult Python. Se pare că din cutie vă permite să fiți destul de flexibili cu bytecode. Permițându-i să fie foarte ușor tradus în valori zecimale, șiruri și hex - adică aceasta este ceea ce avem de fapt nevoie pentru a înțelege structura pachetului. Deci, de exemplu, puteți obține o serie de octeți în HEX și doar octeți: