DHCP+Mysql server v Pythonu

DHCP+Mysql server v Pythonu

Účelem tohoto projektu bylo:

  • Informace o DHCP v síti IPv4
  • Učení Pythonu (trochu více než od nuly 😉)
  • výměna serveru DB2DHCP (moje vidlice), originál zde, jehož sestavení pro nový OS je stále obtížnější. A nelíbí se mi, že je to binární soubor, který neexistuje žádný způsob, jak „změnit právě teď“
  • získání funkčního serveru DHCP s možností vybrat IP adresu účastníka pomocí kombinace mac nebo switch mac+port (volba 82)
  • psát další kolo (Oh! to je moje oblíbená činnost)
  • přijímání komentářů o vaší klubovosti na Habrahabru (nebo ještě lépe pozvánky) 😉

Výsledek: funguje 😉 Testováno na FreeBSD a Ubuntu OS. Teoreticky lze kód požádat, aby fungoval pod jakýmkoli OS, protože Zdá se, že v kódu nejsou žádné specifické vazby.
Opatrně! Je toho ještě hodně.

Odkaz na úložiště pro amatéry "dotknout se živě".

Proces instalace, konfigurace a používání výsledku „studia hardwaru“ je mnohem nižší a pak trocha teorie o protokolu DHCP. Pro mě. A k historii 😉

Trochu teorie

Co je DHCP

Jedná se o síťový protokol, který umožňuje zařízení zjistit svou IP adresu (a další parametry, jako je brána, DNS atd.) ze serveru DHCP. Pakety jsou vyměňovány pomocí protokolu UDP. Obecný princip fungování zařízení při požadavku na síťové parametry je následující:

  1. Zařízení (klient) odešle požadavek na vysílání UDP (DHCPDISCOVER) po celé síti s požadavkem „no, dejte mi někdo IP adresu“. Navíc obvykle (ale ne vždy) požadavek přichází z portu 68 (zdroj) a cílem je port 67 (cíl). Některá zařízení také odesílají pakety z portu 67. MAC adresa klientského zařízení je součástí paketu DHCPDISCOVER.
  2. Všechny servery DHCP umístěné v síti (a může jich být několik) tvoří nabídku DHCPOFFER se síťovým nastavením pro zařízení, které odeslalo DHCPDISCOVER, a také ji vysílají po síti. Identifikace toho, komu je tento paket určen, je založena na MAC adrese klienta uvedené dříve v požadavku DHCPDISCOVER.
  3. Klient přijme pakety s návrhy na nastavení sítě, vybere ten nejatraktivnější (kritéria se mohou lišit, např. čas doručení paketu, počet mezisměr) a provede „oficiální požadavek“ DHCPREQUEST s nastavením sítě. z DHCP serveru, který se mu líbí. V tomto případě jde paket na konkrétní server DHCP.
  4. Server, který přijal DHCPREQUEST, odešle paket ve formátu DHCPACK, ve kterém ještě jednou vypíše síťová nastavení určená pro tohoto klienta.

DHCP+Mysql server v Pythonu

Kromě toho existují pakety DHCPINFORM, které přicházejí od klienta a jejichž účelem je informovat server DHCP, že „klient žije“ a používá vydaná síťová nastavení. V implementaci tohoto serveru jsou tyto pakety ignorovány.

Formát balíčku

Ethernetový paketový rámec obecně vypadá nějak takto:

DHCP+Mysql server v Pythonu

V našem případě budeme uvažovat pouze data přímo z obsahu paketu UDP, bez hlaviček protokolu vrstvy OSI, konkrétně struktury DHCP:

DHCPDISCOVER

Proces získání IP adresy pro zařízení tedy začíná tím, že klient DHCP odešle požadavek na vysílání z portu 68 na 255.255.255.255:67. V tomto balíčku klient obsahuje svou MAC adresu a také to, co přesně chce přijímat od DHCP serveru. Struktura balíčku je popsána v tabulce níže.

Tabulka struktury paketů DHCPDISCOVER

Umístění v balení
Název hodnoty
příklad
Úvod
Byte
Objasnění

1
Požadavek na spuštění
1
Hex
1
Typ zprávy. 1 - požadavek od klienta na server, 2 - odpověď ze serveru na klienta

