DHCP+Mysql-server i Python

DHCP+Mysql-server i Python

Formålet med dette projekt var:

  • Lær om DHCP på et IPv4-netværk
  • At lære Python (lidt mere end fra bunden 😉)
  • server udskiftning DB2DHCP (min gaffel), original her, som bliver sværere og sværere at samle til det nye OS. Og jeg kan ikke lide, at det er binært, at der ikke er nogen måde at "ændre lige nu"
  • opnåelse af en fungerende DHCP-server med mulighed for at vælge en abonnents IP-adresse ved hjælp af abonnentens mac eller switch mac+port kombination (mulighed 82)
  • skrive en anden cykel (Åh! dette er min yndlingsaktivitet)
  • modtagelse af kommentarer om din klubhånd på Habrahabr (eller endnu bedre, en invitation) 😉

Resultat: det virker 😉 Testet på FreeBSD og Ubuntu OS. Teoretisk set kan koden blive bedt om at virke under ethvert OS, fordi Der synes ikke at være nogen specifikke bindinger i koden.
Forsigtigt! Der er meget mere i vente.

Link til repository for amatører "røre i live".

Processen med at installere, konfigurere og bruge resultatet af "at studere hardwaren" er meget lavere, og så lidt teori om DHCP-protokollen. For mig selv. Og for historien 😉

Lidt teori

Hvad er DHCP

Dette er en netværksprotokol, der gør det muligt for en enhed at finde ud af sin IP-adresse (og andre parametre som gateway, DNS osv.) fra en DHCP-server. Pakker udveksles ved hjælp af UDP-protokollen. Det generelle princip for drift af enheden, når der anmodes om netværksparametre, er som følger:

  1. Enheden (klienten) sender en UDP-udsendelsesanmodning (DHCPDISCOVER) gennem netværket med anmodningen "nå, nogen giver mig en IP-adresse." Desuden sker anmodningen normalt (men ikke altid) fra port 68 (kilde), og destinationen er port 67 (destination). Nogle enheder sender også pakker fra port 67. MAC-adressen på klientenheden er inkluderet i DHCPDISCOVER-pakken.
  2. Alle DHCP-servere placeret på netværket (og der kan være flere af dem) danner et DHCPOFFER-tilbud med netværksindstillinger for den enhed, der sendte DHCPDISCOVER, og udsender det også over netværket. Identifikation af, hvem denne pakke er beregnet til, er baseret på MAC-adressen på klienten, der er angivet tidligere i DHCPDISCOVER-anmodningen.
  3. Klienten accepterer pakker med forslag til netværksindstillinger, vælger den mest attraktive (kriterierne kan være forskellige, f.eks. tidspunktet for pakkelevering, antallet af mellemveje), og laver en "officiel anmodning" DHCPREQUEST med netværksindstillingerne fra den DHCP-server, den kan lide. I dette tilfælde går pakken til en specifik DHCP-server.
  4. Serveren, der modtog DHCPREQUEST, sender en pakke i DHCPACK-format, hvori den igen viser netværksindstillingerne beregnet til denne klient

DHCP+Mysql-server i Python

Derudover er der DHCPINFORM-pakker, der kommer fra klienten, og formålet med dem er at informere DHCP-serveren om, at "klienten er i live" og bruger de udstedte netværksindstillinger. I denne servers implementering ignoreres disse pakker.

Pakkeformat

Generelt ser en Ethernet-pakkeramme nogenlunde sådan ud:

DHCP+Mysql-server i Python

I vores tilfælde vil vi kun overveje dataene direkte fra indholdet af UDP-pakken, uden OSI-lagprotokolheadere, nemlig DHCP-strukturen:

DHCPOPDAG

Så processen med at opnå en IP-adresse til en enhed begynder med, at DHCP-klienten sender en udsendelsesanmodning fra port 68 til 255.255.255.255:67. I denne pakke inkluderer klienten sin MAC-adresse, samt hvad den præcis vil modtage fra DHCP-serveren. Pakkestrukturen er beskrevet i tabellen nedenfor.

DHCPDISCOVER Pakkestrukturtabel

Position i pakken
Værdinavn
Eksempel
idé
byte
Afklaring

