DHCP+Mysql-server i Python

DHCP+Mysql-server i Python

Syftet med detta projekt var:

  • Lär dig om DHCP i ett IPv4-nätverk
  • Att lära sig Python (lite mer än från början 😉)
  • serverbyte DB2DHCP (min gaffel), original här, som blir svårare och svårare att montera för det nya operativsystemet. Och jag gillar inte att det är binärt att det inte finns något sätt att "ändra just nu"
  • skaffa en fungerande DHCP-server med möjlighet att välja en abonnents IP-adress med hjälp av abonnentens mac eller byta mac+port-kombination (alternativ 82)
  • skriva en annan cykel (Åh! det här är min favoritaktivitet)
  • få kommentarer om din klubbhändelse på Habrahabr (eller ännu bättre, en inbjudan) 😉

Resultat: det fungerar 😉 Testat på FreeBSD och Ubuntu OS. Teoretiskt kan koden uppmanas att fungera under vilket operativsystem som helst, eftersom Det verkar inte finnas några specifika bindningar i koden.
Försiktigt! Det kommer mycket mer.

Länk till arkiv för amatörer "beröra vid liv".

Processen att installera, konfigurera och använda resultatet av att "studera hårdvaran" är mycket lägre, och sedan lite teori om DHCP-protokollet. För mig själv. Och för historien 😉

Lite teori

Vad är DHCP

Detta är ett nätverksprotokoll som gör att en enhet kan ta reda på sin IP-adress (och andra parametrar som gateway, DNS, etc.) från en DHCP-server. Paket utbyts med UDP-protokollet. Den allmänna principen för enhetens drift när du begär nätverksparametrar är som följer:

  1. Enheten (klienten) skickar en UDP-sändningsbegäran (DHCPDISCOVER) i hela nätverket med begäran "ja, någon ger mig en IP-adress." Dessutom sker vanligtvis (men inte alltid) begäran från port 68 (källa), och destinationen är port 67 (destination). Vissa enheter skickar även paket från port 67. MAC-adressen för klientenheten ingår i DHCPDISCOVER-paketet.
  2. Alla DHCP-servrar som finns på nätverket (och det kan finnas flera av dem) bildar ett DHCPOFFER-erbjudande med nätverksinställningar för enheten som skickade DHCPDISCOVER, och sänder även det över nätverket. Identifiering av vem detta paket är avsett för baseras på MAC-adressen för klienten som angavs tidigare i DHCPDISCOVER-begäran.
  3. Klienten accepterar paket med förslag på nätverksinställningar, väljer den mest attraktiva (kriterierna kan vara olika, till exempel tidpunkten för paketleverans, antalet mellanvägar) och gör en "officiell begäran" DHCPREQUEST med nätverksinställningarna från DHCP-servern den gillar. I det här fallet går paketet till en specifik DHCP-server.
  4. Servern som tog emot DHCPREQUEST skickar ett paket i DHCPACK-format, där den återigen listar nätverksinställningarna avsedda för denna klient

DHCP+Mysql-server i Python

Dessutom finns det DHCPINFORM-paket som kommer från klienten, och syftet med dessa är att informera DHCP-servern om att "klienten är vid liv" och använder de utfärdade nätverksinställningarna. I den här serverns implementering ignoreras dessa paket.

Paketformat

I allmänhet ser en Ethernet-paketram ut ungefär så här:

DHCP+Mysql-server i Python

I vårt fall kommer vi endast att överväga data direkt från innehållet i UDP-paketet, utan OSI-lagerprotokollhuvuden, nämligen DHCP-strukturen:

DHCPUPPTÄCK

Så processen att erhålla en IP-adress för en enhet börjar med att DHCP-klienten skickar en sändningsförfrågan från port 68 till 255.255.255.255:67. I detta paket inkluderar klienten sin MAC-adress, samt vad den exakt vill ta emot från DHCP-servern. Paketstrukturen beskrivs i tabellen nedan.

DHCPDISCOVER Paketstrukturtabell

Position i förpackningen
Värdenamn
Exempel
idé
bitgrupp
klargörande

1
Startbegäran
1
Hex
1
Meddelandetyp. 1 - begäran från klient till server, 2 - svar från server till klient

