DHCP+Mysql-server i Python

DHCP+Mysql-server i Python

Formålet med dette prosjektet var:

  • Lær om DHCP på et IPv4-nettverk
  • Lære Python (litt mer enn fra bunnen av 😉)
  • servererstatning DB2DHCP (min gaffel), original her, som blir mer og mer vanskelig å montere for det nye operativsystemet. Og jeg liker ikke at det er en binær måte at det ikke er mulig å "endre akkurat nå"
  • skaffe en fungerende DHCP-server med muligheten til å velge abonnentens IP-adresse ved å bruke abonnentens mac eller bytte mac+port-kombinasjon (alternativ 82)
  • skrive en annen sykkel (Å, dette er favorittaktiviteten min)
  • motta kommentarer om klubbhendelsen din på Habrahabr (eller enda bedre, en invitasjon) 😉

Resultat: det fungerer 😉 Testet på FreeBSD og Ubuntu OS. Teoretisk sett kan koden bli bedt om å fungere under et hvilket som helst operativsystem, fordi Det ser ikke ut til å være noen spesifikke bindinger i koden.
Forsiktig! Det er mye mer i vente.

Link til repository for amatører "berør levende".

Prosessen med å installere, konfigurere og bruke resultatet av å "studere maskinvaren" er mye lavere, og deretter litt teori om DHCP-protokollen. For meg selv. Og for historien 😉

Litt teori

Hva er DHCP

Dette er en nettverksprotokoll som lar en enhet finne ut sin IP-adresse (og andre parametere som gateway, DNS, etc.) fra en DHCP-server. Pakker utveksles ved hjelp av UDP-protokollen. Det generelle prinsippet for drift av enheten når du ber om nettverksparametere er som følger:

  1. Enheten (klienten) sender en UDP-kringkastingsforespørsel (DHCPDISCOVER) gjennom nettverket med forespørselen "vel, noen gir meg en IP-adresse." Dessuten skjer vanligvis (men ikke alltid) forespørselen fra port 68 (kilde), og destinasjonen er port 67 (destinasjon). Noen enheter sender også pakker fra port 67. MAC-adressen til klientenheten er inkludert i DHCPDISCOVER-pakken.
  2. Alle DHCP-servere som ligger på nettverket (og det kan være flere av dem) danner et DHCPOFFER-tilbud med nettverksinnstillinger for enheten som sendte DHCPDISCOVER, og kringkaster det også over nettverket. Identifikasjon av hvem denne pakken er ment for er basert på MAC-adressen til klienten som ble oppgitt tidligere i DHCPDISCOVER-forespørselen.
  3. Klienten godtar pakker med forslag til nettverksinnstillinger, velger den mest attraktive (kriteriene kan være forskjellige, for eksempel tidspunktet for pakkelevering, antall mellomliggende ruter), og gjør en "offisiell forespørsel" DHCPREQUEST med nettverksinnstillingene fra DHCP-serveren den liker. I dette tilfellet går pakken til en bestemt DHCP-server.
  4. Serveren som mottok DHCPREQUEST sender en DHCPACK-formatpakke, der den igjen viser nettverksinnstillingene beregnet for denne klienten

DHCP+Mysql-server i Python

I tillegg er det DHCPINFORM-pakker som kommer fra klienten, og formålet med disse er å informere DHCP-serveren om at "klienten er i live" og bruker de utstedte nettverksinnstillingene. I denne serverens implementering ignoreres disse pakkene.

Pakkeformat

Generelt ser en Ethernet-pakkeramme omtrent slik ut:

DHCP+Mysql-server i Python

I vårt tilfelle vil vi kun vurdere dataene direkte fra innholdet i UDP-pakken, uten OSI-lagprotokolloverskrifter, nemlig DHCP-strukturen:

DHCPOPPDATER

Så prosessen med å skaffe en IP-adresse for en enhet begynner med at DHCP-klienten sender en kringkastingsforespørsel fra port 68 til 255.255.255.255:67. I denne pakken inkluderer klienten sin MAC-adresse, samt hva den nøyaktig ønsker å motta fra DHCP-serveren. Pakkestrukturen er beskrevet i tabellen nedenfor.

