
Qëllimi i këtij projekti ishte:
- Studimi i protokollit DHCP në punën me rrjetin IPv4
- Studimi i Python (pak më shumë se nga fillimi 😉 )
- zëvendësimi i serverit (forku im), origjinali , i cili bëhet gjithnjë e më e vështirë të ndërtohet për sistemet e reja operative. Madje, nuk më pëlqen që ekzekutuesi, i cili nuk ka mundësi "ta ndërroni menjëherë"
- marrja e një serveri DHCP funksional me mundësinë e marrjes së IP adresës së abonentit sipas mac adresës së abonentit apo lidhjes mac të switch-it + port (Opsioni 82)
- shkrimi i një biçiklete të re (O! kjo është aktiviteti im i preferuar)
- marrja e kritika për neglizhencën time në HabrHabr (e preferuara është një ftesë) 😉
Rezultati: punon 😉 Testuar në OS FreeBSD dhe Ubuntu. Teoretikisht, mund të kërkohet që kodi të punojë për çdo OS, pasi nuk ka lidhje specifike në kod.
Kujdes! Më poshtë ka shumë.
Lidhja me depo për adhuruesit .
Procesi i instalimit, konfigurimit dhe përdorimit të rezultatit "të studimit të materies" është shumë poshtë, dhe më pas pak teori për protokollin DHCP. Për vete. Dhe për historinë 😉
Pak teori
Çfarë është DHCP
Ky është një protokoll rrjetesh që lejon një aparat të mësojë IP adresën e tij (dhe parametra të tjerë si gateway, DNS etj.) nga serveri DHCP. Shkëmbimi i paketeve bëhet përmes protokolit UDP. Parimi i përgjithshëm i punës së aparatit kur kërkon parametrat e rrjetit është si në vijim:
- Aparati (klienti) shpërndan një kërkesë UDP të gjerë (DHCPDISCOVER) në të gjithë rrjetin me kërkesën "cilido, më jepni një IP adresë". Zakonisht (por jo gjithmonë), kërkesa ndodh nga porta 68 (burimi), dhe destinimi është porta 67 (destinacioni). Disa aparate dërgojnë paketa edhe nga porta 67. Brenda paketës DHCPDISCOVER është përfshirë adresa MAC e aparatit klient.
- Të gjithë serverat DHCP, që ndodhen në rrjet (dhe mund të ketë disa), formulojnë për aparatin që dërgoi DHCPDISCOVER, një ofertë DHCPOFFER me cilësimet e rrjetit, dhe gjithashtu e dërgojnë atë në mënyrë të gjerë në rrjet. Identifikimi se për kë është për këtë paketë bëhet përmes adresës MAC të klientit, e cila është dhënë më parë në kërkesën DHCPDISCOVER.
- Klienti pranon paketat me propozime për konfigurimet e rrjetit, zgjedh paketën më tërheqëse (kriteret mund të jenë të ndryshme, përfshirë edhe kohën e dërgesës së paketës, numrin e rrugëve ndërmjetëse), dhe bën një "kërkesë zyrtare" DHCPREQUEST me konfigurimet e rrjetit për serverin DHCP që i pëlqen. Në këtë rast, paketa shkon tashmë për te një server specifik DHCP.
- Serveri që merr DHCPREQUEST dërgon një paketë në formatin DHCPACK, në të cilën përmend sërish konfigurimet e rrjetit të destinuara për këtë klient.