1
Bootanmodning
1
Hex
1
Meddelelsestype. 1 - anmodning fra klient til server, 2 - svar fra server til klient

2
Hardware type
1
Hex
1
Type hardwareadresse, i denne protokol 1 - MAC

3
Hardwareadresselængde
6
Hex
1
Enhedens MAC-adresselængde

4
Humle
1
Hex
1
Antal mellemveje

5
Transaktions ID
23:cf:de:1d
Hex
4
Unik transaktions-id. Genereret af klienten i begyndelsen af ​​en anmodningsoperation

7
Andet forløbet
0
Hex
4
Tid i sekunder fra begyndelsen af ​​processen med at opnå en adresse

9
Støvleflag
0
Hex
2
Visse flag, der kan indstilles til at angive protokolparametre

11
Klientens IP-adresse
0.0.0.0
Line
4
Klientens IP-adresse (hvis nogen)

15
Din klients IP-adresse
0.0.0.0
Line
4
IP-adresse, der tilbydes af serveren (hvis tilgængelig)

19
Næste server IP-adresse
0.0.0.0
Line
4
Server IP-adresse (hvis kendt)

23
Relæagentens IP-adresse
172.16.114.41
Line
4
IP-adressen på relæagenten (f.eks. en switch)

27
Klients MAC-adresse
14:d6:4d:a7:c9:55
Hex
6
MAC-adresse på pakkeafsender (klient)

31
Klienthardwareadresseudfyldning
 
Hex
10
Reserveret sæde. Normalt fyldt med nuller

41
Serverens værtsnavn
 
Line
64
DHCP-servernavn. Normalt ikke transmitteret

105
Navn på opstartsfil
 
Line
128
Filnavn på serveren, der bruges af diskløse stationer ved opstart

235
Magisk småkage
63: 82: 53: 63
Hex
4
“Magisk” nummer, hvorefter inkl. du kan bestemme, at denne pakke tilhører DHCP-protokollen

DHCP muligheder. Kan gå i enhver rækkefølge

236
Option nummer
53
december
1
Mulighed 53, som specificerer DHCP-pakketypen

1 - DHCPOPDAG
3 - DHCPREQUEST
2 - DHCP-TILBUD
5 - DHCPACK
8 - DHCPINFORM

 
Mulighedens længde
1
december
1

 
Option værdi
1
december
1

 
Option nummer
50
december
1
Hvilken IP-adresse ønsker klienten at modtage?

 
Mulighedens længde
4
december
1

 
Option værdi
172.16.134.61
Line
4

 
Option nummer
55
 
1
Netværksparametre anmodet af klienten. Sammensætningen kan variere

01 — Netværksmaske
03 - Gateway
06 - DNS
oc — Værtsnavn
0f - netværksdomænenavn
1c - adresse på udsendelsesanmodning (udsendelse)
42 - TFTP-servernavn
79 - Klasseløs statisk rute

 
Mulighedens længde
8
 
1

 
Option værdi
01:03:06:0c:0f:1c:42:79
 
8

 
Option nummer
82
december
 
Mulighed 82, som sender MAC-adressen for repeaterenheden og nogle yderligere værdier.

Oftest er dette porten på switchen, som slut-DHCP-klienten kører på. Denne mulighed indeholder yderligere parametre. Den første byte er nummeret på "underoptionen", den anden er dens længde, derefter dens værdi.

I dette tilfælde, i mulighed 82, er underindstillingerne indlejret:
Agentkredsløbs-id = 00:04:00:01:00:04, hvor de sidste to bytes er den DHCP-klientport, som anmodningen kom fra

Agent Remote ID = 00:06:c8:be:19:93:11:48 - MAC-adressen på DHCP-repeaterenheden

 
Mulighedens længde
18
december
 

 
Option værdi
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Hex
 

 
Slut på pakken
255
december
1
255 symboliserer slutningen af ​​pakken

DHCP TILBUD

Så snart serveren modtager DHCPDISCOVER-pakken, og hvis den ser, at den kan tilbyde klienten noget fra den anmodede, genererer den et svar for den - DHCPDISCOVER. Svaret sendes til havnen "hvorfra det kom", ved udsendelse, pga på nuværende tidspunkt har klienten endnu ikke en IP-adresse, derfor kan den kun acceptere pakken, hvis den sendes via broadcast. Klienten genkender, at dette er en pakke til ham ved hans MAC-adresse inde i pakken, samt transaktionsnummeret, som han genererer på det tidspunkt, den første pakke oprettes.