DHCPDISCOVER Pakkestrukturtabell

Plassering i pakken
Verdinavn
Eksempel
Представление
byte
Avklaring

1
Oppstartsforespørsel
1
Hex
1
Meldingstype. 1 - forespørsel fra klient til server, 2 - svar fra server til klient

2
Maskinvaretype
1
Hex
1
Type maskinvareadresse, i denne protokollen 1 - MAC

3
Lengde på maskinvareadresser
6
Hex
1
Lengde på enhetens MAC-adresse

4
Humle
1
Hex
1
Antall mellomveier

5
Transaksjons-ID
23:cf:de:1d
Hex
4
Unik transaksjonsidentifikator. Generert av klienten i begynnelsen av en forespørselsoperasjon

7
Andre gikk
0
Hex
4
Tid i sekunder fra begynnelsen av prosessen med å skaffe en adresse

9
Støvelflagg
0
Hex
2
Visse flagg som kan settes for å indikere protokollparametere

11
Klientens IP-adresse
0.0.0.0
Linje
4
Klientens IP-adresse (hvis noen)

15
Din klients IP-adresse
0.0.0.0
Linje
4
IP-adresse som tilbys av serveren (hvis tilgjengelig)

19
Neste server IP-adresse
0.0.0.0
Linje
4
Server IP-adresse (hvis kjent)

23
Reléagentens IP-adresse
172.16.114.41
Linje
4
IP-adressen til reléagenten (for eksempel en svitsj)

27
Klientens MAC-adresse
14:d6:4d:a7:c9:55
Hex
6
MAC-adressen til pakkeavsenderen (klienten)

31
Klientmaskinvareadresseutfylling
 
Hex
10
Reservert sete. Vanligvis fylt med nuller

41
Serverens vertsnavn
 
Linje
64
DHCP-servernavn. Vanligvis ikke overført

105
Navn på oppstartsfil
 
Linje
128
Filnavn på serveren som brukes av diskløse stasjoner ved oppstart

235
Magisk kake
63: 82: 53: 63
Hex
4
"Magisk" nummer, ifølge hvilket, inkl. du kan fastslå at denne pakken tilhører DHCP-protokollen

DHCP-alternativer. Kan gå i hvilken som helst rekkefølge

236
Opsjonsnummer
53
desember
1
Alternativ 53, som spesifiserer DHCP-pakketypen

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

 
Alternativ lengde
1
desember
1

 
Opsjonsverdi
1
desember
1

 
Opsjonsnummer
50
desember
1
Hvilken IP-adresse ønsker klienten å motta?

 
Alternativ lengde
4
desember
1

 
Opsjonsverdi
172.16.134.61
Linje
4

 
Opsjonsnummer
55
 
1
Nettverksparametere forespurt av klienten. Sammensetningen kan variere

01 — Nettverksmaske
03 - Gateway
06 - DNS
oc — vertsnavn
0f - nettverksdomenenavn
1c - adresse til kringkastingsforespørsel (kringkasting)
42 - TFTP-servernavn
79 - Klasseløs statisk rute

 
Alternativ lengde
8
 
1

 
Opsjonsverdi
01:03:06:0c:0f:1c:42:79
 
8

 
Opsjonsnummer
82
desember
 
Alternativ 82, som overfører MAC-adressen til repeaterenheten og noen tilleggsverdier.

Oftest er dette porten til bryteren som slutt-DHCP-klienten kjører på. Dette alternativet inneholder tilleggsparametere. Den første byten er nummeret på "underalternativet", den andre er lengden, deretter verdien.

I dette tilfellet, i alternativ 82, er underalternativene nestet:
Agentkrets-ID = 00:04:00:01:00:04, der de to siste bytene er DHCP-klientporten som forespørselen kom fra

Agent Remote ID = 00:06:c8:be:19:93:11:48 - MAC-adressen til DHCP-repeaterenheten

 
Alternativ lengde
18
desember
 

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

 
Slutt på pakken
255
desember
1
255 symboliserer slutten av pakken

DHCP-TILBUD