2
Typ hardwaru
1
Hex
1
Typ hardwarové adresy, v tomto protokolu 1 - MAC

3
Délka hardwarových adres
6
Hex
1
Délka MAC adresy zařízení

4
Chmel
1
Hex
1
Počet mezilehlých tras

5
ID transakce
23:cf:de:1d
Hex
4
Jedinečný identifikátor transakce. Generuje klient na začátku operace požadavku

7
Uplynula druhá
0
Hex
4
Čas v sekundách od začátku procesu získávání adresy

9
Spouštěcí příznaky
0
Hex
2
Určité příznaky, které lze nastavit k označení parametrů protokolu

11
IP adresa klienta
0.0.0.0
Řetězec
4
IP adresa klienta (pokud existuje)

15
IP adresa vašeho klienta
0.0.0.0
Řetězec
4
IP adresa nabízená serverem (pokud je k dispozici)

19
IP adresa dalšího serveru
0.0.0.0
Řetězec
4
IP adresa serveru (pokud je známa)

23
IP adresa přenosového agenta
172.16.114.41
Řetězec
4
IP adresa přenosového agenta (například přepínače)

27
MAC adresa klienta
14:d6:4d:a7:c9:55
Hex
6
MAC adresa odesílatele paketů (klienta)

31
Výplň hardwarové adresy klienta
 
Hex
10
Rezervované místo. Obvykle vyplněno nulami

41
Název hostitele serveru
 
Řetězec
64
název serveru DHCP. Obvykle se nepřenáší

105
Název spouštěcího souboru
 
Řetězec
128
Název souboru na serveru používaný bezdiskovými stanicemi při bootování

235
Kouzelná sušenka
63: 82: 53: 63
Hex
4
„Magické“ číslo, podle kterého vč. můžete určit, že tento paket patří do protokolu DHCP

možnosti DHCP. Může jít v libovolném pořadí

236
Číslo možnosti
53
prosince
1
Možnost 53, která určuje typ paketu DHCP

1 - DHCPDISCOVER
3 - DHCPREQUEST
2 - NABÍDKA DHCP
5 - DHCPACK
8 - DHCPINFORM

 
Délka varianty
1
prosince
1

 
Hodnota opce
1
prosince
1

 
Číslo možnosti
50
prosince
1
Jakou IP adresu chce klient obdržet?

 
Délka varianty
4
prosince
1

 
Hodnota opce
172.16.134.61
Řetězec
4

 
Číslo možnosti
55
 
1
Parametry sítě požadované klientem. Složení se může lišit

01 — Maska sítě
03 - Brána
06 - DNS
oc — Název hostitele
0f - název síťové domény
1c - adresa požadavku na vysílání (vysílání)
42 - Název serveru TFTP
79 - Beztřídní statická cesta

 
Délka varianty
8
 
1

 
Hodnota opce
01:03:06:0c:0f:1c:42:79
 
8

 
Číslo možnosti
82
prosince
 
Možnost 82, která přenáší MAC adresu opakovacího zařízení a některé další hodnoty.

Nejčastěji se jedná o port switche, na kterém běží koncový DHCP klient.Tato volba obsahuje další parametry.První byte je číslo „podvolby“, druhý je její délka a poté její hodnota.

V tomto případě jsou ve volbě 82 vnořené dílčí možnosti:
ID okruhu agenta = 00:04:00:01:00:04, kde poslední dva bajty jsou port klienta DHCP, ze kterého požadavek přišel

ID vzdáleného agenta = 00:06:c8:be:19:93:11:48 - MAC adresa zařízení DHCP repeater

 
Délka varianty
18
prosince
 

 
Hodnota opce
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Hex
 

 
Konec balení
255
prosince
1
255 symbolizuje konec paketu

DHCPOFFER

Jakmile server obdrží paket DHCPDISCOVER a pokud uvidí, že může klientovi něco nabídnout z požadovaného, ​​vygeneruje na něj odpověď - DHCPDISCOVER. Odpověď je odeslána na port „odkud to přišlo“, vysíláním, protože v tuto chvíli klient ještě nemá IP adresu, proto může přijmout paket pouze v případě, že je odeslán broadcastem. Klient pozná, že se jedná o balíček pro něj, podle MAC adresy uvnitř balíčku a také podle čísla transakce, které si vygeneruje v okamžiku vytvoření prvního balíčku.