DHCPOFFER Pakkestrukturtabel

Position i pakken
Navn på værdi (fælles)
Eksempel
idé
byte
Afklaring

1
Bootanmodning
1
Hex
1
Meddelelsestype. 1 - anmodning fra klient til server, 2 - svar fra server til klient

2
Hardware type
1
Hex
1
Type hardwareadresse, i denne protokol 1 - MAC

3
Hardwareadresselængde
6
Hex
1
Enhedens MAC-adresselængde

4
Humle
1
Hex
1
Antal mellemveje

5
Transaktions ID
23:cf:de:1d
Hex
4
Unik transaktions-id. Genereret af klienten i begyndelsen af ​​en anmodningsoperation

7
Andet forløbet
0
Hex
4
Tid i sekunder fra begyndelsen af ​​processen med at opnå en adresse

9
Støvleflag
0
Hex
2
Visse flag, der kan indstilles til at angive protokolparametre. I dette tilfælde betyder 0 Unicast-anmodningstypen

11
Klientens IP-adresse
0.0.0.0
Line
4
Klientens IP-adresse (hvis nogen)

15
Din klients IP-adresse
172.16.134.61
Line
4
IP-adresse, der tilbydes af serveren (hvis tilgængelig)

19
Næste server IP-adresse
0.0.0.0
Line
4
Server IP-adresse (hvis kendt)

23
Relæagentens IP-adresse
172.16.114.41
Line
4
IP-adressen på relæagenten (f.eks. en switch)

27
Klients MAC-adresse
14:d6:4d:a7:c9:55
Hex
6
MAC-adresse på pakkeafsender (klient)

31
Klienthardwareadresseudfyldning
 
Hex
10
Reserveret sæde. Normalt fyldt med nuller

41
Serverens værtsnavn
 
Line
64
DHCP-servernavn. Normalt ikke transmitteret

105
Navn på opstartsfil
 
Line
128
Filnavn på serveren, der bruges af diskløse stationer ved opstart

235
Magisk småkage
63: 82: 53: 63
Hex
4
“Magisk” nummer, hvorefter inkl. du kan bestemme, at denne pakke tilhører DHCP-protokollen

DHCP muligheder. Kan gå i enhver rækkefølge

236
Option nummer
53
december
1
Mulighed 53, som definerer DHCP 2-pakketypen - DHCPOFFER

 
Mulighedens længde
1
december
1

 
Option værdi
2
december
1

 
Option nummer
1
december
1
Mulighed for at tilbyde DHCP-klienten en netværksmaske

 
Mulighedens længde
4
december
1

 
Option værdi
255.255.224.0
Line
4

 
Option nummer
3
december
1
Mulighed for at tilbyde DHCP-klienten en standardgateway

 
Mulighedens længde
4
december
1

 
Option værdi
172.16.12.1
Line
4

 
Option nummer
6
december
1
Mulighed for at tilbyde DHCP til DNS-klient

 
Mulighedens længde
4
december
1

 
Option værdi
8.8.8.8
Line
4

 
Option nummer
51
december
1
Levetiden for de udstedte netværksparametre i sekunder, hvorefter DHCP-klienten skal anmode om dem igen

 
Mulighedens længde
4
december
1

 
Option værdi
86400
december
4

 
Option nummer
82
december
1
Mulighed 82, gentager det, der kom i DHCPDISCOVER

 
Mulighedens længde
18
december
1

 
Option værdi
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
december
18

 
Slut på pakken
255
december
1
255 symboliserer slutningen af ​​pakken

DHC -FORESPØRGSEL

Efter at klienten har modtaget DHCPOFFER, danner han en pakke, der anmoder om netværksparametre, ikke til alle DHCP-servere på netværket, men kun til én specifik, hvis DHCPOFFER-tilbud han "kan lide" mest. Kriterierne for "synes godt om" kan være forskellige og afhænger af klientens DHCP-implementering. Modtageren af ​​anmodningen angives ved hjælp af DHCP-serverens MAC-adresse. Desuden kan en DHCPREQUEST-pakke sendes af klienten uden først at generere DHCPDISCOVER, hvis serverens IP-adresse allerede er opnået tidligere.