Så snart serveren mottar DHCPDISCOVER-pakken og hvis den ser at den kan tilby klienten noe fra den forespurte, genererer den et svar for den - DHCPDISCOVER. Svaret sendes til havnen "der det kom fra", ved kringkasting, fordi for øyeblikket har klienten ennå ikke en IP-adresse, derfor kan den bare godta pakken hvis den sendes med kringkasting. Klienten gjenkjenner at dette er en pakke for ham ved hans MAC-adresse inne i pakken, samt transaksjonsnummeret som han genererer på det tidspunktet den første pakken opprettes.

DHCPOFFER Pakkestrukturtabell

Plassering i pakken
Navn på verdi (vanlig)
Eksempel
Представление
byte
Avklaring

1
Oppstartsforespørsel
1
Hex
1
Meldingstype. 1 - forespørsel fra klient til server, 2 - svar fra server til klient

2
Maskinvaretype
1
Hex
1
Type maskinvareadresse, i denne protokollen 1 - MAC

3
Lengde på maskinvareadresser
6
Hex
1
Lengde på enhetens MAC-adresse

4
Humle
1
Hex
1
Antall mellomveier

5
Transaksjons-ID
23:cf:de:1d
Hex
4
Unik transaksjonsidentifikator. Generert av klienten i begynnelsen av en forespørselsoperasjon

7
Andre gikk
0
Hex
4
Tid i sekunder fra begynnelsen av prosessen med å skaffe en adresse

9
Støvelflagg
0
Hex
2
Visse flagg som kan settes for å indikere protokollparametere. I dette tilfellet betyr 0 Unicast-forespørselstypen

11
Klientens IP-adresse
0.0.0.0
Linje
4
Klientens IP-adresse (hvis noen)

15
Din klients IP-adresse
172.16.134.61
Linje
4
IP-adresse som tilbys av serveren (hvis tilgjengelig)

19
Neste server IP-adresse
0.0.0.0
Linje
4
Server IP-adresse (hvis kjent)

23
Reléagentens IP-adresse
172.16.114.41
Linje
4
IP-adressen til reléagenten (for eksempel en svitsj)

27
Klientens MAC-adresse
14:d6:4d:a7:c9:55
Hex
6
MAC-adressen til pakkeavsenderen (klienten)

31
Klientmaskinvareadresseutfylling
 
Hex
10
Reservert sete. Vanligvis fylt med nuller

41
Serverens vertsnavn
 
Linje
64
DHCP-servernavn. Vanligvis ikke overført

105
Navn på oppstartsfil
 
Linje
128
Filnavn på serveren som brukes av diskløse stasjoner ved oppstart

235
Magisk kake
63: 82: 53: 63
Hex
4
"Magisk" nummer, ifølge hvilket, inkl. du kan fastslå at denne pakken tilhører DHCP-protokollen

DHCP-alternativer. Kan gå i hvilken som helst rekkefølge

236
Opsjonsnummer
53
desember
1
Alternativ 53, som definerer DHCP 2-pakketypen - DHCPOFFER

 
Alternativ lengde
1
desember
1

 
Opsjonsverdi
2
desember
1

 
Opsjonsnummer
1
desember
1
Mulighet for å tilby DHCP-klienten en nettverksmaske

 
Alternativ lengde
4
desember
1

 
Opsjonsverdi
255.255.224.0
Linje
4

 
Opsjonsnummer
3
desember
1
Mulighet for å tilby DHCP-klienten en standard gateway

 
Alternativ lengde
4
desember
1

 
Opsjonsverdi
172.16.12.1
Linje
4

 
Opsjonsnummer
6
desember
1
Mulighet for å tilby DHCP til DNS-klient

 
Alternativ lengde
4
desember
1

 
Opsjonsverdi
8.8.8.8
Linje
4

 
Opsjonsnummer
51
desember
1
Levetiden til utstedte nettverksparametere i sekunder, hvoretter DHCP-klienten må be om dem på nytt

 
Alternativ lengde
4
desember
1

 
Opsjonsverdi
86400
desember
4

 
Opsjonsnummer
82
desember
1
Alternativ 82, gjentar det som kom i DHCPDISCOVER

 
Alternativ lengde
18
desember
1

 
Opsjonsverdi
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
desember
18

 
Slutt på pakken
255
desember
1
255 symboliserer slutten av pakken

