DHCP+MySQL server në Python

DHCP+MySQL server në Python

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 DB2DHCP (forku im), origjinali këtu, 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 "të prekësh në jet".

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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.

DHCP+MySQL server në Python

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:

DHCP+MySQL server në Python

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ë GitHub

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:

DHCP+MySQL server në Python

DHCP+MySQL server në Python

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ël

Pranimi/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

Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS 🔥 Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS - ProHoster