Tabulka struktury paketů DHCPOFFER

Umístění v balení
Název hodnoty (společný)
příklad
Úvod
Byte
Objasnění

1
Požadavek na spuštění
1
Hex
1
Typ zprávy. 1 - požadavek od klienta na server, 2 - odpověď ze serveru na klienta

2
Typ hardwaru
1
Hex
1
Typ hardwarové adresy, v tomto protokolu 1 - MAC

3
Délka hardwarových adres
6
Hex
1
Délka MAC adresy zařízení

4
Chmel
1
Hex
1
Počet mezilehlých tras

5
ID transakce
23:cf:de:1d
Hex
4
Jedinečný identifikátor transakce. Generuje klient na začátku operace požadavku

7
Uplynula druhá
0
Hex
4
Čas v sekundách od začátku procesu získávání adresy

9
Spouštěcí příznaky
0
Hex
2
Určité příznaky, které lze nastavit k označení parametrů protokolu. V tomto případě 0 znamená typ požadavku Unicast

11
IP adresa klienta
0.0.0.0
Řetězec
4
IP adresa klienta (pokud existuje)

15
IP adresa vašeho klienta
172.16.134.61
Řetězec
4
IP adresa nabízená serverem (pokud je k dispozici)

19
IP adresa dalšího serveru
0.0.0.0
Řetězec
4
IP adresa serveru (pokud je známa)

23
IP adresa přenosového agenta
172.16.114.41
Řetězec
4
IP adresa přenosového agenta (například přepínače)

27
MAC adresa klienta
14:d6:4d:a7:c9:55
Hex
6
MAC adresa odesílatele paketů (klienta)

31
Výplň hardwarové adresy klienta
 
Hex
10
Rezervované místo. Obvykle vyplněno nulami

41
Název hostitele serveru
 
Řetězec
64
název serveru DHCP. Obvykle se nepřenáší

105
Název spouštěcího souboru
 
Řetězec
128
Název souboru na serveru používaný bezdiskovými stanicemi při bootování

235
Kouzelná sušenka
63: 82: 53: 63
Hex
4
„Magické“ číslo, podle kterého vč. můžete určit, že tento paket patří do protokolu DHCP

možnosti DHCP. Může jít v libovolném pořadí

236
Číslo možnosti
53
prosince
1
Možnost 53, která definuje typ paketu DHCP 2 - DHCPOFFER

 
Délka varianty
1
prosince
1

 
Hodnota opce
2
prosince
1

 
Číslo možnosti
1
prosince
1
Možnost nabídnout klientovi DHCP masku sítě

 
Délka varianty
4
prosince
1

 
Hodnota opce
255.255.224.0
Řetězec
4

 
Číslo možnosti
3
prosince
1
Možnost nabídnout klientovi DHCP výchozí bránu

 
Délka varianty
4
prosince
1

 
Hodnota opce
172.16.12.1
Řetězec
4

 
Číslo možnosti
6
prosince
1
Možnost nabídnout DHCP klientovi DNS

 
Délka varianty
4
prosince
1

 
Hodnota opce
8.8.8.8
Řetězec
4

 
Číslo možnosti
51
prosince
1
Životnost vydaných síťových parametrů v sekundách, po jejichž uplynutí si je musí klient DHCP znovu vyžádat

 
Délka varianty
4
prosince
1

 
Hodnota opce
86400
prosince
4

 
Číslo možnosti
82
prosince
1
Možnost 82, opakuje to, co přišlo v DHCPDISCOVER

 
Délka varianty
18
prosince
1

 
Hodnota opce
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
prosince
18

 
Konec balení
255
prosince
1
255 symbolizuje konec paketu

DHCPREQUEST

Poté, co klient obdrží DHCPOFFER, vytvoří paket požadující parametry sítě ne všem DHCP serverům v síti, ale pouze jednomu konkrétnímu, jehož nabídka DHCPOFFER se mu „líbila“ nejvíce. Kritéria „jako“ mohou být různá a záviset na implementaci DHCP klienta. Příjemce požadavku je určen pomocí MAC adresy DHCP serveru. Klient může také odeslat paket DHCPREQUEST bez předchozího generování DHCPDISCOVER, pokud již byla adresa IP serveru získána dříve.