Forespørsel om DHC

Etter at klienten mottar DHCPOFFER, danner han en pakke som ber om nettverksparametere ikke til alle DHCP-servere på nettverket, men bare til én spesifikk, hvis DHCPOFFER-tilbud han "likte" best. "Like"-kriteriene kan være forskjellige og avhenge av klientens DHCP-implementering. Mottakeren av forespørselen angis ved å bruke MAC-adressen til DHCP-serveren. Dessuten kan en DHCPREQUEST-pakke sendes av klienten uten først å generere DHCPDISCOVER, hvis serverens IP-adresse allerede er oppnådd tidligere.

DHCPREQUEST Pakkestrukturtabell

Plassering i pakken
Navn på verdi (vanlig)
Eksempel
Представление
byte
Avklaring

1
Oppstartsforespørsel
1
Hex
1
Meldingstype. 1 - forespørsel fra klient til server, 2 - svar fra server til klient

2
Maskinvaretype
1
Hex
1
Type maskinvareadresse, i denne protokollen 1 - MAC

3
Lengde på maskinvareadresser
6
Hex
1
Lengde på enhetens MAC-adresse

4
Humle
1
Hex
1
Antall mellomveier

5
Transaksjons-ID
23:cf:de:1d
Hex
4
Unik transaksjonsidentifikator. Generert av klienten i begynnelsen av en forespørselsoperasjon

7
Andre gikk
0
Hex
4
Tid i sekunder fra begynnelsen av prosessen med å skaffe en adresse

9
Støvelflagg
8000
Hex
2
Visse flagg som kan settes for å indikere protokollparametere. I dette tilfellet er "kringkasting" satt

11
Klientens IP-adresse
0.0.0.0
Linje
4
Klientens IP-adresse (hvis noen)

15
Din klients IP-adresse
172.16.134.61
Linje
4
IP-adresse som tilbys av serveren (hvis tilgjengelig)

19
Neste server IP-adresse
0.0.0.0
Linje
4
Server IP-adresse (hvis kjent)

23
Reléagentens IP-adresse
172.16.114.41
Linje
4
IP-adressen til reléagenten (for eksempel en svitsj)

27
Klientens MAC-adresse
14:d6:4d:a7:c9:55
Hex
6
MAC-adressen til pakkeavsenderen (klienten)

31
Klientmaskinvareadresseutfylling
 
Hex
10
Reservert sete. Vanligvis fylt med nuller

41
Serverens vertsnavn
 
Linje
64
DHCP-servernavn. Vanligvis ikke overført

105
Navn på oppstartsfil
 
Linje
128
Filnavn på serveren som brukes av diskløse stasjoner ved oppstart

235
Magisk kake
63: 82: 53: 63
Hex
4
"Magisk" nummer, ifølge hvilket, inkl. du kan fastslå at denne pakken tilhører DHCP-protokollen

DHCP-alternativer. Kan gå i hvilken som helst rekkefølge

236
Opsjonsnummer
53
desember
3
Alternativ 53, som definerer DHCP-pakketype 3 - DHCPREQUEST

 
Alternativ lengde
1
desember
1

 
Opsjonsverdi
3
desember
1

 
Opsjonsnummer
61
desember
1
Klient-ID: 01 (for Ehernet) + klient-MAC-adresse

 
Alternativ lengde
7
desember
1

 
Opsjonsverdi
01:2c:ab:25:ff:72:a6
Hex
7

 
Opsjonsnummer
60
desember
 
"Leverandørklasseidentifikator". I mitt tilfelle rapporterer den DHCP-klientversjonen. Kanskje andre enheter returnerer noe annet. Windows rapporterer for eksempel MSFT 5.0

 
Alternativ lengde
11
desember
 

 
Opsjonsverdi
udhcp 0.9.8
Linje
 

 
Opsjonsnummer
55
 
1
Nettverksparametere forespurt av klienten. Sammensetningen kan variere

