
Syftet med detta projekt var:
- Studie av DHCP-protokollet nÀr det anvÀnds i IPv4-nÀtverk
- Studie av Python (nĂ„got mer Ă€n frĂ„n grunden đ )
- byte av server (min fork), originalet , som det blir svÄrare och svÄrare att kompilera för det nya operativsystemet. Och jag gillar inte att det finns en binÀrfil som man inte kan "byta ut just nu"
- skapa en fungerande DHCP-server med möjlighet att hÀmta IP-adressen för en klient baserat pÄ klientens mac-adress eller kombinationen av switchens mac-adress + port (Option 82)
- skriva Ànnu ett exemplar (à h! det Àr min favoritaktivitet)
- fĂ„ kritik för min klumpighet pĂ„ Habrhabr (eller helst en inbjudan) đ
Resultat: fungerar đ Testat pĂ„ FreeBSD och Ubuntu. Teoretiskt kan koden anpassas för att fungera pĂ„ vilket operativsystem som helst, eftersom det inte verkar finnas nĂ„gra specifika bindningar i koden.
Varning! Mycket mer följer.
LÀnk till repository för dem som vill .
Processen för installation, konfiguration och anvĂ€ndning av resultatet av "studien av materien" beskrivs lĂ€ngre ner, följt av lite teori om DHCP-protokollet. För mig. Och för historien đ
Lite teori
Vad Àr DHCP
Det Àr ett nÀtverksprotokoll som tillÄter en enhet att ta reda pÄ sin IP-adress (och andra parametrar som gateway, DNS och sÄ vidare) frÄn en DHCP-server. Paketbyte sker via UDP-protokollet. Den allmÀnna principen för hur enheten fungerar vid begÀran av nÀtverksparametrar Àr följande:
- Enheten (klienten) skickar en broadcast UDP-begÀran (DHCPDISCOVER) över hela nÀtverket med begÀran "nÄgon, ge mig en IP-adress". Vanligtvis (men inte alltid) sker begÀran frÄn port 68 (kÀlla) till port 67 (destination). Vissa enheter skickar paket Àven frÄn port 67. Inuti DHCPDISCOVER-paketet finns klientens MAC-adress.
- Alla DHCP-servrar i nÀtverket (och de kan vara flera) formar ett erbjudande, DHCPOFFER, med nÀtverksinstÀllningar för enheten som skickade DHCPDISCOVER, och skickar det ocksÄ som broadcast över nÀtverket. Identifieringen av till vem detta paket Àr avsett sker med hjÀlp av klientens MAC-adress som gavs tidigare i DHCPDISCOVER-begÀran.
- Kunden tar emot paket med nÀtverksinstÀllningar, vÀljer det som Àr mest attraktivt (kriterier kan variera, till exempel tid för paketleverans eller antal mellanliggande vÀgar), och gör en "officiell begÀran" DHCPREQUEST med nÀtverksinstÀllningarna till den servern som han gillar. I detta fall gÄr paketet direkt till en specifik DHCP-server.
- Servern som mottagit DHCPREQUEST skickar ett paket av formatet DHCPACK, dÀr den Àn en gÄng listar nÀtverksinstÀllningarna som Àr avsedda för denna klient.