2
Hårdvarutyp
1
Hex
1
Typ av hårdvaruadress, i detta protokoll 1 - MAC

3
Hårdvaruadressers längd
6
Hex
1
Enhetens MAC-adress längd

4
Humle
1
Hex
1
Antal mellanvägar

5
Transaktions ID
23:cf:de:1d
Hex
4
Unik transaktionsidentifierare. Genereras av klienten i början av en begäran

7
Andra förflutit
0
Hex
4
Tid i sekunder från början av processen att erhålla en adress

9
Boot flaggor
0
Hex
2
Vissa flaggor som kan ställas in för att indikera protokollparametrar

11
Klientens IP-adress
0.0.0.0
Linje
4
Klientens IP-adress (om någon)

15
Din klients IP-adress
0.0.0.0
Linje
4
IP-adress som erbjuds av servern (om tillgänglig)

19
Nästa server IP-adress
0.0.0.0
Linje
4
Serverns IP-adress (om känd)

23
Reläagentens IP-adress
172.16.114.41
Linje
4
IP-adress för reläagenten (till exempel en switch)

27
Klientens MAC-adress
14:d6:4d:a7:c9:55
Hex
6
MAC-adress för paketavsändaren (klienten)

31
Adressutfyllnad för klienthårdvara
 
Hex
10
Reserverat säte. Vanligtvis fylld med nollor

41
Serverns värdnamn
 
Linje
64
DHCP-servernamn. Överförs vanligtvis inte

105
Startfilens namn
 
Linje
128
Filnamn på servern som används av disklösa stationer vid uppstart

235
Magisk kaka
63: 82: 53: 63
Hex
4
"Magiskt" nummer, enligt vilket, inkl. du kan fastställa att detta paket tillhör DHCP-protokollet

DHCP-alternativ. Kan gå i vilken ordning som helst

236
Alternativnummer
53
december
1
Alternativ 53, som specificerar DHCP-pakettypen

1 - DHCPUPPTÄCK
3 - DHCPREQUEST
2 - DHCPERBJUDANDE
5 - DHCPACK
8 - DHCPINFORM

 
Alternativ längd
1
december
1

 
Optionsvärde
1
december
1

 
Alternativnummer
50
december
1
Vilken IP-adress vill klienten få?

 
Alternativ längd
4
december
1

 
Optionsvärde
172.16.134.61
Linje
4

 
Alternativnummer
55
 
1
Nätverksparametrar som begärs av klienten. Sammansättningen kan variera

01 — Nätverksmask
03 - Gateway
06 - DNS
oc — Värdnamn
0f - nätverksdomännamn
1c - adress för sändningsbegäran (sändning)
42 - TFTP-servernamn
79 - Klasslös statisk väg

 
Alternativ längd
8
 
1

 
Optionsvärde
01:03:06:0c:0f:1c:42:79
 
8

 
Alternativnummer
82
december
 
Alternativ 82, som sänder MAC-adressen för repeaterenheten och några ytterligare värden.

Oftast är detta porten för switchen som slut-DHCP-klienten körs på. Det här alternativet innehåller ytterligare parametrar. Den första byten är numret på "underalternativet", den andra är dess längd, sedan dess värde.

I det här fallet, i alternativ 82, är underalternativen kapslade:
Agentkrets-ID = 00:04:00:01:00:04, där de två sista byten är DHCP-klientporten från vilken begäran kom

Agent Remote ID = 00:06:c8:be:19:93:11:48 - MAC-adress för DHCP-repeaterenheten

 
Alternativ längd
18
december
 

 
Optionsvärde
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Hex
 

 
Slutet på paketet
255
december
1
255 symboliserar slutet på paketet

DHCPERBJUDANDE

Så snart servern tar emot DHCPDISCOVER-paketet och om den ser att den kan erbjuda klienten något från den begärda, genererar den ett svar för det - DHCPDISCOVER. Svaret skickas till hamnen "där det kom ifrån", via sändning, eftersom för närvarande har klienten ännu ingen IP-adress, därför kan den bara acceptera paketet om det skickas via broadcast. Klienten känner igen att detta är ett paket för honom genom sin MAC-adress inuti paketet, såväl som transaktionsnumret som han genererar när det första paketet skapas.