01 — Nettverksmaske
03 - Gateway
06 - DNS
oc — vertsnavn
0f - nettverksdomenenavn
1c - adresse til kringkastingsforespørsel (kringkasting)
42 - TFTP-servernavn
79 - Klasseløs statisk rute

 
Alternativ lengde
8
 
1

 
Opsjonsverdi
01:03:06:0c:0f:1c:42:79
 
8

 
Opsjonsnummer
82
desember
1
Alternativ 82, gjentar det som kom i DHCPDISCOVER

 
Alternativ lengde
18
desember
1

 
Opsjonsverdi
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
desember
18

 
Slutt på pakken
255
desember
1
255 symboliserer slutten av pakken

DHCPACK

Som bekreftelse på at "ja, det stemmer, dette er din IP-adresse, og jeg vil ikke gi den ut til noen andre" fra DHCP-serveren, serverer en pakke i DHCPACK-format fra serveren til klienten. Det sendes kringkastet akkurat som andre pakker. Selv om jeg, i koden nedenfor for en DHCP-server implementert i Python, dupliserer enhver kringkastingsforespørsel ved å sende en pakke til en spesifikk klient-IP, hvis den allerede er kjent. Dessuten bryr ikke DHCP-serveren seg i det hele tatt om DHCPACK-pakken har nådd klienten. Hvis klienten ikke mottar DHCPACK, gjentar den ganske enkelt DHCPREQUEST etter en stund

DHCPACK-pakkestrukturtabell

Plassering i pakken
Navn på verdi (vanlig)
Eksempel
Представление
byte
Avklaring

1
Oppstartsforespørsel
2
Hex
1
Meldingstype. 1 - forespørsel fra klient til server, 2 - svar fra server til klient

2
Maskinvaretype
1
Hex
1
Type maskinvareadresse, i denne protokollen 1 - MAC

3
Lengde på maskinvareadresser
6
Hex
1
Lengde på enhetens MAC-adresse

4
Humle
1
Hex
1
Antall mellomveier

5
Transaksjons-ID
23:cf:de:1d
Hex
4
Unik transaksjonsidentifikator. Generert av klienten i begynnelsen av en forespørselsoperasjon

7
Andre gikk
0
Hex
4
Tid i sekunder fra begynnelsen av prosessen med å skaffe en adresse

9
Støvelflagg
8000
Hex
2
Visse flagg som kan settes for å indikere protokollparametere. I dette tilfellet er "kringkasting" satt

11
Klientens IP-adresse
0.0.0.0
Linje
4
Klientens IP-adresse (hvis noen)

15
Din klients IP-adresse
172.16.134.61
Linje
4
IP-adresse som tilbys av serveren (hvis tilgjengelig)

19
Neste server IP-adresse
0.0.0.0
Linje
4
Server IP-adresse (hvis kjent)

23
Reléagentens IP-adresse
172.16.114.41
Linje
4
IP-adressen til reléagenten (for eksempel en svitsj)

27
Klientens MAC-adresse
14:d6:4d:a7:c9:55
Hex
6
MAC-adressen til pakkeavsenderen (klienten)

31
Klientmaskinvareadresseutfylling
 
Hex
10
Reservert sete. Vanligvis fylt med nuller

41
Serverens vertsnavn
 
Linje
64
DHCP-servernavn. Vanligvis ikke overført

105
Navn på oppstartsfil
 
Linje
128
Filnavn på serveren som brukes av diskløse stasjoner ved oppstart

235
Magisk kake
63: 82: 53: 63
Hex
4
"Magisk" nummer, ifølge hvilket, inkl. du kan fastslå at denne pakken tilhører DHCP-protokollen

DHCP-alternativer. Kan gå i hvilken som helst rekkefølge

