
Šī projekta mērķis bija:
- Mācīšanās par DHCP IPv4 tīklā
- Python apgūšana (nedaudz vairāk nekā no nulles 😉)
- servera nomaiņa (mana dakša), oriģināls , kuru jaunajai OS samontēt kļūst arvien grūtāk. Un man nepatīk, ka tas ir binārs, ko nevar “šobrīd mainīt”
- strādājoša DHCP servera iegūšana ar iespēju izvēlēties abonenta IP adresi, izmantojot abonenta mac vai slēdža mac+porta kombināciju (82. iespēja)
- cita velosipēda rakstīšana (Ak, šī ir mana mīļākā nodarbe)
- saņemt komentārus par jūsu izturēšanos pret klubu vietnē Habrahabr (vai vēl labāk, uzaicinājumu) 😉
Rezultāts: tas darbojas 😉 Pārbaudīts uz FreeBSD OS un UbuntuTeorētiski kodu var panākt, lai tas darbotos jebkurā operētājsistēmā, jo kodā nav īpašu saistījumu.
Uzmanīgi! Ir vēl daudz kas priekšā.
Saite uz amatieru repozitoriju .
Instalēšanas, konfigurēšanas un “aparatūras izpētes” rezultāta izmantošanas process ir daudz zemāks, un tad nedaudz teorijas par DHCP protokolu. Priekš manis. Un vēsturei 😉
Nedaudz teorijas
Kas ir DHCP
Šis ir tīkla protokols, kas ļauj ierīcei uzzināt savu IP adresi (un citus parametrus, piemēram, vārteju, DNS utt.) no DHCP servera. Pakešu apmaiņa notiek, izmantojot UDP protokolu. Ierīces vispārējais darbības princips, pieprasot tīkla parametrus, ir šāds:
- Ierīce (klients) nosūta UDP apraides pieprasījumu (DHCPDISCOVER) visā tīklā ar pieprasījumu "kāds, dodiet man IP adresi". Turklāt parasti (bet ne vienmēr) pieprasījums tiek saņemts no 68. porta (avota), un galamērķis ir 67. ports (galamērķis). Dažas ierīces arī sūta paketes no 67. porta. Klienta ierīces MAC adrese ir iekļauta DHCPDISCOVER pakotnē.
- Visi tīklā esošie DHCP serveri (un tie var būt vairāki) veido DHCPOFFER piedāvājumu ar tīkla iestatījumiem ierīcei, kas nosūtīja DHCPDISCOVER, un arī pārraida to tīklā. Identifikācija, kam šī pakete ir paredzēta, ir balstīta uz klienta MAC adresi, kas norādīta iepriekš DHCPDISCOVER pieprasījumā.
- Klients pieņem paketes ar priekšlikumiem tīkla iestatījumiem, izvēlas pievilcīgāko (kritēriji var atšķirties, piemēram, pakešu piegādes laiks, starpceļu skaits) un veic “oficiālu pieprasījumu” DHCPREQUEST ar tīkla iestatījumiem. no DHCP servera, kas tai patīk. Šajā gadījumā pakete tiek nosūtīta uz noteiktu DHCP serveri.
- Serveris, kurš saņēma DHCPREQUEST, nosūta DHCPACK formāta paketi, kurā vēlreiz uzskaita šim klientam paredzētos tīkla iestatījumus.