DHCPOFFER Paketstrukturtabell

Position i förpackningen
Värdenamn (vanligt)
Exempel
idé
bitgrupp
klargörande

1
Startbegäran
1
Hex
1
Meddelandetyp. 1 - begäran från klient till server, 2 - svar från server till klient

2
Hårdvarutyp
1
Hex
1
Typ av hårdvaruadress, i detta protokoll 1 - MAC

3
Hårdvaruadressers längd
6
Hex
1
Enhetens MAC-adress längd

4
Humle
1
Hex
1
Antal mellanvägar

5
Transaktions ID
23:cf:de:1d
Hex
4
Unik transaktionsidentifierare. Genereras av klienten i början av en begäran

7
Andra förflutit
0
Hex
4
Tid i sekunder från början av processen att erhålla en adress

9
Boot flaggor
0
Hex
2
Vissa flaggor som kan ställas in för att indikera protokollparametrar. I det här fallet betyder 0 typen Unicast-begäran

11
Klientens IP-adress
0.0.0.0
Linje
4
Klientens IP-adress (om någon)

15
Din klients IP-adress
172.16.134.61
Linje
4
IP-adress som erbjuds av servern (om tillgänglig)

19
Nästa server IP-adress
0.0.0.0
Linje
4
Serverns IP-adress (om känd)

23
Reläagentens IP-adress
172.16.114.41
Linje
4
IP-adress för reläagenten (till exempel en switch)

27
Klientens MAC-adress
14:d6:4d:a7:c9:55
Hex
6
MAC-adress för paketavsändaren (klienten)

31
Adressutfyllnad för klienthårdvara
 
Hex
10
Reserverat säte. Vanligtvis fylld med nollor

41
Serverns värdnamn
 
Linje
64
DHCP-servernamn. Överförs vanligtvis inte

105
Startfilens namn
 
Linje
128
Filnamn på servern som används av disklösa stationer vid uppstart

235
Magisk kaka
63: 82: 53: 63
Hex
4
"Magiskt" nummer, enligt vilket, inkl. du kan fastställa att detta paket tillhör DHCP-protokollet

DHCP-alternativ. Kan gå i vilken ordning som helst

236
Alternativnummer
53
december
1
Alternativ 53, som definierar pakettypen DHCP 2 - DHCPOFFER

 
Alternativ längd
1
december
1

 
Optionsvärde
2
december
1

 
Alternativnummer
1
december
1
Möjlighet att erbjuda DHCP-klienten en nätverksmask

 
Alternativ längd
4
december
1

 
Optionsvärde
255.255.224.0
Linje
4

 
Alternativnummer
3
december
1
Möjlighet att erbjuda DHCP-klienten en standardgateway

 
Alternativ längd
4
december
1

 
Optionsvärde
172.16.12.1
Linje
4

 
Alternativnummer
6
december
1
Möjlighet att erbjuda DHCP till DNS-klient

 
Alternativ längd
4
december
1

 
Optionsvärde
8.8.8.8
Linje
4

 
Alternativnummer
51
december
1
Livslängden för de utfärdade nätverksparametrarna i sekunder, varefter DHCP-klienten måste begära dem igen

 
Alternativ längd
4
december
1

 
Optionsvärde
86400
december
4

 
Alternativnummer
82
december
1
Alternativ 82, upprepar det som kom i DHCPDISCOVER

 
Alternativ längd
18
december
1

 
Optionsvärde
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
december
18

 
Slutet på paketet
255
december
1
255 symboliserar slutet på paketet

DHC -FÖRFRÅGA

Efter att klienten tagit emot DHCPOFFER, bildar han ett paket som begär nätverksparametrar inte till alla DHCP-servrar i nätverket, utan bara till en specifik, vars DHCPOFFER-erbjudande han "gillade" mest. "Gilla"-kriterierna kan vara olika och beror på klientens DHCP-implementering. Mottagaren av begäran anges med MAC-adressen för DHCP-servern. Dessutom kan ett DHCPREQUEST-paket skickas av klienten utan att först generera DHCPDISCOVER, om serverns IP-adress redan har erhållits tidigare.