Tabulka struktury paketů DHCPREQUEST

Umístění v balení
Název hodnoty (společný)
příklad
Úvod
Byte
Objasnění

1
Požadavek na spuštění
1
Hex
1
Typ zprávy. 1 - požadavek od klienta na server, 2 - odpověď ze serveru na klienta

2
Typ hardwaru
1
Hex
1
Typ hardwarové adresy, v tomto protokolu 1 - MAC

3
Délka hardwarových adres
6
Hex
1
Délka MAC adresy zařízení

4
Chmel
1
Hex
1
Počet mezilehlých tras

5
ID transakce
23:cf:de:1d
Hex
4
Jedinečný identifikátor transakce. Generuje klient na začátku operace požadavku

7
Uplynula druhá
0
Hex
4
Čas v sekundách od začátku procesu získávání adresy

9
Spouštěcí příznaky
8000
Hex
2
Určité příznaky, které lze nastavit k označení parametrů protokolu. V tomto případě je nastaveno „vysílání“.

11
IP adresa klienta
0.0.0.0
Řetězec
4
IP adresa klienta (pokud existuje)

15
IP adresa vašeho klienta
172.16.134.61
Řetězec
4
IP adresa nabízená serverem (pokud je k dispozici)

19
IP adresa dalšího serveru
0.0.0.0
Řetězec
4
IP adresa serveru (pokud je známa)

23
IP adresa přenosového agenta
172.16.114.41
Řetězec
4
IP adresa přenosového agenta (například přepínače)

27
MAC adresa klienta
14:d6:4d:a7:c9:55
Hex
6
MAC adresa odesílatele paketů (klienta)

31
Výplň hardwarové adresy klienta
 
Hex
10
Rezervované místo. Obvykle vyplněno nulami

41
Název hostitele serveru
 
Řetězec
64
název serveru DHCP. Obvykle se nepřenáší

105
Název spouštěcího souboru
 
Řetězec
128
Název souboru na serveru používaný bezdiskovými stanicemi při bootování

235
Kouzelná sušenka
63: 82: 53: 63
Hex
4
„Magické“ číslo, podle kterého vč. můžete určit, že tento paket patří do protokolu DHCP

možnosti DHCP. Může jít v libovolném pořadí

236
Číslo možnosti
53
prosince
3
Možnost 53, která definuje typ paketu DHCP 3 - DHCPREQUEST

 
Délka varianty
1
prosince
1

 
Hodnota opce
3
prosince
1

 
Číslo možnosti
61
prosince
1
ID klienta: 01 (pro Ehernet) + MAC adresa klienta

 
Délka varianty
7
prosince
1

 
Hodnota opce
01:2c:ab:25:ff:72:a6
Hex
7

 
Číslo možnosti
60
prosince
 
"Identifikátor třídy dodavatele". V mém případě to hlásí verzi klienta DHCP. Možná jiná zařízení vrátí něco jiného. Windows například hlásí MSFT 5.0

 
Délka varianty
11
prosince
 

 
Hodnota opce
udhcp 0.9.8
Řetězec
 

 
Číslo možnosti
55
 
1
Parametry sítě požadované klientem. Složení se může lišit

01 — Maska sítě
03 - Brána
06 - DNS
oc — Název hostitele
0f - název síťové domény
1c - adresa požadavku na vysílání (vysílání)
42 - Název serveru TFTP
79 - Beztřídní statická cesta

 
Délka varianty
8
 
1

 
Hodnota opce
01:03:06:0c:0f:1c:42:79
 
8

 
Číslo možnosti
82
prosince
1
Možnost 82, opakuje to, co přišlo v DHCPDISCOVER

 
Délka varianty
18
prosince
1

 
Hodnota opce
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
prosince
18

 
Konec balení
255
prosince
1
255 symbolizuje konec paketu

DHCPACK

Jako potvrzení, že „ano, je to tak, toto je vaše IP adresa a nikomu ji neposkytnu“ ze serveru DHCP, slouží paket ve formátu DHCPACK ze serveru klientovi. Odesílá se jako ostatní pakety. Ačkoli v níže uvedeném kódu pro server DHCP implementovaný v Pythonu, pro každý případ, duplikuji jakýkoli požadavek na vysílání odesláním paketu na konkrétní IP adresu klienta, pokud je již známa. Navíc DHCP server vůbec nezajímá, zda paket DHCPACK dorazil ke klientovi. Pokud klient neobdrží DHCPACK, tak po chvíli prostě zopakuje DHCPREQUEST