DHCPREQUEST Pakkestrukturtabel

Position i pakken
Navn på værdi (fælles)
Eksempel
idé
byte
Afklaring

1
Bootanmodning
1
Hex
1
Meddelelsestype. 1 - anmodning fra klient til server, 2 - svar fra server til klient

2
Hardware type
1
Hex
1
Type hardwareadresse, i denne protokol 1 - MAC

3
Hardwareadresselængde
6
Hex
1
Enhedens MAC-adresselængde

4
Humle
1
Hex
1
Antal mellemveje

5
Transaktions ID
23:cf:de:1d
Hex
4
Unik transaktions-id. Genereret af klienten i begyndelsen af ​​en anmodningsoperation

7
Andet forløbet
0
Hex
4
Tid i sekunder fra begyndelsen af ​​processen med at opnå en adresse

9
Støvleflag
8000
Hex
2
Visse flag, der kan indstilles til at angive protokolparametre. I dette tilfælde er "broadcast" indstillet

11
Klientens IP-adresse
0.0.0.0
Line
4
Klientens IP-adresse (hvis nogen)

15
Din klients IP-adresse
172.16.134.61
Line
4
IP-adresse, der tilbydes af serveren (hvis tilgængelig)

19
Næste server IP-adresse
0.0.0.0
Line
4
Server IP-adresse (hvis kendt)

23
Relæagentens IP-adresse
172.16.114.41
Line
4
IP-adressen på relæagenten (f.eks. en switch)

27
Klients MAC-adresse
14:d6:4d:a7:c9:55
Hex
6
MAC-adresse på pakkeafsender (klient)

31
Klienthardwareadresseudfyldning
 
Hex
10
Reserveret sæde. Normalt fyldt med nuller

41
Serverens værtsnavn
 
Line
64
DHCP-servernavn. Normalt ikke transmitteret

105
Navn på opstartsfil
 
Line
128
Filnavn på serveren, der bruges af diskløse stationer ved opstart

235
Magisk småkage
63: 82: 53: 63
Hex
4
“Magisk” nummer, hvorefter inkl. du kan bestemme, at denne pakke tilhører DHCP-protokollen

DHCP muligheder. Kan gå i enhver rækkefølge

236
Option nummer
53
december
3
Mulighed 53, som definerer DHCP-pakketype 3 - DHCPREQUEST

 
Mulighedens længde
1
december
1

 
Option værdi
3
december
1

 
Option nummer
61
december
1
Klient-id: 01 (for Ehernet) + klient-MAC-adresse

 
Mulighedens længde
7
december
1

 
Option værdi
01:2c:ab:25:ff:72:a6
Hex
7

 
Option nummer
60
december
 
"Leverandør klasse identifikator". I mit tilfælde rapporterer den DHCP-klientversionen. Måske returnerer andre enheder noget andet. Windows rapporterer for eksempel MSFT 5.0

 
Mulighedens længde
11
december
 

 
Option værdi
udhcp 0.9.8
Line
 

 
Option nummer
55
 
1
Netværksparametre anmodet af klienten. Sammensætningen kan variere

01 — Netværksmaske
03 - Gateway
06 - DNS
oc — Værtsnavn
0f - netværksdomænenavn
1c - adresse på udsendelsesanmodning (udsendelse)
42 - TFTP-servernavn
79 - Klasseløs statisk rute

 
Mulighedens længde
8
 
1

 
Option værdi
01:03:06:0c:0f:1c:42:79
 
8

 
Option nummer
82
december
1
Mulighed 82, gentager det, der kom i DHCPDISCOVER

 
Mulighedens længde
18
december
1

 
Option værdi
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
december
18

 
Slut på pakken
255
december
1
255 symboliserer slutningen af ​​pakken

DHCPACK