Turklāt ir DHCPINFORM paketes, kas nāk no klienta un kuru mērķis ir informēt DHCP serveri, ka “klients ir dzīvs” un izmanto izsniegtos tīkla iestatījumus. Šī servera ieviešanā šīs paketes tiek ignorētas.
Pakas formāts
Kopumā Ethernet pakešu rāmis izskatās apmēram šādi:
![]()
Mūsu gadījumā mēs ņemsim vērā tikai datus tieši no UDP paketes satura bez OSI slāņa protokola galvenēm, proti, DHCP struktūras:
DHCPDISCOVER
Tātad ierīces IP adreses iegūšanas process sākas ar to, ka DHCP klients nosūta apraides pieprasījumu no 68. porta uz 255.255.255.255:67. Šajā pakotnē klients iekļauj savu MAC adresi, kā arī to, ko tieši tas vēlas saņemt no DHCP servera. Iepakojuma struktūra ir aprakstīta tabulā zemāk.
DHCPDISCOVER pakešu struktūras tabula
Pozīcija iepakojumā
Vērtības nosaukums
Piemērs
Ievads
Baits
Noskaidrošana
1
Sāknēšanas pieprasījums
1
Hex
1
Ziņojuma veids. 1 - pieprasījums no klienta uz serveri, 2 - atbilde no servera uz klientu
2
Aparatūras veids
1
Hex
1
Aparatūras adreses veids, šajā protokolā 1 - MAC
3
Aparatūras adreses garums
6
Hex
1
Ierīces MAC adreses garums
4
Apiņi
1
Hex
1
Starpmaršrutu skaits
5
Darījuma ID
23:cf:de:1d
Hex
4
Unikāls darījuma identifikators. To ģenerē klients pieprasījuma darbības sākumā
7
Otrais pagājis
0
Hex
4
Laiks sekundēs no adreses iegūšanas procesa sākuma
9
Zābaku karodziņi
0
Hex
2
Atsevišķi karodziņi, kurus var iestatīt, lai norādītu protokola parametrus
11
Klienta IP adrese
0.0.0.0
String
4
Klienta IP adrese (ja tāda ir)
15
Jūsu klienta IP adrese
0.0.0.0
String
4
Servera piedāvātā IP adrese (ja pieejama)
19
Nākamā servera IP adrese
0.0.0.0
String
4
Servera IP adrese (ja zināma)
23
Releja aģenta IP adrese
172.16.114.41
String
4
Releja aģenta (piemēram, slēdža) IP adrese
27
Klienta MAC adrese
14:d6:4d:a7:c9:55
Hex
6
Pakešu sūtītāja (klienta) MAC adrese
31
Klienta aparatūras adreses aizpildīšana
Hex
10
Rezervēta vieta. Parasti aizpilda ar nullēm
41
Servera saimniekdatora nosaukums
String
64
DHCP servera nosaukums. Parasti netiek pārraidīts
105
Sāknēšanas faila nosaukums
String
128
Faila nosaukums serverī, ko sāknēšanas laikā izmanto bezdiska stacijas
235
Burvju cepumi
63: 82: 53: 63
Hex
4
“Maģiskais” numurs, saskaņā ar kuru, t.sk. varat noteikt, ka šī pakete pieder DHCP protokolam
DHCP opcijas. Var iet jebkurā secībā
236
Opcijas numurs
53
Decembris
1
Opcija 53, kas norāda DHCP paketes veidu
1 — DHCPDISCOVER
3 - DHCPREQUEST
2 — DHCPPIEDĀVĀJUMS
5 - DHCPACK
8 - DHCPINFORM
Opcijas garums
1
Decembris
1
Opcijas vērtība
1
Decembris
1
Opcijas numurs
50
Decembris
1
Kādu IP adresi klients vēlas saņemt?
Opcijas garums
4
Decembris
1
Opcijas vērtība
172.16.134.61
String
4
Opcijas numurs
55
1
Klienta pieprasītie tīkla parametri. Sastāvs var atšķirties
01 — tīkla maska
03 — vārteja
06 - DNS
oc — resursdatora nosaukums
0f - tīkla domēna nosaukums
1c — apraides pieprasījuma adrese (apraide)
42 — TFTP servera nosaukums
79 - Statiskais maršruts bez klasēm
Opcijas garums
8
1
Opcijas vērtība
01:03:06:0c:0f:1c:42:79
8
Opcijas numurs
82
Decembris
82. iespēja, kas pārraida atkārtotāja ierīces MAC adresi un dažas papildu vērtības.
Visbiežāk tas ir slēdža ports, uz kura darbojas gala DHCP klients.Šī opcija satur papildu parametrus.Pirmais baits ir “apakšopcijas” numurs, otrais ir tā garums, tad tā vērtība.
Šajā gadījumā 82. opcijā apakšopcijas ir ligzdotas:
Aģenta shēmas ID = 00:04:00:01:00:04, kur pēdējie divi baiti ir DHCP klienta ports, no kura tika saņemts pieprasījums
Aģenta attālais ID = 00:06:c8:be:19:93:11:48 — DHCP atkārtotāja ierīces MAC adrese
Opcijas garums
18
Decembris
Opcijas vērtība
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Hex
Pakas beigas
255
Decembris
1
255 simbolizē paciņas beigas
DHCPPIEDĀVĀJUMS
Tiklīdz serveris saņem DHCPDISCOVER paketi un redz, ka var piedāvāt klientam kaut ko no pieprasītās, tad ģenerē tai atbildi - DHCPDISCOVER. Atbilde tiek nosūtīta uz ostu “no kurienes tā nāca”, ar apraidi, jo uz doto brīdi klientam vēl nav IP adreses, tāpēc tas var pieņemt paketi tikai tad, ja tā tiek nosūtīta ar apraidi. Klients atpazīst, ka šī ir viņam paredzēta pakotne, pēc viņa MAC adreses paketē, kā arī darījuma numura, ko viņš ģenerē pirmās pakotnes izveides laikā.
DHCPOFFER pakešu struktūras tabula
Pozīcija iepakojumā
Vērtības nosaukums (parasti)
Piemērs
Ievads
Baits
Noskaidrošana
1
Sāknēšanas pieprasījums
1
Hex
1
Ziņojuma veids. 1 - pieprasījums no klienta uz serveri, 2 - atbilde no servera uz klientu
2
Aparatūras veids
1
Hex
1
Aparatūras adreses veids, šajā protokolā 1 - MAC
3
Aparatūras adreses garums
6
Hex
1
Ierīces MAC adreses garums
4
Apiņi
1
Hex
1
Starpmaršrutu skaits
5
Darījuma ID
23:cf:de:1d
Hex
4
Unikāls darījuma identifikators. To ģenerē klients pieprasījuma darbības sākumā
7
Otrais pagājis
0
Hex
4
Laiks sekundēs no adreses iegūšanas procesa sākuma
9
Zābaku karodziņi
0
Hex
2
Atsevišķi karodziņi, kurus var iestatīt, lai norādītu protokola parametrus. Šajā gadījumā 0 nozīmē Unicast pieprasījuma veidu
11
Klienta IP adrese
0.0.0.0
String
4
Klienta IP adrese (ja tāda ir)
15
Jūsu klienta IP adrese
172.16.134.61
String
4
Servera piedāvātā IP adrese (ja pieejama)
19
Nākamā servera IP adrese
0.0.0.0
String
4
Servera IP adrese (ja zināma)
23
Releja aģenta IP adrese
172.16.114.41
String
4
Releja aģenta (piemēram, slēdža) IP adrese
27
Klienta MAC adrese
14:d6:4d:a7:c9:55
Hex
6
Pakešu sūtītāja (klienta) MAC adrese
31
Klienta aparatūras adreses aizpildīšana
Hex
10
Rezervēta vieta. Parasti aizpilda ar nullēm
41
Servera saimniekdatora nosaukums
String
64
DHCP servera nosaukums. Parasti netiek pārraidīts
105
Sāknēšanas faila nosaukums
String
128
Faila nosaukums serverī, ko sāknēšanas laikā izmanto bezdiska stacijas
235
Burvju cepumi
63: 82: 53: 63
Hex
4
“Maģiskais” numurs, saskaņā ar kuru, t.sk. varat noteikt, ka šī pakete pieder DHCP protokolam
DHCP opcijas. Var iet jebkurā secībā
236
Opcijas numurs
53
Decembris
1
53. opcija, kas nosaka DHCP 2 pakešu veidu - DHCPOFFER
Opcijas garums
1
Decembris
1
Opcijas vērtība
2
Decembris
1
Opcijas numurs
1
Decembris
1
Iespēja piedāvāt DHCP klientam tīkla masku
Opcijas garums
4
Decembris
1
Opcijas vērtība
255.255.224.0
String
4
Opcijas numurs
3
Decembris
1
Iespēja piedāvāt DHCP klientam noklusējuma vārteju
Opcijas garums
4
Decembris
1
Opcijas vērtība
172.16.12.1
String
4
Opcijas numurs
6
Decembris
1
Iespēja piedāvāt DHCP DNS klientam
Opcijas garums
4
Decembris
1
Opcijas vērtība
8.8.8.8
String
4
Opcijas numurs
51
Decembris
1
Izdoto tīkla parametru kalpošanas laiks sekundēs, pēc kura DHCP klientam tie jāpieprasa vēlreiz
Opcijas garums
4
Decembris
1
Opcijas vērtība
86400
Decembris
4
Opcijas numurs
82
Decembris
1
82. iespēja, atkārto to, kas bija programmā DHCPDISCOVER
Opcijas garums
18
Decembris
1
Opcijas vērtība
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Decembris
18
Pakas beigas
255
Decembris
1
255 simbolizē paciņas beigas
DHCPREQUEST
Pēc tam, kad klients ir saņēmis DHCPOFFER, viņš veido paketi, pieprasot tīkla parametrus nevis visiem tīklā esošajiem DHCP serveriem, bet tikai vienam konkrētam, kura DHCPOFFER piedāvājums viņam “patika” visvairāk. "Patīk" kritēriji var būt dažādi un atkarīgi no klienta DHCP ieviešanas. Pieprasījuma adresāts tiek norādīts, izmantojot DHCP servera MAC adresi. Tāpat klients var nosūtīt DHCPREQUEST paketi, iepriekš neģenerējot DHCPDISCOVER, ja servera IP adrese jau ir iegūta iepriekš.
DHCPREQUEST pakešu struktūras tabula
Pozīcija iepakojumā
Vērtības nosaukums (parasti)
Piemērs
Ievads
Baits
Noskaidrošana
1
Sāknēšanas pieprasījums
1
Hex
1
Ziņojuma veids. 1 - pieprasījums no klienta uz serveri, 2 - atbilde no servera uz klientu
2
Aparatūras veids
1
Hex
1
Aparatūras adreses veids, šajā protokolā 1 - MAC
3
Aparatūras adreses garums
6
Hex
1
Ierīces MAC adreses garums
4
Apiņi
1
Hex
1
Starpmaršrutu skaits
5
Darījuma ID
23:cf:de:1d
Hex
4
Unikāls darījuma identifikators. To ģenerē klients pieprasījuma darbības sākumā
7
Otrais pagājis
0
Hex
4
Laiks sekundēs no adreses iegūšanas procesa sākuma
9
Zābaku karodziņi
8000
Hex
2
Atsevišķi karodziņi, kurus var iestatīt, lai norādītu protokola parametrus. Šajā gadījumā ir iestatīta “apraide”.
11
Klienta IP adrese
0.0.0.0
String
4
Klienta IP adrese (ja tāda ir)
15
Jūsu klienta IP adrese
172.16.134.61
String
4
Servera piedāvātā IP adrese (ja pieejama)
19
Nākamā servera IP adrese
0.0.0.0
String
4
Servera IP adrese (ja zināma)
23
Releja aģenta IP adrese
172.16.114.41
String
4
Releja aģenta (piemēram, slēdža) IP adrese
27
Klienta MAC adrese
14:d6:4d:a7:c9:55
Hex
6
Pakešu sūtītāja (klienta) MAC adrese
31
Klienta aparatūras adreses aizpildīšana
Hex
10
Rezervēta vieta. Parasti aizpilda ar nullēm
41
Servera saimniekdatora nosaukums
String
64
DHCP servera nosaukums. Parasti netiek pārraidīts
105
Sāknēšanas faila nosaukums
String
128
Faila nosaukums serverī, ko sāknēšanas laikā izmanto bezdiska stacijas
235
Burvju cepumi
63: 82: 53: 63
Hex
4
“Maģiskais” numurs, saskaņā ar kuru, t.sk. varat noteikt, ka šī pakete pieder DHCP protokolam
DHCP opcijas. Var iet jebkurā secībā
236
Opcijas numurs
53
Decembris
3
53. opcija, kas definē DHCP pakešu tipu 3 — DHCPREQUEST
Opcijas garums
1
Decembris
1
Opcijas vērtība
3
Decembris
1
Opcijas numurs
61
Decembris
1
Klienta ID: 01 (Ehernet) + klienta MAC adrese
Opcijas garums
7
Decembris
1
Opcijas vērtība
01:2c:ab:25:ff:72:a6
Hex
7
Opcijas numurs
60
Decembris
"Pārdevēja klases identifikators." Manā gadījumā tas norāda DHCP klienta versiju. Citas ierīces var atgriezt atšķirīgu informāciju. Windows piemēram, MSFT 5.0 ziņojumi
Opcijas garums
11
Decembris
Opcijas vērtība
udhcp 0.9.8
String
Opcijas numurs
55
1
Klienta pieprasītie tīkla parametri. Sastāvs var atšķirties
01 — tīkla maska
03 — vārteja
06 - DNS
oc — resursdatora nosaukums
0f - tīkla domēna nosaukums
1c — apraides pieprasījuma adrese (apraide)
42 — TFTP servera nosaukums
79 - Statiskais maršruts bez klasēm
Opcijas garums
8
1
Opcijas vērtība
01:03:06:0c:0f:1c:42:79
8
Opcijas numurs
82
Decembris
1
82. iespēja, atkārto to, kas bija programmā DHCPDISCOVER
Opcijas garums
18
Decembris
1
Opcijas vērtība
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Decembris
18
Pakas beigas
255
Decembris
1
255 simbolizē paciņas beigas
DHCPACK
Kā apstiprinājumu, ka “jā, tā ir, šī ir jūsu IP adrese, un es to nevienam citam neizdošu” no DHCP servera, tiek apkalpota pakete DHCPACK formātā no servera uz klientu. To pārraida tāpat kā citas paketes. Lai gan tālāk esošajā kodā Python ieviestajam DHCP serverim katram gadījumam es dublēju jebkuru apraides pieprasījumu, nosūtot paketi uz konkrētu klienta IP, ja tas jau ir zināms. Turklāt DHCP serverim ir pilnīgi vienalga, vai DHCPACK pakete ir sasniegusi klientu. Ja klients nesaņem DHCPACK, tad pēc kāda laika tas vienkārši atkārto DHCPREQUEST
DHCPACK pakešu struktūras tabula
Pozīcija iepakojumā
Vērtības nosaukums (parasti)
Piemērs
Ievads
Baits
Noskaidrošana
1
Sāknēšanas pieprasījums
2
Hex
1
Ziņojuma veids. 1 - pieprasījums no klienta uz serveri, 2 - atbilde no servera uz klientu
2
Aparatūras veids
1
Hex
1
Aparatūras adreses veids, šajā protokolā 1 - MAC
3
Aparatūras adreses garums
6
Hex
1
Ierīces MAC adreses garums
4
Apiņi
1
Hex
1
Starpmaršrutu skaits
5
Darījuma ID
23:cf:de:1d
Hex
4
Unikāls darījuma identifikators. To ģenerē klients pieprasījuma darbības sākumā
7
Otrais pagājis
0
Hex
4
Laiks sekundēs no adreses iegūšanas procesa sākuma
9
Zābaku karodziņi
8000
Hex
2
Atsevišķi karodziņi, kurus var iestatīt, lai norādītu protokola parametrus. Šajā gadījumā ir iestatīta “apraide”.
11
Klienta IP adrese
0.0.0.0
String
4
Klienta IP adrese (ja tāda ir)
15
Jūsu klienta IP adrese
172.16.134.61
String
4
Servera piedāvātā IP adrese (ja pieejama)
19
Nākamā servera IP adrese
0.0.0.0
String
4
Servera IP adrese (ja zināma)
23
Releja aģenta IP adrese
172.16.114.41
String
4
Releja aģenta (piemēram, slēdža) IP adrese
27
Klienta MAC adrese
14:d6:4d:a7:c9:55
Hex
6
Pakešu sūtītāja (klienta) MAC adrese
31
Klienta aparatūras adreses aizpildīšana
Hex
10
Rezervēta vieta. Parasti aizpilda ar nullēm
41
Servera saimniekdatora nosaukums
String
64
DHCP servera nosaukums. Parasti netiek pārraidīts
105
Sāknēšanas faila nosaukums
String
128
Faila nosaukums serverī, ko sāknēšanas laikā izmanto bezdiska stacijas
235
Burvju cepumi
63: 82: 53: 63
Hex
4
“Maģiskais” numurs, saskaņā ar kuru, t.sk. varat noteikt, ka šī pakete pieder DHCP protokolam
DHCP opcijas. Var iet jebkurā secībā
236
Opcijas numurs
53
Decembris
3
53. opcija, kas nosaka DHCP pakešu veidu 5 — DHCPACK
Opcijas garums
1
Decembris
1
Opcijas vērtība
5
Decembris
1
Opcijas numurs
1
Decembris
1
Iespēja piedāvāt DHCP klientam tīkla masku
Opcijas garums
4
Decembris
1
Opcijas vērtība
255.255.224.0
String
4
Opcijas numurs
3
Decembris
1
Iespēja piedāvāt DHCP klientam noklusējuma vārteju
Opcijas garums
4
Decembris
1
Opcijas vērtība
172.16.12.1
String
4
Opcijas numurs
6
Decembris
1
Iespēja piedāvāt DHCP DNS klientam
Opcijas garums
4
Decembris
1
Opcijas vērtība
8.8.8.8
String
4
Opcijas numurs
51
Decembris
1
Izdoto tīkla parametru kalpošanas laiks sekundēs, pēc kura DHCP klientam tie jāpieprasa vēlreiz
Opcijas garums
4
Decembris
1
Opcijas vērtība
86400
Decembris
4
Opcijas numurs
82
Decembris
1
82. iespēja, atkārto to, kas bija programmā DHCPDISCOVER
Opcijas garums
18
Decembris
1
Opcijas vērtība
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Decembris
18
Pakas beigas
255
Decembris
1
255 simbolizē paciņas beigas
Uzstādīšana
Instalācija faktiski sastāv no darbam nepieciešamo python moduļu uzstādīšanas. Tiek pieņemts, ka MySQL jau ir instalēts un konfigurēts.
FreeBSD
pkg instalēt python3 python3 -m securepip pip3 instalēt mysql savienotāju
Ubuntu
sudo apt-get instalēt python3 sudo apt-get instalēt pip3 sudo pip3 instalēt mysql-connector
Mēs izveidojam MySQL datu bāzi, augšupielādējam tajā pydhcp.sql dump un konfigurējam konfigurācijas failu.
Konfigurācija
Visi servera iestatījumi ir xml failā. Atsauces fails:
1.0 0.0.0.0 255.255.255.255 192.168.0.71 8600 1 255.255.255.0 192.168.0.1 vietējais saimnieks pārbaude pārbaude 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 atlasiet ip,mask,router,dns no lietotājiem, kur augšējais(mac)=augšējais('{option_3_AgentRemoteId_hex}') un augšējais(ports)=upper('{option_1_AgentCircuitId_port_hex}') atlasiet ip,mask,router,dns no lietotājiem, kur augšējais(mac)=augšējais('{sw_mac}') un augšējais(ports)=augšējais('{sw_port82}') atlasiet ip,mask,router,dns no lietotājiem, kur augšējais(mac)=upper('{ClientMacAddress}') ievietot vēsturē (id,dt,mac,ip,comment) vērtības (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')Tagad sīkāk par tagiem:
Sadaļā dhcpserver ir aprakstīti pamata iestatījumi servera palaišanai, proti:
- resursdators — kādu IP adresi serveris klausās 67. portā
- apraide — kura IP ir pārraide DHCPOFFER un DHCPACK
- DHCPServer - kāds ir DHCP servera IP
- Izsniegtās IP adreses LeaseTime nomas laiks
- ThreadLimit — cik pavedienu vienlaikus darbojas, lai apstrādātu ienākošās UDP paketes portā 67. Tam vajadzētu palīdzēt lielas slodzes projektos 😉
- defaultMask,defaultRouter,defaultDNS - kas pēc noklusējuma tiek piedāvāts abonentam, ja datu bāzē tiek atrasts IP, bet tam nav norādīti papildu parametri
mysql sadaļa:
resursdators, lietotājvārds, parole, bāzes nosaukums - viss runā pats par sevi. Aptuvenā datu bāzes struktūra ir publicēta
Vaicājumu sadaļa: pieprasījumi PIEDĀVĀJUMA/ATKRIEŠANAS saņemšanai ir aprakstīti šeit:
- offer_count — rindu skaits ar pieprasījumiem, kas atgriež rezultātu, piemēram, ip, mask, router, dns
- offer_n — vaicājuma virkne. Ja atgriešana ir tukša, izpilda šādu piedāvājuma pieprasījumu
- history_sql - vaicājums, kas raksta, piemēram, abonenta “autorizācijas vēsturē”
Pieprasījumos var iekļaut jebkurus mainīgos lielumus no opciju sadaļas vai opcijas no DHCP protokola.
Opciju sadaļa. Šeit tas kļūst interesantāk. Šeit mēs varam izveidot mainīgos, ko varam izmantot vēlāk vaicājumu sadaļā.
Piemēram:
option_82_hex:sw_port1:20:22, šī komandrinda aizņem visu rindu, kas tika iekļauta DHCP pieprasījuma opcijā 82, heksadecimālā formātā diapazonā no 20 līdz 22 baitiem (ieskaitot), un ievieto to jaunajā mainīgajā sw_port1 (slēgt portu, no kurienes tika saņemts pieprasījums)
option_82_hex:sw_mac:26:40, definējiet sw_mac mainīgo, ņemot hex no diapazona 26:40
Jūs varat redzēt visas iespējamās opcijas, kuras var izmantot vaicājumos, startējot serveri ar slēdzi -d. Mēs redzēsim kaut ko līdzīgu šim žurnālam:
-- DHCPINFORM pakete ieradās 67. portā no 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress'B,0025224'764CAddress'00t,7'91 ': b'x5 0%"Jxd3d" , ' HType': 'Ethernet', 'HostName': b'x5xa9xe8xa8xa43xa0.0.0.0-x5.0fx0025224a', 'ReqListDNS': True, 'ReqListDomainName': True, 'ReqListPerfowmRouter': TrustL:Discover''Req ReqListStaticRoute': patiess, 'ReqListSubnetM ask': True, 'ReqListVendorSpecInfo': 764, 'RequestedIpAddress': '172.30.128.13', 'Vendor': b'MSFT 00', 'chaddr': '00ad172.30.114.25'dr'308', 6. , 'flags': b'x1x82', 'giaddr': '12', 'gpoz': 12, 'hlen': 53, 'hops': 53, 'htype': 'MAC', 'magic_cookie': b'cx55Sc ', 'op': 'DHCPINFORM', 'opcija 55': 60, 'opcija 60': 61, 'opcija 61': 82, 'opcija 82': 82, 'opcija 12': 01, 'opcija06': 00 option_04_byte': b'x00x01x00x06x02x08x00x06x00x1x9x2' b'x82x12010600040001000602080006001x589eXx2exb82xad', 'opcija_18_hex': '82 'option_12_len': 01 06, 'option_00_str': "b'x04x00x01x00x06x02x08x00x06x00x1x9x2x768x0.0.0.0eXx001exb589xad'", "rezultāts": false,', '2cs 'siaddr': '1', 'sw_mac': '06e89eb8ad', 'sw_port3': '897', 'xidbyte': b'Attiecīgi mēs varam ietīt jebkuru mainīgo {}, un tas tiks izmantots SQL vaicājumā.
Reģistrēsim vēsturei, ka klients saņēma IP adresi:


Servera palaišana
./pydhcpdb.py -d -c config.xml
— d konsoles izvades režīms DEBUG
- c <faila nosaukums> konfigurācijas fails
Pārskats
Un tagad sīkāka informācija par servera ieviešanu Python. Tās ir sāpes. Python tika apgūts lidojumā. Daudzi mirkļi ir veidoti stilā "wow, man kaut kā izdevās." Nemaz nav optimizēts un atstāts šādā formā galvenokārt tāpēc, ka ir maz pieredzes Python izstrādē. Es pakavēšos pie interesantākajiem servera ieviešanas aspektiem “kodā”.
XML konfigurācijas failu parsētājs
Tiek izmantots standarta Python modulis xml.dom. Šķiet vienkārši, taču ieviešanas laikā bija manāms skaidras dokumentācijas un piemēru trūkums tīklā, izmantojot šo moduli.
koks = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") elementam mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("host")Child.dartast[0]. gconfig["mysql_username"]=elem.getElementsByTagName("lietotājvārds")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("parole")[0].first"g =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") elementam dconfig: gconfig["broadcast"]=elem.getElementsByTagcast.") firstChild.data gconfig["dhcp_host"]=elem.getElementsByTagName("host")[0].firstChild.data gconfig["dhcp_LeaseTime"]=elem.getElementsByTagName("LeaseTime")gstcon[0]. dhcp_threadlimit "] = int (elem.getElementsByTagName (" threadlimit ") [0] .firstchild.data) gconfig [" dhcp_server "] = elem.getElementsByTagname (" dhcpServer ") =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig " defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("vaicājums") elementam qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[0].firstChild in. range(int(gconfig["piedāvājuma_skaits"])): gconfig["piedāvājums_"+str(num+0)]=elem.getElementsByTagName("piedāvājums"+str(num+0))[1].firstChild.data gconfig ["history_sql"]=elem.getElementsByTagName("history_sql")[1].firstChild.data options=tree.getElementsByTagName("options") elementam opcijās: node=elem.getElementsByTagName("option") opcijām node : opcijasMod.append(options.firstChild.data)Daudzpavedienu veidošana
Savādi, bet vairāku pavedienu veidošana Python ir ieviesta ļoti skaidri un vienkārši.
def PacketWork(data,addr): ... # ienākošās paketes parsēšanas un atbildes uz to ieviešana ... while True: data, addr = udp_socket.recvfrom(1024) # gaida UDP paketes pavedienu = threading.Thread( target=PacketWork , args=(data,addr,)).start() # kā tas bija - palaižam fonā iepriekš definēto PacketWork funkciju ar parametriem, kamēr threading.active_count() >gconfig["dhcp_ThreadLimit"]: laiks. miega(1) # ja numurs Jau darbojas vairāk pavedienu nekā iestatījumos, mēs gaidām, kamēr to būs mazāk
Saņemt/nosūtīt DHCP paketi
Lai pārtvertu UDP paketes, kas nāk caur tīkla karti, jums ir "jāpaceļ" ligzda:
udp_socket = ligzda.ligzda(ligzda.AF_INET,ligzda.SOCK_DGRAM,ligzda.IPPROTO_UDP) udp_socket.bind((gconfig["dhcp_host"],67))
, kur karogi ir:
- AF_INET - nozīmē, ka adreses formāts būs IP: ports. Var būt arī AF_UNIX — kur adrese tiek norādīta ar faila nosaukumu.
- SOCK_DGRAM - nozīmē, ka mēs nepieņemam “neapstrādātu paketi”, bet gan tādu, kas jau ir izgājusi cauri ugunsmūrim un ar daļēji apgrieztu paketi. Tie. mēs saņemam tikai UDP paketi bez UDP pakešu iesaiņojuma “fiziskā” komponenta. Ja izmantojat karodziņu SOCK_RAW, jums būs arī jāparsē šis “iesaiņojums”.
Pakešu nosūtīšana var būt kā apraide:
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #pārslēdziet ligzdu apraides režīmā rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))
un uz adresi “no kurienes nāca paka”:
udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # pārslēdziet ligzdu uz vairāku klausītāju režīmu rz=udp_socket.sendto(packetack, addr)
, kur SOL_SOCKET nozīmē “protokola līmeni” opciju iestatīšanai,
, SO_BROADCAST opciju, ka ķiveres pakete ir “pārraide”
Opcija ,SO_REUSEADDR pārslēdz ligzdu uz “daudzu klausītāju” režīmu. Teorētiski šajā gadījumā tas ir lieki, taču vienā no FreeBSD serveriem, kurā testēju, kods bez šīs opcijas nedarbojās.
DHCP paketes parsēšana
Šeit man ļoti patika Python. Izrādās, ka no kastes tas ļauj būt diezgan elastīgam ar baitkodu. Ļaujot to ļoti viegli pārtulkot decimālvērtībās, virknēs un hex - t.i. tas ir tas, kas mums patiesībā ir nepieciešams, lai saprastu paketes struktūru. Piemēram, jūs varat iegūt virkni baitu HEX un tikai baitus:
res["xidhex"]=dati[4:8].hex() res["xidbyte"]=dati[4:8]
, iesaiņojiet baitus struktūrā:
res["flags"]=pack('BB',data[10],data[11])Iegūstiet IP no struktūras:
res["ciaddr"]=socket.inet_ntoa(pack('BBBB',data[12],data[13],data[14],dati[15]));Un otrādi:
res=res+socket.inet_pton(ligzda.AF_INET, gconfig["dhcp_Server"])
Pagaidām tas arī viss 😉
Avots: www.habr.com