DHCPREQUEST Paketstrukturtabell

Position i förpackningen
Värdenamn (vanligt)
Exempel
idé
bitgrupp
klargörande

1
Startbegäran
1
Hex
1
Meddelandetyp. 1 - begäran från klient till server, 2 - svar från server till klient

2
Hårdvarutyp
1
Hex
1
Typ av hårdvaruadress, i detta protokoll 1 - MAC

3
Hårdvaruadressers längd
6
Hex
1
Enhetens MAC-adress längd

4
Humle
1
Hex
1
Antal mellanvägar

5
Transaktions ID
23:cf:de:1d
Hex
4
Unik transaktionsidentifierare. Genereras av klienten i början av en begäran

7
Andra förflutit
0
Hex
4
Tid i sekunder från början av processen att erhålla en adress

9
Boot flaggor
8000
Hex
2
Vissa flaggor som kan ställas in för att indikera protokollparametrar. I det här fallet är "sändning" inställd

11
Klientens IP-adress
0.0.0.0
Linje
4
Klientens IP-adress (om någon)

15
Din klients IP-adress
172.16.134.61
Linje
4
IP-adress som erbjuds av servern (om tillgänglig)

19
Nästa server IP-adress
0.0.0.0
Linje
4
Serverns IP-adress (om känd)

23
Reläagentens IP-adress
172.16.114.41
Linje
4
IP-adress för reläagenten (till exempel en switch)

27
Klientens MAC-adress
14:d6:4d:a7:c9:55
Hex
6
MAC-adress för paketavsändaren (klienten)

31
Adressutfyllnad för klienthårdvara
 
Hex
10
Reserverat säte. Vanligtvis fylld med nollor

41
Serverns värdnamn
 
Linje
64
DHCP-servernamn. Överförs vanligtvis inte

105
Startfilens namn
 
Linje
128
Filnamn på servern som används av disklösa stationer vid uppstart

235
Magisk kaka
63: 82: 53: 63
Hex
4
"Magiskt" nummer, enligt vilket, inkl. du kan fastställa att detta paket tillhör DHCP-protokollet

DHCP-alternativ. Kan gå i vilken ordning som helst

236
Alternativnummer
53
december
3
Alternativ 53, som definierar DHCP-pakettyp 3 - DHCPREQUEST

 
Alternativ längd
1
december
1

 
Optionsvärde
3
december
1

 
Alternativnummer
61
december
1
Klient-ID: 01 (för Ehernet) + klientens MAC-adress

 
Alternativ längd
7
december
1

 
Optionsvärde
01:2c:ab:25:ff:72:a6
Hex
7

 
Alternativnummer
60
december
 
"Leverantörsklassidentifierare". I mitt fall rapporterar den DHCP-klientversionen. Kanske returnerar andra enheter något annat. Windows rapporterar till exempel MSFT 5.0

 
Alternativ längd
11
december
 

 
Optionsvärde
udhcp 0.9.8
Linje
 

 
Alternativnummer
55
 
1
Nätverksparametrar som begärs av klienten. Sammansättningen kan variera

01 — Nätverksmask
03 - Gateway
06 - DNS
oc — Värdnamn
0f - nätverksdomännamn
1c - adress för sändningsbegäran (sändning)
42 - TFTP-servernamn
79 - Klasslös statisk väg

 
Alternativ längd
8
 
1

 
Optionsvärde
01:03:06:0c:0f:1c:42:79
 
8

 
Alternativnummer
82
december
1
Alternativ 82, upprepar det som kom i DHCPDISCOVER

 
Alternativ längd
18
december
1

 
Optionsvärde
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
december
18

 
Slutet på paketet
255
december
1
255 symboliserar slutet på paketet

DHCPACK

Som bekräftelse på att "ja, det stämmer, det här är din IP-adress, och jag kommer inte att ge ut den till någon annan" från DHCP-servern, serverar ett paket i DHCPACK-format från servern till klienten. Det skickas som broadcast precis som andra paket. Även om jag i koden nedan för en DHCP-server implementerad i Python, för säkerhets skull, duplicerar en sändningsförfrågan genom att skicka ett paket till en specifik klient-IP, om den redan är känd. Dessutom bryr sig DHCP-servern inte alls om DHCPACK-paketet har nått klienten. Om klienten inte tar emot DHCPACK, upprepar den efter ett tag helt enkelt DHCPREQUEST