Tabulka struktury paketů DHCPACK

Umístění v balení
Název hodnoty (společný)
příklad
Úvod
Byte
Objasnění

1
Požadavek na spuštění
2
Hex
1
Typ zprávy. 1 - požadavek od klienta na server, 2 - odpověď ze serveru na klienta

2
Typ hardwaru
1
Hex
1
Typ hardwarové adresy, v tomto protokolu 1 - MAC

3
Délka hardwarových adres
6
Hex
1
Délka MAC adresy zařízení

4
Chmel
1
Hex
1
Počet mezilehlých tras

5
ID transakce
23:cf:de:1d
Hex
4
Jedinečný identifikátor transakce. Generuje klient na začátku operace požadavku

7
Uplynula druhá
0
Hex
4
Čas v sekundách od začátku procesu získávání adresy

9
Spouštěcí příznaky
8000
Hex
2
Určité příznaky, které lze nastavit k označení parametrů protokolu. V tomto případě je nastaveno „vysílání“.

11
IP adresa klienta
0.0.0.0
Řetězec
4
IP adresa klienta (pokud existuje)

15
IP adresa vašeho klienta
172.16.134.61
Řetězec
4
IP adresa nabízená serverem (pokud je k dispozici)

19
IP adresa dalšího serveru
0.0.0.0
Řetězec
4
IP adresa serveru (pokud je známa)

23
IP adresa přenosového agenta
172.16.114.41
Řetězec
4
IP adresa přenosového agenta (například přepínače)

27
MAC adresa klienta
14:d6:4d:a7:c9:55
Hex
6
MAC adresa odesílatele paketů (klienta)

31
Výplň hardwarové adresy klienta
 
Hex
10
Rezervované místo. Obvykle vyplněno nulami

41
Název hostitele serveru
 
Řetězec
64
název serveru DHCP. Obvykle se nepřenáší

105
Název spouštěcího souboru
 
Řetězec
128
Název souboru na serveru používaný bezdiskovými stanicemi při bootování

235
Kouzelná sušenka
63: 82: 53: 63
Hex
4
„Magické“ číslo, podle kterého vč. můžete určit, že tento paket patří do protokolu DHCP

možnosti DHCP. Může jít v libovolném pořadí

236
Číslo možnosti
53
prosince
3
Možnost 53, která definuje typ paketu DHCP 5 - DHCPACK

 
Délka varianty
1
prosince
1

 
Hodnota opce
5
prosince
1

 
Číslo možnosti
1
prosince
1
Možnost nabídnout klientovi DHCP masku sítě

 
Délka varianty
4
prosince
1

 
Hodnota opce
255.255.224.0
Řetězec
4

 
Číslo možnosti
3
prosince
1
Možnost nabídnout klientovi DHCP výchozí bránu

 
Délka varianty
4
prosince
1

 
Hodnota opce
172.16.12.1
Řetězec
4

 
Číslo možnosti
6
prosince
1
Možnost nabídnout DHCP klientovi DNS

 
Délka varianty
4
prosince
1

 
Hodnota opce
8.8.8.8
Řetězec
4

 
Číslo možnosti
51
prosince
1
Životnost vydaných síťových parametrů v sekundách, po jejichž uplynutí si je musí klient DHCP znovu vyžádat

 
Délka varianty
4
prosince
1

 
Hodnota opce
86400
prosince
4

 
Číslo možnosti
82
prosince
1
Možnost 82, opakuje to, co přišlo v DHCPDISCOVER

 
Délka varianty
18
prosince
1

 
Hodnota opce
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
prosince
18

 
Konec balení
255
prosince
1
255 symbolizuje konec paketu

Instalace

Instalace ve skutečnosti spočívá v instalaci pythonových modulů nezbytných pro práci. Předpokládá se, že MySQL je již nainstalován a nakonfigurován.

FreeBSD

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

ubuntu

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

Vytvoříme databázi MySQL, nahrajeme do ní výpis pydhcp.sql a nakonfigurujeme konfigurační soubor.

Konfigurace

Všechna nastavení serveru jsou v souboru xml. Referenční soubor:

1.0 0.0.0.0 255.255.255.255 192.168.0.71 8600 1 255.255.255.0 192.168.0.1 localhost 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 vyberte ip,mask,router,dns od uživatelů, kde horní(mac)=upper('{option_3_AgentRemoteId_hex}') a horní(port)=upper('{option_1_AgentCircuitId_port_hex}') vyberte ip,mask,router,dns od uživatelů, kde horní(mac)=upper('{sw_mac}') a horní(port)=upper('{sw_port82}') vyberte ip,mask,router,dns od uživatelů, kde horní(mac)=upper('{ClientMacAddress}') vložit do historie (id,dt,mac,ip,comment) hodnoty ​​(null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')

Nyní podrobněji o značkách:

Sekce dhcpserver popisuje základní nastavení pro spuštění serveru, konkrétně:

  • hostitel - jakou IP adresu server naslouchá na portu 67
  • broadcast - která IP je vysílání pro DHCPOFFER a DHCPACK
  • DHCPServer – jaká je ip DHCP serveru
  • LeaseTime doba zapůjčení vydané IP adresy
  • ThreadLimit - kolik vláken běží současně pro zpracování příchozích UDP paketů na portu 67. Má to pomoci na vysoce vytížených projektech 😉
  • defaultMask,defaultRouter,defaultDNS - co je standardně nabízeno účastníkovi, pokud je v databázi nalezena IP, ale nejsou pro ni specifikovány další parametry

sekce mysql:

hostitel, uživatelské jméno, heslo, základní jméno - vše mluví samo za sebe. Přibližná struktura databáze je zveřejněna na GitHub

Sekce dotazu: požadavky na přijetí NABÍDKY/ACK jsou popsány zde:

  • offer_count — počet řádků s požadavky, které vracejí výsledek jako ip,mask,router,dns
  • offer_n — řetězec dotazu. Pokud je return prázdný, provede se následující žádost o nabídku
  • history_sql - dotaz, který zapisuje například do „historie autorizací“ pro předplatitele

Požadavky mohou obsahovat libovolné proměnné ze sekce voleb nebo volby z protokolu DHCP.

Sekce Možnosti. Tady to začíná být zajímavější. Zde můžeme vytvořit proměnné, které můžeme později použít v sekci dotazů.

Například:

option_82_hex:sw_port1:20:22

, tento příkazový řádek převezme celý řádek, který přišel s volbou požadavku DHCP 82, v hexadecimálním formátu, v rozsahu od 20 do 22 bajtů včetně, a vloží jej do nové proměnné sw_port1 (přepnout port, odkud požadavek přišel)

option_82_hex:sw_mac:26:40

, definujte proměnnou sw_mac, přičemž hex z rozsahu 26:40

Všechny možné volby, které lze v dotazech použít, můžete zobrazit spuštěním serveru pomocí přepínače -d. Uvidíme něco jako tento log:

--a DHCPINFORM paket dorazil na port 67, z 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress': '0025224'Client': '764'Client' 00%"Jxd7d' , ' HType': 'Ethernet', 'HostName': b'x91xa5xe0xa3xa5xa9-x8fx8a', 'ReqListDNS': True, 'ReqListDomainName': True, 'ReqReqListPerfowmRouter,Rist'ReqListPerfowmRouter,Rist'ReqListPerfowmRouter,Ris' Trasa': Pravda, 'ReqListSubnetM ask': True, 'ReqListVendorSpecInfo': 43, 'RequestedIpAddress': '0.0.0.0', 'Vendor': b'MSFT 5.0', 'chaddr': '0025224ad764', 172.30.128.13.'00.'00.'172.30.114.25. , 'flags': b'x308x6', 'giaddr': '1', 'gpoz': 82, 'hlen': 12, 'hops': 12, 'htype': 'MAC', 'magic_cookie': b'cx53Sc ', 'op': 'DHCPINFORM', 'option53': 55, 'option55': 60, 'option60': 61, 'option61': 82, 'option82': 82, 'option12': 01, option_06_byte': b'x00x04x00x01x00x06x02x08x00x06x00x1' b'x9x2x82eXx12010600040001000602080006001exb589xad', 'option_2_82_hex': '18 option_82_len': 12 01, 'option_06_str': "b'x00x04x00x01x00x06x02x08x00x06x00x1x9x2x768eXx0.0.0.0exb001xad'", 'výsledek': False: '589s, 's' 'siaddr': '2', 'sw_mac': '1e06eb89ad', 'sw_port8': '3', 'xidbyte': b'

Podle toho můžeme zabalit libovolnou proměnnou do {} a ta bude použita v SQL dotazu.

Zaznamenejme do historie, že klient obdržel IP adresu:

DHCP+Mysql server v Pythonu

DHCP+Mysql server v Pythonu

Spuštění serveru

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

— d režim výstupu konzoly DEBUG
- c konfigurační soubor <název_souboru>

Debriefing

A nyní více podrobností o implementaci serveru v Pythonu. Je to bolest. Python se učil za chodu. Mnoho momentů je natočeno ve stylu „wow, nějak se mi to povedlo“. Neoptimalizováno vůbec a ponecháno v této podobě hlavně kvůli malým zkušenostem s vývojem Pythonu. Zastavím se u nejzajímavějších aspektů implementace serveru v „kódu“.

Parser konfiguračního souboru XML

Je použit standardní Python modul xml.dom. Zdá se to jednoduché, ale během implementace byl znatelný nedostatek přehledné dokumentace a příkladů na síti využívající tento modul.

    tree = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") pro prvek v 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_name] =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") pro prvek v 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.datagsk_config["d =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig["dhcp(dhcp(DNS"]=Naget(DNS) defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("query") pro prvek v qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[0].firstChild.data pro 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") pro prvek v možnostech: node=elem.getElementsByTagName("option") pro možnosti v uzlu : optionsMod.append(options.firstChild.data)

Vícevláknové zpracování

Kupodivu je multithreading v Pythonu implementován velmi jasně a jednoduše.

def PacketWork(data,addr): ... # implementace analýzy příchozího paketu a reakce na něj ... zatímco True: data, addr = udp_socket.recvfrom(1024) # čekání na vlákno paketu UDP = threading.Thread( target=PacketWork , args=(data,addr,)).start() # jak to přišlo - spustíme dříve definovanou funkci PacketWork na pozadí s parametry při threading.active_count() >gconfig["dhcp_ThreadLimit"]: čas. sleep(1) # if number Již běží více vláken než v nastavení, počkáme, až jich bude méně

Přijmout/odeslat paket DHCP

Abyste mohli zachytit UDP pakety přicházející přes síťovou kartu, musíte „zvednout“ soket:

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

, kde jsou vlajky:

  • AF_INET - znamená, že formát adresy bude IP: port. Může také existovat AF_UNIX - kde je adresa dána názvem souboru.
  • SOCK_DGRAM - znamená, že nepřijímáme „raw paket“, ale ten, který již prošel firewallem a s částečně oříznutým paketem. Tito. přijímáme pouze paket UDP bez „fyzické“ složky obalu paketů UDP. Pokud použijete příznak SOCK_RAW, budete také muset analyzovat tento „wrapper“.

Odeslání paketu může být jako vysílání:

                    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #přepněte soket do režimu vysílání rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))

a na adresu „odkud balíček přišel“:

                        udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # přepnout socket do režimu více posluchačů rz=udp_socket.sendto(packetack, addr)

, kde SOL_SOCKET znamená „úroveň protokolu“ pro možnosti nastavení,

, možnost SO_BROADCAST, že balíček helmy je „vysílán“

  ,Volba SO_REUSEADDR přepne zásuvku do režimu „mnoho posluchačů“. Teoreticky je to v tomto případě zbytečné, ale na jednom ze serverů FreeBSD, na kterém jsem testoval, kód bez této možnosti nefungoval.

Analýza paketu DHCP

Tady se mi Python opravdu líbil. Ukazuje se, že po vybalení vám umožňuje být s bajtkódem docela flexibilní. Umožňuje to velmi snadno převést na desítkové hodnoty, řetězce a hex - tzn. to je to, co vlastně potřebujeme, abychom pochopili strukturu balíčku. Takže například můžete získat rozsah bajtů v HEX a pouze bajty:

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

, zabalte bajty do struktury:

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

Získejte IP ze struktury:

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

A naopak:

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

To je zatím vše 😉

Zdroj: www.habr.com

Přidat komentář