Som bekræftelse på, at "ja, det er rigtigt, dette er din IP-adresse, og jeg vil ikke give den ud til nogen andre" fra DHCP-serveren, serverer en pakke i DHCPACK-format fra serveren til klienten. Det sendes broadcast ligesom andre pakker. Selvom jeg i koden nedenfor for en DHCP-server implementeret i Python, for en sikkerheds skyld, duplikerer enhver udsendelsesanmodning ved at sende en pakke til en specifik klient-IP, hvis den allerede er kendt. Desuden er DHCP-serveren overhovedet ligeglad med, om DHCPACK-pakken har nået klienten. Hvis klienten ikke modtager DHCPACK, gentager den efter et stykke tid blot DHCPREQUEST

DHCPACK-pakkestrukturtabel

Position i pakken
Navn på værdi (fælles)
Eksempel
idé
byte
Afklaring

1
Bootanmodning
2
Hex
1
Meddelelsestype. 1 - anmodning fra klient til server, 2 - svar fra server til klient

2
Hardware type
1
Hex
1
Type hardwareadresse, i denne protokol 1 - MAC

3
Hardwareadresselængde
6
Hex
1
Enhedens MAC-adresselængde

4
Humle
1
Hex
1
Antal mellemveje

5
Transaktions ID
23:cf:de:1d
Hex
4
Unik transaktions-id. Genereret af klienten i begyndelsen af ​​en anmodningsoperation

7
Andet forløbet
0
Hex
4
Tid i sekunder fra begyndelsen af ​​processen med at opnå en adresse

9
Støvleflag
8000
Hex
2
Visse flag, der kan indstilles til at angive protokolparametre. I dette tilfælde er "broadcast" indstillet

11
Klientens IP-adresse
0.0.0.0
Line
4
Klientens IP-adresse (hvis nogen)

15
Din klients IP-adresse
172.16.134.61
Line
4
IP-adresse, der tilbydes af serveren (hvis tilgængelig)

19
Næste server IP-adresse
0.0.0.0
Line
4
Server IP-adresse (hvis kendt)

23
Relæagentens IP-adresse
172.16.114.41
Line
4
IP-adressen på relæagenten (f.eks. en switch)

27
Klients MAC-adresse
14:d6:4d:a7:c9:55
Hex
6
MAC-adresse på pakkeafsender (klient)

31
Klienthardwareadresseudfyldning
 
Hex
10
Reserveret sæde. Normalt fyldt med nuller

41
Serverens værtsnavn
 
Line
64
DHCP-servernavn. Normalt ikke transmitteret

105
Navn på opstartsfil
 
Line
128
Filnavn på serveren, der bruges af diskløse stationer ved opstart

235
Magisk småkage
63: 82: 53: 63
Hex
4
“Magisk” nummer, hvorefter inkl. du kan bestemme, at denne pakke tilhører DHCP-protokollen

DHCP muligheder. Kan gå i enhver rækkefølge

236
Option nummer
53
december
3
Mulighed 53, som definerer DHCP-pakketype 5 - DHCPACK

 
Mulighedens længde
1
december
1

 
Option værdi
5
december
1

 
Option nummer
1
december
1
Mulighed for at tilbyde DHCP-klienten en netværksmaske

 
Mulighedens længde
4
december
1

 
Option værdi
255.255.224.0
Line
4

 
Option nummer
3
december
1
Mulighed for at tilbyde DHCP-klienten en standardgateway

 
Mulighedens længde
4
december
1

 
Option værdi
172.16.12.1
Line
4

 
Option nummer
6
december
1
Mulighed for at tilbyde DHCP til DNS-klient

 
Mulighedens længde
4
december
1

 
Option værdi
8.8.8.8
Line
4

 
Option nummer
51
december
1
Levetiden for de udstedte netværksparametre i sekunder, hvorefter DHCP-klienten skal anmode om dem igen

 
Mulighedens længde
4
december
1

 
Option værdi
86400
december
4

 
Option nummer
82
december
1
Mulighed 82, gentager det, der kom i DHCPDISCOVER

 
Mulighedens længde
18
december
1

 
Option værdi
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
december
18

 
Slut på pakken
255
december
1
255 symboliserer slutningen af ​​pakken

Installation

Installationen består faktisk i at installere de python-moduler, der er nødvendige for arbejdet. Det antages, at MySQL allerede er installeret og konfigureret.

FreeBSD

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

Ubuntu

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

Vi opretter en MySQL-database, uploader pydhcp.sql-dumpen til den og konfigurerer konfigurationsfilen.