DHCPACK-paketstrukturtabell

Position i förpackningen
Värdenamn (vanligt)
Exempel
idé
bitgrupp
klargörande

1
Startbegäran
2
Hex
1
Meddelandetyp. 1 - begäran från klient till server, 2 - svar från server till klient

2
Hårdvarutyp
1
Hex
1
Typ av hårdvaruadress, i detta protokoll 1 - MAC

3
Hårdvaruadressers längd
6
Hex
1
Enhetens MAC-adress längd

4
Humle
1
Hex
1
Antal mellanvägar

5
Transaktions ID
23:cf:de:1d
Hex
4
Unik transaktionsidentifierare. Genereras av klienten i början av en begäran

7
Andra förflutit
0
Hex
4
Tid i sekunder från början av processen att erhålla en adress

9
Boot flaggor
8000
Hex
2
Vissa flaggor som kan ställas in för att indikera protokollparametrar. I det här fallet är "sändning" inställd

11
Klientens IP-adress
0.0.0.0
Linje
4
Klientens IP-adress (om någon)

15
Din klients IP-adress
172.16.134.61
Linje
4
IP-adress som erbjuds av servern (om tillgänglig)

19
Nästa server IP-adress
0.0.0.0
Linje
4
Serverns IP-adress (om känd)

23
Reläagentens IP-adress
172.16.114.41
Linje
4
IP-adress för reläagenten (till exempel en switch)

27
Klientens MAC-adress
14:d6:4d:a7:c9:55
Hex
6
MAC-adress för paketavsändaren (klienten)

31
Adressutfyllnad för klienthårdvara
 
Hex
10
Reserverat säte. Vanligtvis fylld med nollor

41
Serverns värdnamn
 
Linje
64
DHCP-servernamn. Överförs vanligtvis inte

105
Startfilens namn
 
Linje
128
Filnamn på servern som används av disklösa stationer vid uppstart

235
Magisk kaka
63: 82: 53: 63
Hex
4
"Magiskt" nummer, enligt vilket, inkl. du kan fastställa att detta paket tillhör DHCP-protokollet

DHCP-alternativ. Kan gå i vilken ordning som helst

236
Alternativnummer
53
december
3
Alternativ 53, som definierar DHCP-pakettyp 5 - DHCPACK

 
Alternativ längd
1
december
1

 
Optionsvärde
5
december
1

 
Alternativnummer
1
december
1
Möjlighet att erbjuda DHCP-klienten en nätverksmask

 
Alternativ längd
4
december
1

 
Optionsvärde
255.255.224.0
Linje
4

 
Alternativnummer
3
december
1
Möjlighet att erbjuda DHCP-klienten en standardgateway

 
Alternativ längd
4
december
1

 
Optionsvärde
172.16.12.1
Linje
4

 
Alternativnummer
6
december
1
Möjlighet att erbjuda DHCP till DNS-klient

 
Alternativ längd
4
december
1

 
Optionsvärde
8.8.8.8
Linje
4

 
Alternativnummer
51
december
1
Livslängden för de utfärdade nätverksparametrarna i sekunder, varefter DHCP-klienten måste begära dem igen

 
Alternativ längd
4
december
1

 
Optionsvärde
86400
december
4

 
Alternativnummer
82
december
1
Alternativ 82, upprepar det som kom i DHCPDISCOVER

 
Alternativ längd
18
december
1

 
Optionsvärde
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
december
18

 
Slutet på paketet
255
december
1
255 symboliserar slutet på paketet

Installation

Installationen består egentligen av att installera de pythonmoduler som behövs för arbetet. Det antas att MySQL redan är installerat och konfigurerat.

FreeBSD

pkg installera python3 python3 -m surepip pip3 installera mysql-connector

ubuntu

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

Vi skapar en MySQL-databas, laddar upp pydhcp.sql-dumpen till den och konfigurerar konfigurationsfilen.

konfiguration

Alla serverinställningar finns i en xml-fil. Referensfil:

1.0 0.0.0.0 255.255.255.255 192.168.0.71 8600 1 255.255.255.0 192.168.0.1 lokal värd testa testa 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 välj ip,mask,router,dns från användare där upper(mac)=upper('{option_3_AgentRemoteId_hex}') och upper(port)=upper('{option_1_AgentCircuitId_port_hex}') välj ip,mask,router,dns från användare där upper(mac)=upper('{sw_mac}') och upper(port)=upper('{sw_port82}') välj ip,mask,router,dns från användare där upper(mac)=upper('{ClientMacAddress}') infoga värden i historik (id,dt,mac,ip,comment) (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')

Nu mer detaljerat om taggarna:

Avsnittet dhcpserver beskriver de grundläggande inställningarna för att starta servern, nämligen:

  • värd - vilken IP-adress servern lyssnar på på port 67
  • broadcast - vilken ip är sändningen för DHCPOFFER och DHCPACK
  • DHCPServer - vad är IP-adressen för DHCP-servern
  • LeaseTime leasingtid för den utfärdade IP-adressen
  • ThreadLimit - hur många trådar körs samtidigt för att bearbeta inkommande UDP-paket på port 67. Det är tänkt att hjälpa till i högbelastningsprojekt 😉
  • defaultMask,defaultRouter,defaultDNS - vad som erbjuds abonnenten som standard om en IP hittas i databasen, men ytterligare parametrar är inte specificerade för den

mysql avsnitt:

värd, användarnamn, lösenord, basnamn - allt talar för sig själv. En ungefärlig databasstruktur publiceras på GitHub

Frågeavsnitt: förfrågningar om att ta emot ERBJUDANDE/ACK beskrivs här:

  • offer_count — antalet rader med förfrågningar som returnerar ett resultat som ip,mask,router,dns
  • offer_n — frågesträng. Om returen är tom, utförs följande erbjudandeförfrågan
  • history_sql - en fråga som till exempel skriver till "auktoriseringshistoriken" för en prenumerant

Förfrågningar kan inkludera alla variabler från alternativsektionen eller alternativ från DHCP-protokollet.

Avsnittet Alternativ. Det är här det blir mer intressant. Här kan vi skapa variabler som vi kan använda senare i frågeavsnittet.

Till exempel:

option_82_hex:sw_port1:20:22

, tar denna kommandorad hela raden som kom i DHCP-begäran alternativ 82, i hex-format, i intervallet från 20 till 22 byte inklusive och placerar den i den nya variabeln sw_port1 (växelport där begäran kom)

option_82_hex:sw_mac:26:40

, definiera variabeln sw_mac, ta hex från intervallet 26:40

Du kan se alla möjliga alternativ som kan användas i frågor genom att starta servern med -d-växeln. Vi kommer att se något sånt här:

--ett DHCPINFORM-paket anlände till port 67, från 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress': 'b'ClientMacAddress': '0025224teMac 764 00%"Jxd7d' , 'Htype': 'Ethernet', 'HostName': B'x91xa5xe0xa3xa5xa9-x8fx8a ',' reqlistdns ': True,' reqlistdomaName ': true,' reqlistperfowmrouerdiscover ' 'ReqListSubnetM ask ': True, 'ReqListVendorSpecInfo': 43, 'RequestedIpAddress': '0.0.0.0', 'Vendor': b'MSFT 5.0', 'chaddr': '0025224ad764', 'ciaddr'.172.30.128.13'.00'. , 'flags': b'x00x172.30.114.25', 'giaddr': '308', 'gpoz': 6, 'hlen': 1, 'hops': 82, 'htype': 'MAC', 'magic_cookie': b'cx12Sc ', 'op': 'DHCPINFORM', 'option12': 53, 'option53': 55, 'option55': 60, 'option60': 61, 'option61': 82, 'option82': 82, ' option_12_byte': b'x01x06x00x04x00x01x00x06x02x08x00x06' b'x00x1x9eXx2exb82xad', 'option_12010600040001000602080006001_hex': '589e2 _82_len': 18 82, 'option_12_str': "b'x01x06x00x04x00x01x00x06x02x08x00x06x00x1x9eXx2exb768xad'", 'result': False, 'secs': 0.0.0.0 'siaddr': '001', 'sw_mac': '589e2eb1ad', 'sw_port06': '89', 'xidbyte': b'

Följaktligen kan vi linda vilken variabel som helst i {} och den kommer att användas i SQL-frågan.

Låt oss registrera för historik att klienten fick IP-adressen:

DHCP+Mysql-server i Python

DHCP+Mysql-server i Python

Startar servern

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

— d konsolutgångsläge DEBUG
- c <filnamn> konfigurationsfil

Briefing

Och nu mer information om implementering av servern i Python. Det är en smärta. Python lärdes in i farten. Många ögonblick är gjorda i stil med "wow, på något sätt fick jag det att fungera." Inte optimerad alls, och kvar i denna form främst på grund av liten erfarenhet av Python-utveckling. Jag kommer att uppehålla mig vid de mest intressanta aspekterna av serverimplementeringen i "kod".

XML konfigurationsfil parser

Standard Python-modulen xml.dom används. Det verkar enkelt, men under implementeringen var det en märkbar brist på tydlig dokumentation och exempel på nätverket med denna modul.

    tree = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") för elem i mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("host")[0].firstChild. gconfig["mysql_username"]=elem.getElementsByTagName("användarnamn")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("lösenord")[0].firstChild.data gconfig_basenamesq] =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") för elem i 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"]defaultMacsk"default =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig["dhcp_defaultDgetElement"]=seBlemyTagElement defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("query") för elem i qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[0].firstChild.data för 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") för elem i optioner: node=elem.getElementsByTagName("option") för alternativ i nod : optionsMod.append(options.firstChild.data)