Dessutom finns det DHCPINFORM-paket som skickas frÄn klienten med syftet att informera DHCP-servern om att "klienten Àr aktiv" och anvÀnder de tilldelade nÀtverksinstÀllningarna. I denna serversimplementation ignoreras dessa paket.
Paketformat
Generellt ser Ethernet-paketets ram ungefÀr ut sÄ hÀr:
![]()
I vÄrt fall kommer vi endast att titta pÄ datan i UDP-paketet, utan headers för OSI-protokollen, det vill sÀga strukturen av DHCP:
DHCPDISCOVER
SÄ, processen för att erhÄlla en IP-adress för en enhet börjar med att DHCP-klienten skickar en broadcast-förfrÄgan frÄn port 68 till 255.255.255.255:67. I detta paket inkluderar klienten sin MAC-adress samt vad den vill fÄ frÄn DHCP-servern. Paketstrukturen beskrivs i tabellen nedan.
Tabell över strukturen av paketet DHCPDISCOVER
Position i paketet
Namn pÄ vÀrdet
Exempel
Representation
Byte
Förklaring
1
Boot Request
1
Hex
1
Typ av meddelande. 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
LÀngd av hÄrdvaruadressen
6
Hex
1
LÀngd pÄ enhetens MAC-adress.
4
Hops
1
Hex
1
Antal mellanliggande vÀgar.
5
Transaktions-ID
23:cf:de:1d
Hex
4
Unik identifierare för transaktionen. Genereras av klienten i början av begÀrningsoperationen.
7
Sekunder förflutna
0
Hex
4
Tiden i sekunder sedan början pÄ processen för att erhÄlla en adress.
9
Bootp-flaggor
0
Hex
2
Vissa flaggor som kan sÀttas som indikator av protokollparametrar.
11
Klientens IP-adress
0.0.0.0
StrÀng
4
IP-adress för klienten (om det finns).
15
Din klient-IP-adress
0.0.0.0
StrÀng
4
IP-adress som föreslagits av servern (om det finns).
19
NĂ€sta servers IP-adress
0.0.0.0
StrÀng
4
IP-adress för servern (om den Àr kÀnd).
23
Relay-agentens IP-adress
172.16.114.41
StrÀng
4
IP-adress för relay-agenten (t.ex. switch).
27
Klientens MAC-adress
14:d6:4d:a7:c9:55
Hex
6
MAC-adressen för avsÀndaren av paketet (klienten).
31
Padding av klientens hÄrdvaruadress
Â
Hex
10
Reserverat utrymme. Vanligtvis fyllt med nollor.
41
Serverns vÀrdnamn
Â
StrÀng
64
Namn pÄ DHCP-servern. Vanligtvis inte överförs.
105
Boot-filnamn
Â
StrÀng
128
Filnamn pÄ servern som anvÀnds av diskfria stationer vid start
235
Magic cookie
63:82:53:63
Hex
4
Ett »magiskt« nummer som kan anvÀndas för att avgöra att detta paket tillhör DHCP-protokollet
DHCP-alternativ. Kan komma i valfri ordning
236
Alternativnummer
53
Dec
1
Alternativ 53 som definierar typen av DHCP-paket
1 â DHCPDISCOVER
3 â DHCPREQUEST
2 â DHCPOFFER
5 â DHCPACK
8 â DHCPINFORM
Â
Alternativets lÀngd
1
Dec
1
Â
Alternativets vÀrde
1
Dec
1
Â
Alternativnummer
50
Dec
1
Vilken IP-adress vill klienten fÄ
Â
Alternativets lÀngd
4
Dec
1
Â
Alternativets vÀrde
172.16.134.61
StrÀng
4
Â
Alternativnummer
55
Â
1
De nÀtverksparametrar som begÀrs av klienten. InnehÄllet kan variera
01 â NĂ€tmask
03 â Gateway
06 â DNS
oc â VĂ€rdnamn
0f â nĂ€tverks domĂ€nnamn
1c â adress för sĂ€ndning av brĂ„dskande meddelanden (broadcast)
42 â namn pĂ„ TFTP-servern
79 â Classless Static Route
Â
Alternativets lÀngd
8
Â
1
Â
Alternativets vÀrde
01:03:06:0c:0f:1c:42:79
Â
8
Â
Alternativnummer
82
Dec
Â
Alternativ 82, dĂ€r MAC-adressen för enheter â retransmittorn och vissa ytterligare vĂ€rden överförs.
Oftast â porten pĂ„ switchen dĂ€r den slutgiltiga DHCP-klienten arbetar. I detta alternativ Ă€r det »inbĂ€ddade« ytterligare parametrar. Den första byte â subalternativets nummer, den andra dess lĂ€ngd, dĂ€refter dess vĂ€rde.
I detta fall bÀr alternativ 82 subalternativ:
Agent Circuit ID = 00:04:00:01:00:04, dÀr de sista tvÄ bytes Àr porten för DHCP-klienten som skickade begÀran
Agent Remote ID = 00:06:c8:be:19:93:11:48 â MAC-adressen för retransmittoren DHCP
Â
Alternativets lÀngd
18
Dec
Â
Â
Alternativets vÀrde
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Hex
Â
Â
Paketets slut
255
Dec
1
255 symboliserar slutet av paketet
DHCPOFFER
SĂ„ snart servern mottar paketet DHCPDISCOVER och om den ser att den kan erbjuda nĂ„got till klienten frĂ„n vad som begĂ€rdes, sĂ„ formar den ett svar â DHCPDISCOVER. Svaret skickas tillbaka till porten »frĂ„n vilken den kom«, som en broadcast, eftersom klienten för tillfĂ€llet Ă€nnu inte har nĂ„gon IP-adress, sĂ„ paketet kan endast tas emot om det skickas ut som en brĂ„dskande sĂ€ndning. Klienten kĂ€nner igen att detta paket Ă€r för den genom sin MAC-adress inuti paketet, sĂ„vĂ€l som transaktionsnumret som den genererar vid skapandet av det första paketet.
Strukturen för DHCPOFFER-paketet
Position i paketet
Namn pÄ vÀrdet (vanligtvis)
Exempel
Representation
Byte
Förklaring
1
Boot Request
1
Hex
1
Typ av meddelande. 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
LÀngd av hÄrdvaruadressen
6
Hex
1
LÀngd pÄ enhetens MAC-adress.
4
Hops
1
Hex
1
Antal mellanliggande vÀgar.
5
Transaktions-ID
23:cf:de:1d
Hex
4
Unik identifierare för transaktionen. Genereras av klienten i början av begÀrningsoperationen.
7
Sekunder förflutna
0
Hex
4
Tiden i sekunder sedan början pÄ processen för att erhÄlla en adress.
9
Bootp-flaggor
0
Hex
2
Vissa flaggor som kan stĂ€llas in som en indikation pĂ„ protokollparametrar. I detta fall, 0 â betyder typ av begĂ€ran Unicast
11
Klientens IP-adress
0.0.0.0
StrÀng
4
IP-adress för klienten (om det finns).
15
Din klient-IP-adress
172.16.134.61
StrÀng
4
IP-adress som föreslagits av servern (om det finns).
19
NĂ€sta servers IP-adress
0.0.0.0
StrÀng
4
IP-adress för servern (om den Àr kÀnd).
23
Relay-agentens IP-adress
172.16.114.41
StrÀng
4
IP-adress för relay-agenten (t.ex. switch).
27
Klientens MAC-adress
14:d6:4d:a7:c9:55
Hex
6
MAC-adressen för avsÀndaren av paketet (klienten).
31
Padding av klientens hÄrdvaruadress
Â
Hex
10
Reserverat utrymme. Vanligtvis fyllt med nollor.
41
Serverns vÀrdnamn
Â
StrÀng
64
Namn pÄ DHCP-servern. Vanligtvis inte överförs.
105
Boot-filnamn
Â
StrÀng
128
Filnamn pÄ servern som anvÀnds av diskfria stationer vid start
235
Magic cookie
63:82:53:63
Hex
4
Ett »magiskt« nummer som kan anvÀndas för att avgöra att detta paket tillhör DHCP-protokollet
DHCP-alternativ. Kan komma i valfri ordning
236
Alternativnummer
53
Dec
1
Alternativ 53, som definierar typen av DHCP-paket 2 â DHCPOFFER
Â
Alternativets lÀngd
1
Dec
1
Â
Alternativets vÀrde
2
Dec
1
Â
Alternativnummer
1
Dec
1
Alternativ som erbjuder DHCP-klienten nÀtmask
Â
Alternativets lÀngd
4
Dec
1
Â
Alternativets vÀrde
255.255.224.0
StrÀng
4
Â
Alternativnummer
3
Dec
1
Alternativ som erbjuder DHCP-klienten standard gateway
Â
Alternativets lÀngd
4
Dec
1
Â
Alternativets vÀrde
172.16.12.1
StrÀng
4
Â
Alternativnummer
6
Dec
1
Alternativ som erbjuder DHCP-klienten DNS
Â
Alternativets lÀngd
4
Dec
1
Â
Alternativets vÀrde
8.8.8.8
StrÀng
4
Â
Alternativnummer
51
Dec
1
LivslÀngden för de utfÀrdade nÀtverksparametrarna i sekunder, efter vilken DHCP-klienten mÄste begÀra dem igen
Â
Alternativets lÀngd
4
Dec
1
Â
Alternativets vÀrde
86400
Dec
4
Â
Alternativnummer
82
Dec
1
Alternativ 82, upprepar vad som kom i DHCPDISCOVER
Â
Alternativets lÀngd
18
Dec
1
Â
Alternativets vÀrde
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Dec
18
Â
Paketets slut
255
Dec
1
255 symboliserar slutet av paketet
DHCPREQUEST
Efter att klienten har fÄtt DHCPOFFER, skapar den ett paket med begÀran om nÀtverksparametrar, inte till alla DHCP-servrar i nÀtverket, utan endast till en specifik, vars DHCPOFFER-erbjudande den tyckte mest om. Kriterierna för "tyckte om" kan variera och beror pÄ implementeringen av DHCP-klienten. Mottagaren av begÀran anges med MAC-adressen för DHCP-servern. Dessutom kan paketet DHCPREQUEST skickas av klienten utan att ha bildat tidigare DHCPDISCOVER, om IP-adressen frÄn servern redan tidigare har erhÄllits.
Tabell över strukturen för DHCPREQUEST-paketet
Position i paketet
Namn pÄ vÀrdet (vanligtvis)
Exempel
Representation
Byte
Förklaring
1
Boot Request
1
Hex
1
Typ av meddelande. 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
LÀngd av hÄrdvaruadressen
6
Hex
1
LÀngd pÄ enhetens MAC-adress.
4
Hops
1
Hex
1
Antal mellanliggande vÀgar.
5
Transaktions-ID
23:cf:de:1d
Hex
4
Unik identifierare för transaktionen. Genereras av klienten i början av begÀrningsoperationen.
7
Sekunder förflutna
0
Hex
4
Tiden i sekunder sedan början pÄ processen för att erhÄlla en adress.
9
Bootp-flaggor
8000
Hex
2
NÄgra flaggor kan sÀttas för att indikera protokollparametrar. I detta fall Àr "broadcast" instÀllt.
11
Klientens IP-adress
0.0.0.0
StrÀng
4
IP-adress för klienten (om det finns).
15
Din klient-IP-adress
172.16.134.61
StrÀng
4
IP-adress som föreslagits av servern (om det finns).
19
NĂ€sta servers IP-adress
0.0.0.0
StrÀng
4
IP-adress för servern (om den Àr kÀnd).
23
Relay-agentens IP-adress
172.16.114.41
StrÀng
4
IP-adress för relay-agenten (t.ex. switch).
27
Klientens MAC-adress
14:d6:4d:a7:c9:55
Hex
6
MAC-adressen för avsÀndaren av paketet (klienten).
31
Padding av klientens hÄrdvaruadress
Â
Hex
10
Reserverat utrymme. Vanligtvis fyllt med nollor.
41
Serverns vÀrdnamn
Â
StrÀng
64
Namn pÄ DHCP-servern. Vanligtvis inte överförs.
105
Boot-filnamn
Â
StrÀng
128
Filnamn pÄ servern som anvÀnds av diskfria stationer vid start
235
Magic cookie
63:82:53:63
Hex
4
Ett »magiskt« nummer som kan anvÀndas för att avgöra att detta paket tillhör DHCP-protokollet
DHCP-alternativ. Kan komma i valfri ordning
236
Alternativnummer
53
Dec
3
Alternativ 53, som definierar typen av DHCP-paket 3 - DHCPREQUEST
Â
Alternativets lÀngd
1
Dec
1
Â
Alternativets vÀrde
3
Dec
1
Â
Alternativnummer
61
Dec
1
Klientidentifierare: 01 (för Ethernet) + klientens MAC-adress
Â
Alternativets lÀngd
7
Dec
1
Â
Alternativets vÀrde
01:2c:ab:25:ff:72:a6
Hex
7
Â
Alternativnummer
60
Dec
Â
"Vendor class identifier". I mitt fall rapporterar den versionen av DHCP-klienten. Andra enheter kan returnera nÄgot annat. Windows till exempel meddelar MSFT 5.0
Â
Alternativets lÀngd
11
Dec
Â
Â
Alternativets vÀrde
udhcp 0.9.8
StrÀng
Â
Â
Alternativnummer
55
Â
1
De nÀtverksparametrar som begÀrs av klienten. InnehÄllet kan variera
01 â NĂ€tmask
03 â Gateway
06 â DNS
oc â VĂ€rdnamn
0f â nĂ€tverks domĂ€nnamn
1c â adress för sĂ€ndning av brĂ„dskande meddelanden (broadcast)
42 â namn pĂ„ TFTP-servern
79 â Classless Static Route
Â
Alternativets lÀngd
8
Â
1
Â
Alternativets vÀrde
01:03:06:0c:0f:1c:42:79
Â
8
Â
Alternativnummer
82
Dec
1
Alternativ 82, upprepar vad som kom i DHCPDISCOVER
Â
Alternativets lÀngd
18
Dec
1
Â
Alternativets vÀrde
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Dec
18
Â
Paketets slut
255
Dec
1
255 symboliserar slutet av paketet
DHCPACK
Som bekrÀftelse pÄ att "ja, precis, det Àr din IP-adress och jag kommer inte att ge den till nÄgon annan" frÄn DHCP-servern, fungerar paketet i formatet DHCPACK frÄn servern till klienten. Det skickas precis som de andra paketen i broadcast. Dock, i nedan presenterad kod för en DHCP-server implementerad i Python, duplicerar jag varje broadcast-begÀran genom att skicka paketet till en specifik IP-adress för klienten, om den redan Àr kÀnd. DHCP-servern bryr sig inte om paketet DHCPACK nÄdde klienten. Om klienten inte fÄr DHCPACK, upprepar den helt enkelt DHCPREQUEST efter en tid.
Tabell över strukturen för DHCPACK-paketet
Position i paketet
Namn pÄ vÀrdet (vanligtvis)
Exempel
Representation
Byte
Förklaring
1
Boot Request
2
Hex
1
Typ av meddelande. 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
LÀngd av hÄrdvaruadressen
6
Hex
1
LÀngd pÄ enhetens MAC-adress.
4
Hops
1
Hex
1
Antal mellanliggande vÀgar.
5
Transaktions-ID
23:cf:de:1d
Hex
4
Unik identifierare för transaktionen. Genereras av klienten i början av begÀrningsoperationen.
7
Sekunder förflutna
0
Hex
4
Tiden i sekunder sedan början pÄ processen för att erhÄlla en adress.
9
Bootp-flaggor
8000
Hex
2
NÄgra flaggor kan sÀttas för att indikera protokollparametrar. I detta fall Àr "broadcast" instÀllt.
11
Klientens IP-adress
0.0.0.0
StrÀng
4
IP-adress för klienten (om det finns).
15
Din klient-IP-adress
172.16.134.61
StrÀng
4
IP-adress som föreslagits av servern (om det finns).
19
NĂ€sta servers IP-adress
0.0.0.0
StrÀng
4
IP-adress för servern (om den Àr kÀnd).
23
Relay-agentens IP-adress
172.16.114.41
StrÀng
4
IP-adress för relay-agenten (t.ex. switch).
27
Klientens MAC-adress
14:d6:4d:a7:c9:55
Hex
6
MAC-adressen för avsÀndaren av paketet (klienten).
31
Padding av klientens hÄrdvaruadress
Â
Hex
10
Reserverat utrymme. Vanligtvis fyllt med nollor.
41
Serverns vÀrdnamn
Â
StrÀng
64
Namn pÄ DHCP-servern. Vanligtvis inte överförs.
105
Boot-filnamn
Â
StrÀng
128
Filnamn pÄ servern som anvÀnds av diskfria stationer vid start
235
Magic cookie
63:82:53:63
Hex
4
Ett »magiskt« nummer som kan anvÀndas för att avgöra att detta paket tillhör DHCP-protokollet
DHCP-alternativ. Kan komma i valfri ordning
236
Alternativnummer
53
Dec
3
Alternativ 53, som definierar typen av DHCP-paket 5 - DHCPACK
Â
Alternativets lÀngd
1
Dec
1
Â
Alternativets vÀrde
5
Dec
1
Â
Alternativnummer
1
Dec
1
Alternativ som erbjuder DHCP-klienten nÀtmask
Â
Alternativets lÀngd
4
Dec
1
Â
Alternativets vÀrde
255.255.224.0
StrÀng
4
Â
Alternativnummer
3
Dec
1
Alternativ som erbjuder DHCP-klienten standard gateway
Â
Alternativets lÀngd
4
Dec
1
Â
Alternativets vÀrde
172.16.12.1
StrÀng
4
Â
Alternativnummer
6
Dec
1
Alternativ som erbjuder DHCP-klienten DNS
Â
Alternativets lÀngd
4
Dec
1
Â
Alternativets vÀrde
8.8.8.8
StrÀng
4
Â
Alternativnummer
51
Dec
1
LivslÀngden för de utfÀrdade nÀtverksparametrarna i sekunder, efter vilken DHCP-klienten mÄste begÀra dem igen
Â
Alternativets lÀngd
4
Dec
1
Â
Alternativets vÀrde
86400
Dec
4
Â
Alternativnummer
82
Dec
1
Alternativ 82, upprepar vad som kom i DHCPDISCOVER
Â
Alternativets lÀngd
18
Dec
1
Â
Alternativets vÀrde
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
Dec
18
Â
Paketets slut
255
Dec
1
255 symboliserar slutet av paketet
Installation
Installationen innebÀr faktiskt att installera de pythonmoduler som behövs för att fungera. Antas att MySQL redan Àr installerat och konfigurerat.
FreeBSD
pkg install python3 python3 -m ensurepip pip3 install mysql-connector
Ubuntu
sudo apt-get install python3 sudo apt-get install pip3 sudo pip3 install mysql-connector
Skapa MySQL-databasen, ladda upp dumpen pydhcp.sql, konfigurera konfigurationsfilen.
Konfiguration
Alla serverinstÀllningar ligger i en fil i xml-format. Referensfil:
0.0.0.0
255.255.255.255
192.168.0.71
8600
1
255.255.255.0
192.168.0.1
8.8.8.8
localhost
test
test
pydhcp
option_82_hex:sw_port1:20:22
option_82_hex:sw_port2:16:18
option_82_hex:sw_mac:26:40
3
select ip,mask,router,dns from users where upper(mac)=upper('{option_82_AgentRemoteId_hex}') and upper(port)=upper('{option_82_AgentCircuitId_port_hex}')
select ip,mask,router,dns from users where upper(mac)=upper('{sw_mac}') and upper(port)=upper('{sw_port2}')
select ip,mask,router,dns from users where upper(mac)=upper('{ClientMacAddress}')
insert into history (id,dt,mac,ip,comment) values (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')Nu ska vi titta nÀrmare pÄ taggarna:
Sektionen dhcpserver beskriver de grundlÀggande instÀllningarna för att starta servern, nÀmligen:
- host â vilken IP-adress servern lyssnar pĂ„ pĂ„ port 67
- broadcast â vilken IP som Ă€r broadcast för DHCPOFFER och DHCPACK
- DHCPServer â vilken IP som anvĂ€nds av DHCP-servern
- LeaseTime Àr tiden för uthyrning av den tilldelade IP-adressen
- ThreadLimit â hur mĂ„nga trĂ„dar som körs samtidigt för att bearbeta mottagna UDP-paket pĂ„ port 67. Antas hjĂ€lpa vid högtrafikprojekt đ
- defaultMask, defaultRouter, defaultDNS â det som erbjuds abonnenten som standard om IP finns i databasen men inga ytterligare parametrar anges för den
Sektion mysql:
host, username, password, basename â allt talar för sig sjĂ€lv. En ungefĂ€rlig struktur av databasen finns publicerad pĂ„
Sektionen query: hÀr beskrivs förfrÄgningarna för att fÄ OFFER/ACK:
- offer_count â antalet rader med förfrĂ„gningar som returnerar resultat av typen ip, mask, router, dns
- offer_n â förfrĂ„gningsstrĂ€ng. Om resultatet Ă€r tomt, utförs nĂ€sta förfrĂ„gan offer
- history_sql â en förfrĂ„gan som skriver till exempel i "autentiseringshistorik" för abonnenten
I förfrÄgningarna kan alla variabler frÄn sektionen options eller alternativ frÄn DHCP-protokollet ingÄ.
Sektion options. HÀr blir det mer intressant. HÀr kan vi skapa variabler som vi kan anvÀnda senare i sektionen query.
Till exempel:
option_82_hex:sw_port1:20:22, denna rad kommando tar hela strÀngen som kommer i DHCP-förfrÄgan i alternativ 82, i hex-format, i intervallet 20 till 22 byte inklusive och lÀgger den i en ny variabel sw_port1 (porten av switchen som begÀran kom ifrÄn)
option_82_hex:sw_mac:26:40, vi definierar variabeln sw_mac genom att ta hex frÄn intervallet 26:40
För att se alla tillgÀngliga alternativ som kan anvÀndas i förfrÄgningar kan vi starta servern med nyckeln -d. Vi ser ungefÀr sÄ hÀr ut i loggen:
--en DHCPINFORM-paket har kommit till port 67, frÄn 0025224ad764, b'x91xa5xe0xa3xa5xa9-x8fx8a', ('172.30.114.25', 68)
{'ClientMacAddress': '0025224ad764',
'ClientMacAddressByte': b'x00%"Jxd7d',
'HType': 'Ethernet',
'HostName': b'x91xa5xe0xa3xa5xa9-x8fx8a',
'ReqListDNS': True,
'ReqListDomainName': True,
'ReqListPerfowmRouterDiscover': True,
'ReqListRouter': True,
'ReqListStaticRoute': True,
'ReqListSubnetMask': True,
'ReqListVendorSpecInfo': 43,
'RequestedIpAddress': '0.0.0.0',
'Vendor': b'MSFT 5.0',
'chaddr': '0025224ad764',
'ciaddr': '172.30.128.13',
'flags': b'x00x00',
'giaddr': '172.30.114.25',
'gpoz': 308,
'hlen': 6,
'hops': 1,
'htype': 'MAC',
'magic_cookie': b'cx82Sc',
'op': 'DHCPINFORM',
'option12': 12,
'option53': 53,
'option55': 55,
'option60': 60,
'option61': 61,
'option82': 82,
'option_82_byte': b'x12x01x06x00x04x00x01x00x06x02x08x00'
b'x06x00x1eXx9exb2xad',
'option_82_hex': '12010600040001000602080006001e589eb2ad',
'option_82_len': 18,
'option_82_str': "b'x12x01x06x00x04x00x01x00x06x02x08x00x06x00x1eXx9exb2xad'",
'result': False,
'secs': 768,
'siaddr': '0.0.0.0',
'sw_mac': '001e589eb2ad',
'sw_port1': '06',
'xidbyte': b'<x89}x8c',
'xidhex': '3c897d8c',
'yiaddr': '0.0.0.0'}DÀrför kan vi kapsla in vilken som helst variabel i {} och den kommer att anvÀndas i SQL-förfrÄgan.
LÄt oss dokumentera att IP-adressen som klienten fick:


Starta servern
.\/pydhcpdb.py -d -c config.xml
â d lĂ€ge för att skriva ut i konsolen DEBUG
â c <filnamn> konfigurationsfil
Flygplansanalys
Nu mer i detalj om implementeringen av servern i Python. Detta Àr smÀrtsamt. Python lÀrdes "pÄ sprÄng". MÄnga aspekter gjordes pÄ ett sÀtt som: "wow, jag gjorde nÄgot som fungerar". Helt ooptimerat och kvarlÀmnat i detta tillstÄnd frÀmst pÄ grund av liten erfarenhet av utveckling i Python. Jag kommer att fokusera pÄ de mest intressanta aspekterna av serverimplementationen i "koden".
Parser för XML-konfigurationsfil
AnvÀnder den standardmodul för Python xml.dom. Det verkar enkelt, men vid implementeringen saknades verkligen bra dokumentation och exempel pÄ nÀtet som anvÀnder denna modul.
tree = minidom.parse(gconfig["config_file"])
mconfig=tree.getElementsByTagName("mysql")
for elem in 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_basename"]=elem.getElementsByTagName("basename")[0].firstChild.data
dconfig=tree.getElementsByTagName("dhcpserver")
for elem in 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["dhcp_defaultMask"]=elem.getElementsByTagName("defaultMask")[0].firstChild.data
gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data
gconfig["dhcp_defaultDNS"]=elem.getElementsByTagName("defaultDNS")[0].firstChild.data
qconfig=tree.getElementsByTagName("query")
for elem in 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 in options:
node=elem.getElementsByTagName("option")
for options in node:
optionsMod.append(options.firstChild.data)MultitrÄdning
Konstigt nog Àr trÄdning i Python implementerat pÄ ett vÀldigt tydligt och enkelt sÀtt.
def PacketWork(data, addr):
...
# implementation of parsing the incoming packet and responding to it
...
while True:
data, addr = udp_socket.recvfrom(1024) # wait for UDP packet
thread = threading.Thread(target=PacketWork, args=(data, addr,)).start() # as soon as it arrives, we launch the previously defined function PacketWork in the background with parameters
while threading.active_count() > gconfig["dhcp_ThreadLimit"]:
time.sleep(1) # if the number of already launched threads exceeds the settings, wait until it decreasesMottagning/avsÀndning av DHCP-paket
För att fÄnga UDP-paket som gÄr genom nÀtverkskortet mÄste du "lyfta" en socket:
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) udp_socket.bind((gconfig["dhcp_host"], 67))
, dÀr flaggorna:
- AF_INET â betyder att adressformatet kommer vara IP: port. Det kan ocksĂ„ finnas AF_UNIX â dĂ€r adressen anges med filnamnet.
- SOCK_DGRAM â betyder att vi tar emot inte ett "rĂ„tt paket", utan ett som redan har passerat genom brandvĂ€ggen, och med en del av paketet bortskuret. Det innebĂ€r att vi fĂ„r bara UDP-paketet utan den "fysiska" komponenten av UDP-paketets omslag. Om du anvĂ€nder flaggan SOCK_RAW, mĂ„ste Ă€ven den "omslutningen" parsas.
Skickandet av paketet kan göras som broadcast:
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # vÀxlar socket till broadcast-lÀge
rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68)), sÄvÀl som till adressen "dÀr paketet kom ifrÄn":
udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # vÀxlar socket till "flera lyssnare"
rz=udp_socket.sendto(packetack, addr), dÀr SOL_SOCKET betyder "protokollnivÄ" för att stÀlla in alternativ,
, SO_BROADCAST Àr alternativet som gör att paketet skickas som "broadcast"
 , SO_REUSEADDR Àr alternativet som vÀxlar socket till lÀget "flera lyssnare". I teorin behövs det inte i detta fall, men pÄ en av serverarna i FreeBSD dÀr jag testade, fungerade inte koden utan detta alternativ.
Analys av DHCP-paketet
HĂ€r gillar jag verkligen Python. Det visar sig att det "ur lĂ„dan" gör att man ganska fritt kan hantera byte-kod. Det gör det vĂ€ldigt enkelt att konvertera till decimala vĂ€rden, strĂ€ngar och hex â det vill sĂ€ga det som vi faktiskt behöver för att förstĂ„ paketets struktur. Till exempel kan man fĂ„ en byte-intervall i HEX och i rena bytes:
res["xidhex"]=data[4:8].hex()
res["xidbyte"]=data[4:8], packa bytes i struktur:
res["flags"]=pack('BB',data[10],data[11])FÄ IP frÄn strukturen:
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"])
Detta Ă€r allt đ
KĂ€lla: habr.com