236
Opsjonsnummer
53
desember
3
Alternativ 53, som definerer DHCP-pakketype 5 - DHCPACK

 
Alternativ lengde
1
desember
1

 
Opsjonsverdi
5
desember
1

 
Opsjonsnummer
1
desember
1
Mulighet for å tilby DHCP-klienten en nettverksmaske

 
Alternativ lengde
4
desember
1

 
Opsjonsverdi
255.255.224.0
Linje
4

 
Opsjonsnummer
3
desember
1
Mulighet for å tilby DHCP-klienten en standard gateway

 
Alternativ lengde
4
desember
1

 
Opsjonsverdi
172.16.12.1
Linje
4

 
Opsjonsnummer
6
desember
1
Mulighet for å tilby DHCP til DNS-klient

 
Alternativ lengde
4
desember
1

 
Opsjonsverdi
8.8.8.8
Linje
4

 
Opsjonsnummer
51
desember
1
Levetiden til utstedte nettverksparametere i sekunder, hvoretter DHCP-klienten må be om dem på nytt

 
Alternativ lengde
4
desember
1

 
Opsjonsverdi
86400
desember
4

 
Opsjonsnummer
82
desember
1
Alternativ 82, gjentar det som kom i DHCPDISCOVER

 
Alternativ lengde
18
desember
1

 
Opsjonsverdi
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
desember
18

 
Slutt på pakken
255
desember
1
255 symboliserer slutten av pakken

Installasjon

Installasjonen består faktisk av å installere pythonmodulene som er nødvendige for arbeidet. Det antas at MySQL allerede er installert og konfigurert.

FreeBSD

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

Ubuntu

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

Vi lager en MySQL-database, laster opp pydhcp.sql-dumpen til den og konfigurerer konfigurasjonsfilen.

Konfigurasjon

Alle serverinnstillinger er i en xml-fil. Referansefil:

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 vert 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 velg ip,mask,ruter,dns fra brukere der upper(mac)=upper('{option_3_AgentRemoteId_hex}') og upper(port)=upper('{option_1_AgentCircuitId_port_hex}') velg ip,maske,ruter,dns fra brukere der upper(mac)=upper('{sw_mac}') og upper(port)=upper('{sw_port82}') velg ip,maske,ruter,dns fra brukere der upper(mac)=upper('{ClientMacAddress}') sett inn verdier i historikk (id,dt,mac,ip,comment) (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')

Nå mer detaljert om taggene:

dhcpserver-delen beskriver de grunnleggende innstillingene for å starte serveren, nemlig:

  • vert - hvilken IP-adresse serveren lytter til på port 67
  • broadcast - hvilken ip er sendingen for DHCPOFFER og DHCPACK
  • DHCPServer - hva er IP-en til DHCP-serveren
  • LeaseTime leietid for den utstedte IP-adressen
  • ThreadLimit - hvor mange tråder kjører samtidig for å behandle innkommende UDP-pakker på port 67. Det er ment å hjelpe på høybelastningsprosjekter 😉
  • defaultMask,defaultRouter,defaultDNS - hva som tilbys abonnenten som standard hvis en IP blir funnet i databasen, men tilleggsparametere er ikke spesifisert for den

mysql delen:

vert, brukernavn, passord, basenavn - alt taler for seg selv. En omtrentlig databasestruktur er lagt ut på GitHub

Spørringsseksjon: forespørsler om å motta TILBUD/ACK er beskrevet her:

  • offer_count — antall linjer med forespørsler som returnerer et resultat som ip,mask,ruter,dns
  • offer_n — spørringsstreng. Hvis returen er tom, utfører du følgende tilbudsforespørsel
  • history_sql - en spørring som for eksempel skriver til "autorisasjonshistorikken" for en abonnent

Forespørsler kan inkludere alle variabler fra alternativseksjonen eller alternativer fra DHCP-protokollen.

Alternativer-delen. Det er her det blir mer interessant. Her kan vi lage variabler som vi kan bruke senere i spørringsdelen.

For eksempel:

option_82_hex:sw_port1:20:22

, tar denne kommandolinjen hele linjen som kom i DHCP-forespørselsalternativ 82, i hex-format, i området fra 20 til og med 22 byte og legger den i den nye variabelen sw_port1 (bytt port der forespørselen kom)

option_82_hex:sw_mac:26:40

, definer sw_mac-variabelen, og tar hex fra området 26:40

Du kan se alle mulige alternativer som kan brukes i spørringer ved å starte serveren med -d-bryteren. Vi vil se noe slikt:

--en DHCPINFORM-pakke ankom port 67, fra 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress': 'BaddressyxMac': '0025224 764 00 %"Jxd7d" , 'Htype': 'Ethernet', 'Hostname': B'x91xa5xe0xa3xa5xa9-x8fx8a ',' reqlistdns ': true,' reqlistomainname ': true,' reqlistperfowmroUterdiscover ': true, true, true,': sanne, ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': sanne': sanne ': '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': '589e2e _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ølgelig kan vi pakke hvilken som helst variabel i {} og den vil bli brukt i SQL-spørringen.

La oss registrere for historikk at klienten mottok IP-adressen:

DHCP+Mysql-server i Python

DHCP+Mysql-server i Python

Serverstart

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

— d konsoll utgangsmodus DEBUG
- c <filnavn> konfigurasjonsfil

debriefing

Og nå flere detaljer om implementering av serveren i Python. Det er en smerte. Python ble lært i farten. Mange øyeblikk er laget i stilen "wow, på en eller annen måte fikk jeg det til å fungere." Ikke optimalisert i det hele tatt, og forlatt i denne formen hovedsakelig på grunn av liten erfaring med Python-utvikling. Jeg vil dvele ved de mest interessante aspektene ved serverimplementeringen i "kode".

XML-konfigurasjonsfil-parser

Standard Python-modul xml.dom brukes. Det virker enkelt, men under implementeringen var det en merkbar mangel på tydelig dokumentasjon og eksempler på nettverket ved bruk av denne modulen.

    tree = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") for elem i mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("host")[0].firstChild. gconfig["mysql_username"]=elem.getElementsByTagName("brukernavn")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("passord")[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"] 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 alternativer: node=elem.getElementsByTagName("option") for alternativer i node : optionsMod.append(options.firstChild.data)