Konfiguration

Alle serverindstillinger er i en xml-fil. Reference fil:

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ært prøve prøve 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ælg ip,mask,router,dns fra brugere, hvor upper(mac)=upper('{option_3_AgentRemoteId_hex}') og upper(port)=upper('{option_1_AgentCircuitId_port_hex}') vælg ip,maske,router,dns fra brugere, hvor upper(mac)=upper('{sw_mac}') og upper(port)=upper('{sw_port82}') vælg ip,maske,router,dns fra brugere, hvor upper(mac)=upper('{ClientMacAddress}') indsæt værdier i historik (id,dt,mac,ip,comment) (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')

Nu mere detaljeret om tags:

Afsnittet dhcpserver beskriver de grundlæggende indstillinger for at starte serveren, nemlig:

  • vært - hvilken IP-adresse serveren lytter til på port 67
  • broadcast - hvilken ip er udsendelsen for DHCPOFFER og DHCPACK
  • DHCPServer - hvad er ip'en på DHCP-serveren
  • LeaseTime lejetid for den udstedte IP-adresse
  • ThreadLimit - hvor mange tråde kører samtidigt for at behandle indgående UDP-pakker på port 67. Det formodes at hjælpe på højbelastningsprojekter 😉
  • defaultMask,defaultRouter,defaultDNS - hvad tilbydes abonnenten som standard, hvis der findes en IP i databasen, men der er ikke angivet yderligere parametre for den

mysql sektion:

vært, brugernavn, adgangskode, basenavn - alt taler for sig selv. En omtrentlig databasestruktur er udgivet på GitHub

Forespørgselssektion: anmodninger om modtagelse af TILBUD/ACK er beskrevet her:

  • offer_count — antallet af linjer med anmodninger, der returnerer et resultat som ip,mask,router,dns
  • offer_n — forespørgselsstreng. Hvis returneringen er tom, udføres følgende tilbudsanmodning
  • history_sql - en forespørgsel, der f.eks. skriver til "autorisationshistorikken" for en abonnent

Anmodninger kan omfatte alle variabler fra indstillingssektionen eller muligheder fra DHCP-protokollen.

Indstillinger sektion. Det er her, det bliver mere interessant. Her kan vi oprette variabler, som vi kan bruge senere i forespørgselsafsnittet.

For eksempel:

option_82_hex:sw_port1:20:22

, tager denne kommandolinje hele linjen, der kom i DHCP-anmodningsmulighed 82, i hex-format, i området fra 20 til 22 bytes inklusive og sætter den i den nye variabel sw_port1 (skift port, hvorfra anmodningen kom)

option_82_hex:sw_mac:26:40

, definere sw_mac-variablen ved at tage hex fra området 26:40

Du kan se alle de mulige muligheder, der kan bruges i forespørgsler ved at starte serveren med -d-switchen. Vi vil se noget som denne log:

--en DHCPINFORM-pakke ankom på port 67, fra 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress': 'B'ClientMacAddress': '0025224teMac': '764 00 7%"Jxd91d' , 'HType': 'Ethernet', 'HostName': B'x5xa0xe3xa5xa9xa8-x8fx43a ',' reqlistdns ': sandt,' reqlistdomaName ': sandt,' reqlistperfowmrouterdiscover ': true,' reqlistdomainname ': sandt,' reqliststaticroTatre ': sande, sand, sand, sand, sand, sand, sand, sand, sand, sand, sand, sand, sand, sand,': sande, sande, sande, sande, sande, sande, sande, sande, sande, sande, sande, sand, ' 'ReqListSubnetM ask ': True, 'ReqListVendorSpecInfo': 0.0.0.0, 'RequestedIpAddress': '5.0', 'Vendor': b'MSFT 0025224', 'chaddr': '764ad172.30.128.13', 'ciaddr'.00'.00'. , 'flags ': b'x172.30.114.25x308', 'giaddr': '6', 'gpoz': 1, 'hlen': 82, 'hops': 12, 'htype': 'MAC', 'magic_cookie': b'cx12Sc ', 'op': 'DHCPINFORM', 'option53': 53, 'option55': 55, 'option60': 60, 'option61': 61, 'option82': 82, 'option82': 12, ' option_01_byte': b'x06x00x04x00x01x00x06x02x08x00x06x00' b'x1x9x2eXx82exb12010600040001000602080006001xad', 'option_589_hex': '2e _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'

Derfor kan vi indpakke enhver variabel i {}, og den vil blive brugt i SQL-forespørgslen.

Lad os registrere for historik, at klienten modtog IP-adressen:

DHCP+Mysql-server i Python

DHCP+Mysql-server i Python

Server start

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

— d konsoludgangstilstand DEBUG
- c <filnavn> konfigurationsfil

debriefing

Og nu flere detaljer om implementering af serveren i Python. Det er en smerte. Python blev lært i farten. Mange øjeblikke er lavet i stil med "wow, på en eller anden måde fik jeg det til at fungere." Slet ikke optimeret og efterladt i denne form hovedsageligt på grund af ringe erfaring med Python-udvikling. Jeg vil dvæle ved de mest interessante aspekter af serverimplementeringen i "kode".

XML-konfigurationsfil-parser

Standard Python-modulet xml.dom bruges. Det virker simpelt, men under implementeringen var der en mærkbar mangel på klar dokumentation og eksempler på netværket ved hjælp af dette modul.

    tree = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") for elem i mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("host")[0].firstChild. gconfig["mysql_brugernavn"]=elem.getElementsByTagName("brugernavn")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("adgangskode")[0].firstChild.data gconfig_basenamesq]l =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") for 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"]defaultMacskp_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") for elem i 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 i optioner: node=elem.getElementsByTagName("option") for muligheder i node : optionsMod.append(options.firstChild.data)