Për më tepër, ka paketa DHCPINFORM që dërgohen nga klienti, dhe qëllimi i tyre është të informojnë serverin DHCP se "klienti është aktiv" dhe po përdor konfigurimet e dhëna të rrjetit. Në realizimin e këtij serveri, këto paketa injorohen.
Formati i paketimeve
Në përgjithësi, fushat e paketa Ethernet duken afërsisht kështu:
![]()
Në rastin tonë, ne do të shqyrtojmë vetëm të dhënat e përmbajtjes së paketës UDP, pa tituj të protokolleve të niveleve OSI, konkretisht strukturën DHCP:
DHCPDISCOVER
Pra, procesi i marrjes së një adrese IP për pajisjen fillon me atë që klienti DHCP dërgon një kërkesë të gjerë nga porta 68 në 255.255.255.255:67. Në këtë paketë, klienti përfshin adresën e tij MAC, si dhe çfarë dëshiron të marrë nga serveri DHCP. Struktura e paketës përshkruhet në formën e tabelës më poshtë.
Tabelë e strukturës së paketës DHCPDISCOVER
Pozita në paketë
Emri i vlerës
Shembulli
Përfaqësimi
Bytes
Shpjegimi
1
Kërkesa Boot
1
Hex
1
Tipi i mesazhit. 1 - kërkesë nga klienti për serverin, 2 - përgjigje nga serveri për klientin
2
Lloji i harduerit
1
Hex
1
Lloji i adresës së harduerit, në këtë protokoll 1 - MAC
3
Gjatësia e adresës së harduerit
6
Hex
1
Gjatësia e adresës MAC të pajisjes
4
Hops
1
Hex
1
Numri i rrugëve ndërmjetëse
5
ID i Transaksionit
23:cf:de:1d
Hex
4
Identifikues unik i transaksionit. Klienti e gjeneron në fillim të procesit të kërkesës
7
Sekondi të kaluara
0
Hex
4
Koha në sekonda që nga fillimi i procesit të marrjes së adresës
9
Flagat e Bootp
0
Hex
2
Disa flag, që mund të vendosen për të treguar parametrat e protokollit
11
Adresa IP e klientit
0.0.0.0
String
4
Adresa IP e klientit (nëse ka)
15
Adresa IP e klientit tuaj
0.0.0.0
String
4
Adresa IP e propozuar nga serveri (nëse ka)
19
Adresa IP e serverit të ardhshëm
0.0.0.0
String
4
Adresa IP e serverit (nëse dihet)
23
Adresa IP e agjentit të rinisjes
172.16.114.41
String
4
Adresa IP e agjentit të rinisjes (për shembull switch)
27
Adresa MAC e klientit
14:d6:4d:a7:c9:55
Hex
6
Adresa MAC e dërguesit të paketës (klienti)
31
Përmasat e adresës së harduerit të klientit
Hex
10
Hapësirë e rezervuar. Zakonisht mbushet me zero
41
Emri i serverit
String
64
Emri i serverit DHCP. Zakonisht nuk dërgohet
105
Emri i skedarit të boot
String
128
Emri i skedarit në server, i përdorur nga stacionet pa disqe gjatë ngarkimit
235
Magic cookie
63:82:53:63
Hex
4
Numri "magjik", me të cilin gjithashtu mund të përcaktohet se ky paket i përket protokollit DHCP
Opsionet DHCP. Mund të shfaqen në çdo rend
236
Numri i opsionit
53
Dec
1
Opsioni 53, që përcakton tipin e paketës DHCP
1 — DHCPDISCOVER
3 — DHCPREQUEST
2 — DHCPOFFER
5 — DHCPACK
8 — DHCPINFORM
Gjatësia e opsionit
1
Dec
1
Vlera e opsionit
1
Dec
1
Numri i opsionit
50
Dec
1
Cila IP adresë dëshiron të marrë klienti
Gjatësia e opsionit
4
Dec
1
Vlera e opsionit
172.16.134.61
String
4
Numri i opsionit
55
1
Parametrat rrjetore të kërkuar nga klienti. Strukturat mund të jenë të ndryshme
01 — Maskë rrjeti
03 — Gjenerator
06 — DNS
oc — Emri i hostit
0f — emri i domenit të rrjetit
1c — adresa e kërkesës së shumicës (broadcast)
42 — emri i serverit TFTP
79 — Rruga Statike pa Klasa
Gjatësia e opsionit
8
1
Vlera e opsionit
01:03:06:0c:0f:1c:42:79
8
Numri i opsionit
82
Dec
Opsioni 82, në të cilin transmetohet adresa MAC e pajisjes - retransmetues dhe disa vlera shtesë.
më së shumti — porta e switch-it ku punon klienti përfundimtar DHCP Në këtë opsion janë "injektuar" parameter të tjerë. Bytes i parë — numri i "nëopsionit", i dyti gjatësia e saj, pastaj vlera e saj.
Në këtë rast, në opsionin 82, janë injektuar nëopsione:
Agent Circuit ID = 00:04:00:01:00:04, ku dy bytes e fundit janë porta e klientit DHCP nga e cila erdhi kërkesa
Agent Remote ID = 00:06:c8:be:19:93:11:48 — adresa MAC e pajisjes retransmetuese DHCP
Gjatësia e opsionit
18
Dec
Vlera e opsionit
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Hex
Përfundimi i paketës
255
Dec
1
255 simbolizon përfundimin e paketës
DHCPOFFER
Sapo serveri merr paketën DHCPDISCOVER dhe nëse sheh se mund t’i ofrojë klientit diçka nga e kërkuara, ai formon një përgjigje për të — DHCPDISCOVER. Përgjigja dërgohet në portin "nga e cila erdhi" si broadcast, pasi në këtë moment, klienti ende nuk ka IP adresë, kështu që ai mund ta pranojë paketën vetëm nëse është dërguar si tërësisht. Klienti e njeh që kjo është një paketë për të përmes adresës së tij MAC në brendësi të paketës, si dhe numrit të transaksionit, i cili gjenerohet në momentin e krijimit të paketës së parë.
Tabela e strukturës së paketës DHCPOFFER
Pozita në paketë
Emri i vlerës (zakonisht e pranuar)
Shembulli
Përfaqësimi
Bytes
Shpjegimi
1
Kërkesa Boot
1
Hex
1
Tipi i mesazhit. 1 - kërkesë nga klienti për serverin, 2 - përgjigje nga serveri për klientin
2
Lloji i harduerit
1
Hex
1
Lloji i adresës së harduerit, në këtë protokoll 1 - MAC
3
Gjatësia e adresës së harduerit
6
Hex
1
Gjatësia e adresës MAC të pajisjes
4
Hops
1
Hex
1
Numri i rrugëve ndërmjetëse
5
ID i Transaksionit
23:cf:de:1d
Hex
4
Identifikues unik i transaksionit. Klienti e gjeneron në fillim të procesit të kërkesës
7
Sekondi të kaluara
0
Hex
4
Koha në sekonda që nga fillimi i procesit të marrjes së adresës
9
Flagat e Bootp
0
Hex
2
Disa flamuj, të cilat mund të vendosen si shenja të parametrave të protokollit. Në këtë rast, 0 — do të thotë lloji i kërkesës Unicast
11
Adresa IP e klientit
0.0.0.0
String
4
Adresa IP e klientit (nëse ka)
15
Adresa IP e klientit tuaj
172.16.134.61
String
4
Adresa IP e propozuar nga serveri (nëse ka)
19
Adresa IP e serverit të ardhshëm
0.0.0.0
String
4
Adresa IP e serverit (nëse dihet)
23
Adresa IP e agjentit të rinisjes
172.16.114.41
String
4
Adresa IP e agjentit të rinisjes (për shembull switch)
27
Adresa MAC e klientit
14:d6:4d:a7:c9:55
Hex
6
Adresa MAC e dërguesit të paketës (klienti)
31
Përmasat e adresës së harduerit të klientit
Hex
10
Hapësirë e rezervuar. Zakonisht mbushet me zero
41
Emri i serverit
String
64
Emri i serverit DHCP. Zakonisht nuk dërgohet
105
Emri i skedarit të boot
String
128
Emri i skedarit në server, i përdorur nga stacionet pa disqe gjatë ngarkimit
235
Magic cookie
63:82:53:63
Hex
4
Numri "magjik", me të cilin gjithashtu mund të përcaktohet se ky paket i përket protokollit DHCP
Opsionet DHCP. Mund të shfaqen në çdo rend
236
Numri i opsionit
53
Dec
1
Opsioni 53, që përcakton tipin e paketës DHCP 2 — DHCPOFFER
Gjatësia e opsionit
1
Dec
1
Vlera e opsionit
2
Dec
1
Numri i opsionit
1
Dec
1
Opsioni që ofron klientit DHCP maskën e rrjetit
Gjatësia e opsionit
4
Dec
1
Vlera e opsionit
255.255.224.0
String
4
Numri i opsionit
3
Dec
1
Opsioni që ofron klientit DHCP portën e paracaktuar
Gjatësia e opsionit
4
Dec
1
Vlera e opsionit
172.16.12.1
String
4
Numri i opsionit
6
Dec
1
Opsioni që ofron klientit DHCP DNS
Gjatësia e opsionit
4
Dec
1
Vlera e opsionit
8.8.8.8
String
4
Numri i opsionit
51
Dec
1
Koha e jetës së parametrave të rrjetit të dhënë në sekonda, pas së cilës klienti DHCP duhet t’i kërkojë përsëri
Gjatësia e opsionit
4
Dec
1
Vlera e opsionit
86400
Dec
4
Numri i opsionit
82
Dec
1
Opsioni 82, përsërit atë që erdhi në DHCPDISCOVER
Gjatësia e opsionit
18
Dec
1
Vlera e opsionit
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Dec
18
Përfundimi i paketës
255
Dec
1
255 simbolizon përfundimin e paketës
DHCPREQUEST
Pas pas klienti të pranojë DHCPOFFER, ai formon një paketë me kërkesën për parametra rrjeti jo më për të gjithë serverët DHCP në rrjet, por vetëm për një të caktuar, oferta DHCPOFFER e të cilit i ka pëlqyer më shumë. Kriteret e "pëlqimit" mund të jenë të ndryshme dhe varen nga implementimi i klientit DHCP. Marrësi i kërkesës tregohet përmes adresës MAC të serverit DHCP. Po ashtu, paketa DHCPREQUEST mund të dërgohet nga klienti dhe pa formimin e mëparshëm DHCPDISCOVER, nëse adresa IP nga serveri ka qenë tashmë e marrë më herët.
Tabela e strukturës së paketës DHCPREQUEST
Pozita në paketë
Emri i vlerës (zakonisht e pranuar)
Shembulli
Përfaqësimi
Bytes
Shpjegimi
1
Kërkesa Boot
1
Hex
1
Tipi i mesazhit. 1 - kërkesë nga klienti për serverin, 2 - përgjigje nga serveri për klientin
2
Lloji i harduerit
1
Hex
1
Lloji i adresës së harduerit, në këtë protokoll 1 - MAC
3
Gjatësia e adresës së harduerit
6
Hex
1
Gjatësia e adresës MAC të pajisjes
4
Hops
1
Hex
1
Numri i rrugëve ndërmjetëse
5
ID i Transaksionit
23:cf:de:1d
Hex
4
Identifikues unik i transaksionit. Klienti e gjeneron në fillim të procesit të kërkesës
7
Sekondi të kaluara
0
Hex
4
Koha në sekonda që nga fillimi i procesit të marrjes së adresës
9
Flagat e Bootp
8000
Hex
2
Disa flagje, të cilat mund të vendosen si një tregues për parametrat e protokollit. Në këtë rast është vendosur "broadcast"
11
Adresa IP e klientit
0.0.0.0
String
4
Adresa IP e klientit (nëse ka)
15
Adresa IP e klientit tuaj
172.16.134.61
String
4
Adresa IP e propozuar nga serveri (nëse ka)
19
Adresa IP e serverit të ardhshëm
0.0.0.0
String
4
Adresa IP e serverit (nëse dihet)
23
Adresa IP e agjentit të rinisjes
172.16.114.41
String
4
Adresa IP e agjentit të rinisjes (për shembull switch)
27
Adresa MAC e klientit
14:d6:4d:a7:c9:55
Hex
6
Adresa MAC e dërguesit të paketës (klienti)
31
Përmasat e adresës së harduerit të klientit
Hex
10
Hapësirë e rezervuar. Zakonisht mbushet me zero
41
Emri i serverit
String
64
Emri i serverit DHCP. Zakonisht nuk dërgohet
105
Emri i skedarit të boot
String
128
Emri i skedarit në server, i përdorur nga stacionet pa disqe gjatë ngarkimit
235
Magic cookie
63:82:53:63
Hex
4
Numri "magjik", me të cilin gjithashtu mund të përcaktohet se ky paket i përket protokollit DHCP
Opsionet DHCP. Mund të shfaqen në çdo rend
236
Numri i opsionit
53
Dec
3
Opsioni 53, që përcakton llojin e paketës DHCP 3 — DHCPREQUEST
Gjatësia e opsionit
1
Dec
1
Vlera e opsionit
3
Dec
1
Numri i opsionit
61
Dec
1
Identifikuesi i klientit: 01 (për Ethernet) + adresa MAC e klientit
Gjatësia e opsionit
7
Dec
1
Vlera e opsionit
01:2c:ab:25:ff:72:a6
Hex
7
Numri i opsionit
60
Dec
"Identifikuesi i klasës së shitësit". Në rastin tim njofton versionin e klientit DHCP. Mundësisht pajisje të tjera, kthejnë diçka tjetër. Windows për shembull raporton MSFT 5.0
Gjatësia e opsionit
11
Dec
Vlera e opsionit
udhcp 0.9.8
String
Numri i opsionit
55
1
Parametrat rrjetore të kërkuar nga klienti. Strukturat mund të jenë të ndryshme
01 — Maskë rrjeti
03 — Gjenerator
06 — DNS
oc — Emri i hostit
0f — emri i domenit të rrjetit
1c — adresa e kërkesës së shumicës (broadcast)
42 — emri i serverit TFTP
79 — Rruga Statike pa Klasa
Gjatësia e opsionit
8
1
Vlera e opsionit
01:03:06:0c:0f:1c:42:79
8
Numri i opsionit
82
Dec
1
Opsioni 82, përsërit atë që erdhi në DHCPDISCOVER
Gjatësia e opsionit
18
Dec
1
Vlera e opsionit
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Dec
18
Përfundimi i paketës
255
Dec
1
255 simbolizon përfundimin e paketës
DHCPACK
Si një konfirmim që "po, me të vërtetë, kjo është adresa juaj IP, dhe nuk do ta jap më askujt" nga serveri DHCP, shërben paketa në formatin DHCPACK nga serveri për klientin. Ai, ashtu si dhe paketat e tjera dërgohet në mënyrë të gjitha. Megjithatë, në kodin e dhënë më poshtë të serverit DHCP të realizuar në Python, që dërgoj çdo kërkesë të gjeneruar në mënyrë të gjitha, duke dërguar paketën në një IP të caktuar të klientit, nëse tashmë është e njohur. Dhe serveri DHCP nuk shqetësohet aspak nëse paketa DHCPACK ka arritur te klienti. Nëse klienti nuk merr DHCPACK, atëherë pas një kohe të caktuar thjesht përsërit DHCPREQUEST
Tabela e strukturës së paketës DHCPACK
Pozita në paketë
Emri i vlerës (zakonisht e pranuar)
Shembulli
Përfaqësimi
Bytes
Shpjegimi
1
Kërkesa Boot
2
Hex
1
Tipi i mesazhit. 1 - kërkesë nga klienti për serverin, 2 - përgjigje nga serveri për klientin
2
Lloji i harduerit
1
Hex
1
Lloji i adresës së harduerit, në këtë protokoll 1 - MAC
3
Gjatësia e adresës së harduerit
6
Hex
1
Gjatësia e adresës MAC të pajisjes
4
Hops
1
Hex
1
Numri i rrugëve ndërmjetëse
5
ID i Transaksionit
23:cf:de:1d
Hex
4
Identifikues unik i transaksionit. Klienti e gjeneron në fillim të procesit të kërkesës
7
Sekondi të kaluara
0
Hex
4
Koha në sekonda që nga fillimi i procesit të marrjes së adresës
9
Flagat e Bootp
8000
Hex
2
Disa flagje, të cilat mund të vendosen si një tregues për parametrat e protokollit. Në këtë rast është vendosur "broadcast"
11
Adresa IP e klientit
0.0.0.0
String
4
Adresa IP e klientit (nëse ka)
15
Adresa IP e klientit tuaj
172.16.134.61
String
4
Adresa IP e propozuar nga serveri (nëse ka)
19
Adresa IP e serverit të ardhshëm
0.0.0.0
String
4
Adresa IP e serverit (nëse dihet)
23
Adresa IP e agjentit të rinisjes
172.16.114.41
String
4
Adresa IP e agjentit të rinisjes (për shembull switch)
27
Adresa MAC e klientit
14:d6:4d:a7:c9:55
Hex
6
Adresa MAC e dërguesit të paketës (klienti)
31
Përmasat e adresës së harduerit të klientit
Hex
10
Hapësirë e rezervuar. Zakonisht mbushet me zero
41
Emri i serverit
String
64
Emri i serverit DHCP. Zakonisht nuk dërgohet
105
Emri i skedarit të boot
String
128
Emri i skedarit në server, i përdorur nga stacionet pa disqe gjatë ngarkimit
235
Magic cookie
63:82:53:63
Hex
4
Numri "magjik", me të cilin gjithashtu mund të përcaktohet se ky paket i përket protokollit DHCP
Opsionet DHCP. Mund të shfaqen në çdo rend
236
Numri i opsionit
53
Dec
3
Opsioni 53, që përcakton llojin e paketës DHCP 5 — DHCPACK
Gjatësia e opsionit
1
Dec
1
Vlera e opsionit
5
Dec
1
Numri i opsionit
1
Dec
1
Opsioni që ofron klientit DHCP maskën e rrjetit
Gjatësia e opsionit
4
Dec
1
Vlera e opsionit
255.255.224.0
String
4
Numri i opsionit
3
Dec
1
Opsioni që ofron klientit DHCP portën e paracaktuar
Gjatësia e opsionit
4
Dec
1
Vlera e opsionit
172.16.12.1
String
4
Numri i opsionit
6
Dec
1
Opsioni që ofron klientit DHCP DNS
Gjatësia e opsionit
4
Dec
1
Vlera e opsionit
8.8.8.8
String
4
Numri i opsionit
51
Dec
1
Koha e jetës së parametrave të rrjetit të dhënë në sekonda, pas së cilës klienti DHCP duhet t’i kërkojë përsëri
Gjatësia e opsionit
4
Dec
1
Vlera e opsionit
86400
Dec
4
Numri i opsionit
82
Dec
1
Opsioni 82, përsërit atë që erdhi në DHCPDISCOVER
Gjatësia e opsionit
18
Dec
1
Vlera e opsionit
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Dec
18
Përfundimi i paketës
255
Dec
1
255 simbolizon përfundimin e paketës
Instalimi
Instalimi në thelb përfshin instalimin e moduleve python të nevojshme për funksionimin. Supozon se MySQL është instaluar dhe konfiguruar tashmë.
FreeBSD
pkg install python3 python3 -m ensurepip pip3 install mysql-connector
Ubuntu
sudo apt-get install python3 sudo apt-get install pip3 sudo pip3 install mysql-connector
Krijojmë BDb MySQL, ngarkojmë në të dump pydhcp.sql, konfigurimin e skedarit.
Konfigurimi
Të gjitha konfigurimet e serverit ndodhen në një skedar me format xml. Skedari referencë:
0.0.0.0
255.255.255.255
192.168.0.71
8600
1
255.255.255.0
192.168.0.1
8.8.8.8
localhost
test
test
pydhcp
option_82_hex:sw_port1:20:22
option_82_hex:sw_port2:16:18
option_82_hex:sw_mac:26:40
3
select ip,mask,router,dns from users where upper(mac)=upper('{option_82_AgentRemoteId_hex}') and upper(port)=upper('{option_82_AgentCircuitId_port_hex}')
select ip,mask,router,dns from users where upper(mac)=upper('{sw_mac}') and upper(port)=upper('{sw_port2}')
select ip,mask,router,dns from users where upper(mac)=upper('{ClientMacAddress}')
insert into history (id,dt,mac,ip,comment) values (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')Tani tani mbi etiketat:
Seksioni dhcpserver përshkruan parametrat kryesorë për aktivizimin e serverit, në veçanti:
- host — cili IP adresë dëgjon serveri në portin 67
- broadcast — cili IP është bllokues për DHCPOFFER dhe DHCPACK
- DHCPServer — cili IP ka serveri DHCP
- LeaseTime është koha e qirasë për IP adresën e dhënë
- ThreadLimit — sa njësi të njëkohshme përpunojnë paketat UDP të marra në portin 67. Supozohet se ndihmon në projekte me ngarkesë të lartë 😉
- defaultMask,defaultRouter,defaultDNS — ato që i ofrohen abonentit si parazgjedhje, nëse IP-ja gjendet në bazë, por parametrat e tjerë për të nuk janë të përcaktuar
Seksioni mysql:
host,username,password,basename — gjithçka flet për vete. Strukturën përfundimtare të bazës së të dhënave e keni në
Seksioni query: këtu përshkruhen pyetjet për marrjen e OFFER/ACK:
- offer_count — numri i rreshtave me pyetje që kthejnë rezultat si ip,mask,router,dns
- offer_n — rreshti i pyetjes. Nëse kthehet — bosh, atëherë realizon pyetjen e ardhshme offer
- history_sql — pyetje që shënon, për shembull, në "historinë e autorizimit" për abonentin
Në pyetje mund të përfshihen çdo variabël nga seksioni options ose opsionet nga protokolli DHCP.
Seksioni options. Këtu bëhet më interesante. Këtu mund të krijojmë variabla që mund t'i përdorim më vonë në seksionin query.
Për shembull:
option_82_hex:sw_port1:20:22, kjo rresht komandë merr të gjithë rreshtin që ka ardhur në kërkesën DHCP në opsionin 82, në formatin hex, në një gamë nga byte 20 deri në 22 përfshirë dhe e vendos atë në një variabël të re sw_port1 (porta e switchit nga e cila erdhi kërkesa)
option_82_hex:sw_mac:26:40, përcaktojmë variablën sw_mac, duke marrë hex nga gama 26:40
Të shikoni të gjitha opsionet e mundshme që mund të përdoren në kërkesa, mund të bëhet duke nisur serverin me çelësin -d. Do të shohim diçka të tillë në log:
--paketi DHCPINFORM ka ardhur në portin 67, nga 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68)
{'ClientMacAddress': '0025224ad764',
'ClientMacAddressByte': b'x00%"Jxd7d',
'HType': 'Ethernet',
'HostName': b'x91xa5xe0xa3xa5xa9-x8fx8a',
'ReqListDNS': True,
'ReqListDomainName': True,
'ReqListPerfowmRouterDiscover': True,
'ReqListRouter': True,
'ReqListStaticRoute': True,
'ReqListSubnetMask': True,
'ReqListVendorSpecInfo': 43,
'RequestedIpAddress': '0.0.0.0',
'Vendor': b'MSFT 5.0',
'chaddr': '0025224ad764',
'ciaddr': '172.30.128.13',
'flags': b'x00x00',
'giaddr': '172.30.114.25',
'gpoz': 308,
'hlen': 6,
'hops': 1,
'htype': 'MAC',
'magic_cookie': b'cx82Sc',
'op': 'DHCPINFORM',
'option12': 12,
'option53': 53,
'option55': 55,
'option60': 60,
'option61': 61,
'option82': 82,
'option_82_byte': b'x12x01x06x00x04x00x01x00x06x02x08x00'
b'x06x00x1eXx9exb2xad',
'option_82_hex': '12010600040001000602080006001e589eb2ad',
'option_82_len': 18,
'option_82_str': "b'x12x01x06x00x04x00x01x00x06x02x08x00x06x00x1eXx9exb2xad'",
'result': False,
'secs': 768,
'siaddr': '0.0.0.0',
'sw_mac': '001e589eb2ad',
'sw_port1': '06',
'xidbyte': b'<x89}x8c',
'xidhex': '3c897d8c',
'yiaddr': '0.0.0.0'}Prandaj, ne mund ta mbështjellim çdo variabël në {} dhe ajo do të përdoret në kërkesën SQL.
Regjistrojmë për historinë që adresa IP që klienti mori:


Nisja e serverit
.\/pydhcpdb.py -d -c config.xml
— d moda e daljes në konsolë DEBUG
— c <emri_fajllit> fajlli i konfigurimit
Analiza e fluturimeve
Tani të flasim më në detaje mbi implementimin e serverit në Python. Kjo është një dhimbje. Python është studiuar 'në fluturim'. Më shumë momente janë bërë në stilin: 'ah, siç e bëra, funksionon'. Totalisht të pambrojtura, dhe janë lënë në këtë formë kryesisht për shkak të eksperiencës së vogël në zhvillimin në python. Do të ndalem në momentet më interesante të implementimit të serverit në 'kod'.
Parser i skedarit të konfigurimit XML
Përdoret moduli standard i Python xml.dom. Dukshëm dhe e thjeshtë, por gjatë implementimit ndiheshit ndjeshëm pa dokumentacion të dobishëm dhe shembuj në rrjet me përdorimin e këtij moduli.
tree = minidom.parse(gconfig["config_file"])
mconfig=tree.getElementsByTagName("mysql")
for 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")
for 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["dhcp_defaultMask"]=elem.getElementsByTagName("defaultMask")[0].firstChild.data
gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data
gconfig["dhcp_defaultDNS"]=elem.getElementsByTagName("defaultDNS")[0].firstChild.data
qconfig=tree.getElementsByTagName("query")
for elem in qconfig:
gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[0].firstChild.data
for num in range(int(gconfig["offer_count"])):
gconfig["offer_"+str(num+1)]=elem.getElementsByTagName("offer_"+str(num+1))[0].firstChild.data
gconfig["history_sql"]=elem.getElementsByTagName("history_sql")[0].firstChild.data
options=tree.getElementsByTagName("options")
for elem in options:
node=elem.getElementsByTagName("option")
for options in node:
optionsMod.append(options.firstChild.data)Multithreading
Çuditërisht, multithreading në Python është realizuar në një mënyrë shumë të qartë dhe të thjeshtë.
def PacketWork(data, addr):
...
# realizimi i analizës së paketës së ardhur dhe përgjigjes së saj
...
while True:
data, addr = udp_socket.recvfrom(1024) # presim një paketë UDP
thread = threading.Thread(target=PacketWork, args=(data, addr,)).start() # sapo ka ardhur - fillojmë në mënyrë të pasme funksionin e caktuar më parë PacketWork me parametra
while threading.active_count() > gconfig["dhcp_ThreadLimit"]:
time.sleep(1) # nëse numri i driteve të nisura është më i madh se sa në vendosje, presim derisa të bëhet më i vogëlPranimi/dërgimi i paketës DHCP
Për të kapur paketat UDP që kalojnë përmes kartës së rrjetit, duhet "të ngrihet" soketi:
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) udp_socket.bind((gconfig["dhcp_host"], 67))
, ku flamujt:
- AF_INET — do të thotë që formati i adresës do të jetë IP: port. Mund të jetë gjithashtu AF_UNIX — ku adresa jepet me emrin e skedarit.
- SOCK_DGRAM — do të thotë, se pranojmë jo "paketën e papërpunuar", por një që tashmë ka kaluar përmes firewallit, dhe me paketën e prerë pjesërisht. Kështu, ne marrim vetëm paketën UDP pa përmbajtjen "fizike" të paketës UDP. Nëse përdoret flamuri SOCK_RAW, atëherë do të duhet të analizojmë edhe këtë "përmbajtje".
Dërgimi i paketës mund të jetë si broadcast:
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # kalojmë soketin në modalitetin e dërgimit të bllokadës
rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68)), ashtu si dhe në adresën "nga ku erdhi paketa":
udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # kalojmë soketin në modalitetin "shumë dëgjues"
rz=udp_socket.sendto(packetack, addr), ku SOL_SOCKET do të thotë "niveli i protokollit" për caktimin e opsioneve,
, SO_BROADCAST është opsioni që paketa dërgohet "në bllok"
, SO_REUSEADDR është opsioni që kalon soketin në modalitetin "shumë dëgjues". Idealisht nuk është e nevojshme në këtë rast, por në një nga serverët FreeBSD, ku kam testuar, pa këtë opsion kodi nuk punonte.
Analiza e paketës DHCP
Këtu më pëlqeu vërtet Python. Të duket se nga "kuti" ai lejon të merremi shumë lirisht me kodin byte. Duke e bërë shumë të thjeshtë ta përkthejmë në vlera dhjetore, telash dhe hex — dmth. atë që na nevojitet për të kuptuar strukturën e paketës. Kështu, për shembull, mund të marrim vargun e bajtave në HEX dhe thjesht bajtat:
res["xidhex"]=data[4:8].hex()
res["xidbyte"]=data[4:8], paketoni bajtat në strukturë:
res["flags"]=pack('BB',data[10],data[11])Merrni IP-në nga struktura:
res["ciaddr"]=socket.inet_ntoa(pack('BBBB',data[12],data[13],data[14],data[15]));Dhe anasjelltas:
res=res+socket.inet_pton(socket.AF_INET, gconfig["dhcp_Server"])
Kjo është gjithçka 😉
Burimi: habr.com