Multithreading

Märkligt nog är multithreading i Python implementerat väldigt tydligt och enkelt.

def PacketWork(data,addr): ... # implementering av att analysera det inkommande paketet och svara på det ... medan True: data, addr = udp_socket.recvfrom(1024) # väntar på UDP-pakettråden = threading.Thread( target=PacketWork , args=(data,addr,)).start() # som det kom - vi startar den tidigare definierade PacketWork-funktionen i bakgrunden med parametrar medan threading.active_count() >gconfig["dhcp_ThreadLimit"]: tid. sleep(1) # om numret Det finns fler trådar som redan körs än i inställningarna, vi väntar tills det finns färre av dem

Ta emot/skicka DHCP-paket

För att fånga upp UDP-paket som kommer genom nätverkskortet måste du "höja" uttaget:

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

, där flaggorna är:

  • AF_INET - betyder att adressformatet kommer att vara IP: port. Det kan också finnas AF_UNIX - där adressen ges av filnamnet.
  • SOCK_DGRAM - betyder att vi inte accepterar ett "råpaket", utan ett som redan har passerat genom brandväggen och med ett delvis trimmat paket. De där. vi tar bara emot ett UDP-paket utan den "fysiska" komponenten i UDP-paketomslaget. Om du använder SOCK_RAW-flaggan måste du också analysera denna "wrapper".

Att skicka ett paket kan vara som en sändning:

                    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #växla socket till broadcast-läge rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))

, och till adressen "varifrån paketet kom":

                        udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # byt uttaget till multilyssnarläge rz=udp_socket.sendto(packetack, addr)

, där SOL_SOCKET betyder "protokollnivån" för inställningsalternativ,

, SO_BROADCAST alternativ att hjälmpaketet är "broadcast"

  ,SO_REUSEADDR-alternativet växlar uttaget till "många lyssnare"-läge. I teorin är det onödigt i det här fallet, men på en av FreeBSD-servrarna som jag testade på fungerade inte koden utan detta alternativ.

Parsar ett DHCP-paket

Det var här jag verkligen gillade Python. Det visar sig att ur lådan låter det dig vara ganska flexibel med bytekoden. Låter det mycket enkelt översättas till decimalvärden, strängar och hex - d.v.s. detta är vad vi faktiskt behöver för att förstå paketets struktur. Så, till exempel, kan du få en rad byte i HEX och bara byte:

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

, packa byten i en struktur:

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

Få IP från struktur:

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

Och vice versa:

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

Det var allt för nu 😉

Källa: will.com

Lägg en kommentar