Multithreading

Mærkeligt nok er multithreading i Python implementeret meget klart og enkelt.

def PacketWork(data,addr): ... # implementering af parsing af den indgående pakke og svar på den ... mens True: data, addr = udp_socket.recvfrom(1024) # venter på UDP-pakketråden = threading.Thread( target=PacketWork , args=(data,addr,)).start() # som det kom - vi starter den tidligere definerede PacketWork-funktion i baggrunden med parametre, mens threading.active_count() >gconfig["dhcp_ThreadLimit"]: tid. sleep(1) # if the number Der kører allerede flere tråde end i indstillingerne, vi venter til der er færre af dem

Modtag/send DHCP-pakke

For at opsnappe UDP-pakker, der kommer gennem netværkskortet, skal du "hæve" stikket:

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

, hvor flagene er:

  • AF_INET - betyder, at adresseformatet vil være IP: port. Der kan også være AF_UNIX - hvor adressen er givet af filnavnet.
  • SOCK_DGRAM - betyder, at vi ikke accepterer en "råpakke", men en, der allerede er passeret gennem firewallen, og med en delvist trimmet pakke. De der. vi modtager kun en UDP-pakke uden den "fysiske" komponent af UDP-pakkeindpakningen. Hvis du bruger SOCK_RAW-flaget, skal du også parse denne "wrapper".

At sende en pakke kan være som en udsendelse:

                    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #switch socket til broadcast-tilstand rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))

, og til adressen "hvor pakken kom fra":

                        udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # skift stikket til multilyttertilstand rz=udp_socket.sendto(packetack, addr)

, hvor SOL_SOCKET betyder "protokolniveauet" for indstillingsmuligheder,

, SO_BROADCAST mulighed, at hjelmpakken er "broadcast"

  ,SO_REUSEADDR-indstillingen skifter stikket til tilstanden "mange lyttere". I teorien er det unødvendigt i dette tilfælde, men på en af ​​de FreeBSD-servere, som jeg testede på, virkede koden ikke uden denne mulighed.

Parsing af en DHCP-pakke

Det var her, jeg virkelig godt kunne lide Python. Det viser sig, at ud af boksen giver det dig mulighed for at være ret fleksibel med bytekoden. Tillader det meget let at blive oversat til decimalværdier, strenge og hex - dvs. det er det, vi faktisk har brug for for at forstå pakkens struktur. Så for eksempel kan du få en række bytes i HEX og kun bytes:

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

, pak bytes ind i en struktur:

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

Hent IP fra struktur:

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

Og omvendt:

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

Det var alt for nu 😉

Kilde: www.habr.com

Tilføj en kommentar