Multithreading

Merkelig nok er multithreading i Python implementert veldig tydelig og enkelt.

def PacketWork(data,addr): ... # implementering av å analysere den innkommende pakken og svare 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 definerte PacketWork-funksjonen i bakgrunnen med parametere mens threading.active_count() >gconfig["dhcp_ThreadLimit"]: tid. sleep(1) # if the number Det er flere tråder som allerede kjører enn i innstillingene, vi venter til det er færre av dem

Motta/sende DHCP-pakke

For å avskjære UDP-pakker som kommer gjennom nettverkskortet, må du "heve" kontakten:

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

, hvor flaggene er:

  • AF_INET - betyr at adresseformatet vil være IP: port. Det kan også være AF_UNIX - hvor adressen er gitt av filnavnet.
  • SOCK_DGRAM - betyr at vi ikke aksepterer en "råpakke", men en som allerede har gått gjennom brannmuren, og med en delvis trimmet pakke. De. vi mottar bare en UDP-pakke uten den "fysiske" komponenten i UDP-pakkeinnpakningen. Hvis du bruker SOCK_RAW-flagget, må du også analysere denne "wrapperen".

Å sende en pakke kan være som en kringkasting:

                    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #bytt kontakten til kringkastingsmodus 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) # bytt kontakten til multilyttermodus rz=udp_socket.sendto(packetack, addr)

, der SOL_SOCKET betyr "protokollnivået" for innstillingsalternativer,

, SO_BROADCAST alternativet at hjelmpakken er "kringkastet"

  ,SO_REUSEADDR-alternativet bytter kontakten til "mange lyttere"-modus. I teorien er det unødvendig i dette tilfellet, men på en av FreeBSD-serverne jeg testet på, fungerte ikke koden uten dette alternativet.

Parsing av en DHCP-pakke

Det var her jeg virkelig likte Python. Det viser seg at ut av esken lar det deg være ganske fleksibel med bytekoden. Tillater det veldig enkelt å oversette til desimalverdier, strenger og hex - dvs. dette er det vi faktisk trenger for å forstå strukturen til pakken. Så, for eksempel, kan du få en rekke byte i HEX og bare byte:

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

, pakk bytene inn i en struktur:

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

Få IP fra struktur:

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

Og vice versa:

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

Det var alt for nå 😉

Kilde: www.habr.com

Legg til en kommentar