DHCP+Mysql server u Pythonu

DHCP+Mysql server u Pythonu

Svrha ovog projekta je bila:

  • Učenje o DHCP-u na IPv4 mreži
  • Učenje Pythona (malo više nego od nule 😉)
  • zamjena servera DB2DHCP (moja viljuška), original ovdje, koji postaje sve teže sastaviti za novi OS. I ne sviđa mi se što je to binarnost koju nema načina da se "promijeni odmah"
  • dobijanje radnog DHCP servera sa mogućnošću odabira pretplatničke IP adrese koristeći pretplatnikov mac ili kombinaciju mac+port (opcija 82)
  • pisanje drugog bicikla (Oh! ovo je moja omiljena aktivnost)
  • primanje komentara o vašem klupskom ponašanju na Habrahabru (ili još bolje, pozivnica) 😉

Rezultat: radi 😉 Testirano na FreeBSD i Ubuntu OS. Teoretski, kod se može tražiti da radi pod bilo kojim OS-om, jer Čini se da u kodu nema posebnih veza.
Pažljivo! Ima još mnogo toga.

Link do repozitorija za amatere "dodirni živ".

Proces instaliranja, konfigurisanja i korišćenja rezultat "proučavanja hardvera" je mnogo niži, a onda i malo teorije o DHCP protokolu. Za mene. I za istoriju 😉

Malo teorije

Šta je DHCP

Ovo je mrežni protokol koji omogućava uređaju da sazna svoju IP adresu (i druge parametre kao što su gateway, DNS, itd.) od DHCP servera. Paketi se razmjenjuju korištenjem UDP protokola. Opći princip rada uređaja pri traženju mrežnih parametara je sljedeći:

  1. Uređaj (klijent) šalje UDP zahtjev za emitiranje (DHCPDISCOVER) širom mreže sa zahtjevom „pa, neka mi neko da IP adresu“. Štaviše, obično (ali ne uvijek) zahtjev se javlja sa porta 68 (izvor), a odredište je port 67 (odredište). Neki uređaji takođe šalju pakete sa porta 67. MAC adresa klijentskog uređaja je uključena unutar DHCPDISCOVER paketa.
  2. Svi DHCP serveri koji se nalaze na mreži (a može ih biti nekoliko) formiraju DHCPOFFER ponudu sa mrežnim postavkama za uređaj koji je poslao DHCPDISCOVER, a također ga emituje preko mreže. Identifikacija kome je ovaj paket namenjen zasniva se na MAC adresi klijenta datoj ranije u DHCPDISCOVER zahtevu.
  3. Klijent prihvata pakete sa predlozima mrežnih podešavanja, bira najatraktivniji (kriterijumi mogu biti različiti, na primer, vreme isporuke paketa, broj međuruta) i postavlja „službeni zahtev“ DHCPREQUEST sa mrežnim postavkama sa DHCP servera koji voli. U ovom slučaju, paket ide na određeni DHCP server.
  4. Server koji je primio DHCPREQUEST šalje paket u formatu DHCPACK, u kojem još jednom navodi mrežne postavke namijenjene ovom klijentu

DHCP+Mysql server u Pythonu

Pored toga, postoje DHCPINFORM paketi koji dolaze od klijenta, a čija je svrha da informišu DHCP server da je „klijent živ“ i da koristi izdate mrežne postavke. U implementaciji ovog servera, ovi paketi se zanemaruju.

Format paketa

Općenito, okvir Ethernet paketa izgleda otprilike ovako:

DHCP+Mysql server u Pythonu

U našem slučaju ćemo uzeti u obzir samo podatke direktno iz sadržaja UDP paketa, bez zaglavlja protokola OSI sloja, odnosno DHCP strukturu:

DHCPDISCOVER

Dakle, proces dobijanja IP adrese za uređaj počinje tako što DHCP klijent šalje zahtev za emitovanje sa porta 68 na 255.255.255.255:67. U ovaj paket klijent uključuje svoju MAC adresu, kao i šta tačno želi da primi od DHCP servera. Struktura paketa je opisana u donjoj tabeli.

DHCPDISCOVER tabela strukture paketa

Položaj u paketu
Ime vrijednosti
Primjer:
Uvod
Bajt
Objašnjenje

1
Zahtjev za pokretanje
1
Hex
1
Vrsta poruke. 1 - zahtjev od klijenta do servera, 2 - odgovor od servera do klijenta

2
Tip hardvera
1
Hex
1
Tip hardverske adrese, u ovom protokolu 1 - MAC

3
Dužina hardverske adrese
6
Hex
1
Dužina MAC adrese uređaja

4
hmelja
1
Hex
1
Broj međuputeva

5
ID transakcije
23:cf:de:1d
Hex
4
Jedinstveni identifikator transakcije. Generirano od strane klijenta na početku operacije zahtjeva

7
Second elapsed
0
Hex
4
Vrijeme u sekundama od početka procesa dobivanja adrese

9
Boot flags
0
Hex
2
Određene zastavice koje se mogu postaviti za označavanje parametara protokola

11
IP adresa klijenta
0.0.0.0
Gudački
4
IP adresa klijenta (ako postoji)

15
IP adresa vašeg klijenta
0.0.0.0
Gudački
4
IP adresa koju nudi server (ako je dostupna)

19
IP adresa sljedećeg servera
0.0.0.0
Gudački
4
IP adresa servera (ako je poznata)

23
Relay agent IP adresa
172.16.114.41
Gudački
4
IP adresa relejnog agenta (na primjer, prekidač)

27
MAC adresa klijenta
14:d6:4d:a7:c9:55
Hex
6
MAC adresa pošiljaoca paketa (klijenta)

31
Hardversko popunjavanje adrese klijenta
 
Hex
10
Rezervirano mjesto. Obično je ispunjen nulama

41
Ime servera hosta
 
Gudački
64
Ime DHCP servera. Obično se ne prenosi

105
Ime datoteke za pokretanje
 
Gudački
128
Ime datoteke na serveru koju koriste stanice bez diska prilikom pokretanja

235
Čarobni kolačići
63: 82: 53: 63
Hex
4
“Magični” broj, prema kojem, uklj. možete utvrditi da ovaj paket pripada DHCP protokolu

DHCP opcije. Može ići bilo kojim redom

236
Broj opcije
53
decembar
1
Opcija 53, koja specificira tip DHCP paketa

1 - DHCPDISCOVER
3 - DHCPREQUEST
2 - DHCPOFFER
5 - DHCPACK
8 - DHCPINFORM

 
Opciona dužina
1
decembar
1

 
Vrijednost opcije
1
decembar
1

 
Broj opcije
50
decembar
1
Koju IP adresu klijent želi da primi?

 
Opciona dužina
4
decembar
1

 
Vrijednost opcije
172.16.134.61
Gudački
4

 
Broj opcije
55
 
1
Mrežni parametri koje zahtijeva klijent. Sastav može varirati

01 — Mrežna maska
03 - Gateway
06 - DNS
oc — Ime hosta
0f - naziv mrežnog domena
1c - adresa zahtjeva za emitovanje (emitovanje)
42 - Ime TFTP servera
79 - Bezklasna statička ruta

 
Opciona dužina
8
 
1

 
Vrijednost opcije
01:03:06:0c:0f:1c:42:79
 
8

 
Broj opcije
82
decembar
 
Opcija 82, koja prenosi MAC adresu repetitornog uređaja i neke dodatne vrijednosti.

Najčešće je to port prekidača na kojem se pokreće krajnji DHCP klijent.Ova opcija sadrži dodatne parametre.Prvi bajt je broj „podopcije“, drugi je njena dužina, zatim njena vrijednost.

U ovom slučaju, u opciji 82, podopcije su ugniježđene:
ID kruga agenta = 00:04:00:01:00:04, gdje su zadnja dva bajta DHCP klijentski port s kojeg je stigao zahtjev

Agent Remote ID = 00:06:c8:be:19:93:11:48 - MAC adresa DHCP repetitora

 
Opciona dužina
18
decembar
 

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

 
Kraj paketa
255
decembar
1
255 simbolizira kraj paketa

DHCPOFFER

Čim server primi DHCPDISCOVER paket i ako vidi da može ponuditi klijentu nešto od traženog, onda za njega generiše odgovor - DHCPDISCOVER. Odgovor se šalje na port “odakle je došao”, putem emitovanja, jer u ovom trenutku, klijent još nema IP adresu, stoga može prihvatiti paket samo ako je poslan putem emitiranja. Klijent prepoznaje da je ovo paket za njega po svojoj MAC adresi unutar paketa, kao i po broju transakcije koji generiše u trenutku kreiranja prvog paketa.

DHCPOFFER tabela strukture paketa

Položaj u paketu
Naziv vrijednosti (uobičajeno)
Primjer:
Uvod
Bajt
Objašnjenje

1
Zahtjev za pokretanje
1
Hex
1
Vrsta poruke. 1 - zahtjev od klijenta do servera, 2 - odgovor od servera do klijenta

2
Tip hardvera
1
Hex
1
Tip hardverske adrese, u ovom protokolu 1 - MAC

3
Dužina hardverske adrese
6
Hex
1
Dužina MAC adrese uređaja

4
hmelja
1
Hex
1
Broj međuputeva

5
ID transakcije
23:cf:de:1d
Hex
4
Jedinstveni identifikator transakcije. Generirano od strane klijenta na početku operacije zahtjeva

7
Second elapsed
0
Hex
4
Vrijeme u sekundama od početka procesa dobivanja adrese

9
Boot flags
0
Hex
2
Određene zastavice koje se mogu postaviti za označavanje parametara protokola. U ovom slučaju, 0 znači Unicast tip zahtjeva

11
IP adresa klijenta
0.0.0.0
Gudački
4
IP adresa klijenta (ako postoji)

15
IP adresa vašeg klijenta
172.16.134.61
Gudački
4
IP adresa koju nudi server (ako je dostupna)

19
IP adresa sljedećeg servera
0.0.0.0
Gudački
4
IP adresa servera (ako je poznata)

23
Relay agent IP adresa
172.16.114.41
Gudački
4
IP adresa relejnog agenta (na primjer, prekidač)

27
MAC adresa klijenta
14:d6:4d:a7:c9:55
Hex
6
MAC adresa pošiljaoca paketa (klijenta)

31
Hardversko popunjavanje adrese klijenta
 
Hex
10
Rezervirano mjesto. Obično je ispunjen nulama

41
Ime servera hosta
 
Gudački
64
Ime DHCP servera. Obično se ne prenosi

105
Ime datoteke za pokretanje
 
Gudački
128
Ime datoteke na serveru koju koriste stanice bez diska prilikom pokretanja

235
Čarobni kolačići
63: 82: 53: 63
Hex
4
“Magični” broj, prema kojem, uklj. možete utvrditi da ovaj paket pripada DHCP protokolu

DHCP opcije. Može ići bilo kojim redom

236
Broj opcije
53
decembar
1
Opcija 53, koja definira tip DHCP 2 paketa - DHCPOFFER

 
Opciona dužina
1
decembar
1

 
Vrijednost opcije
2
decembar
1

 
Broj opcije
1
decembar
1
Opcija da se DHCP klijentu ponudi mrežna maska

 
Opciona dužina
4
decembar
1

 
Vrijednost opcije
255.255.224.0
Gudački
4

 
Broj opcije
3
decembar
1
Opcija da se DHCP klijentu ponudi podrazumevani gateway

 
Opciona dužina
4
decembar
1

 
Vrijednost opcije
172.16.12.1
Gudački
4

 
Broj opcije
6
decembar
1
Mogućnost ponude DHCP za DNS klijent

 
Opciona dužina
4
decembar
1

 
Vrijednost opcije
8.8.8.8
Gudački
4

 
Broj opcije
51
decembar
1
Životni vijek izdanih mrežnih parametara u sekundama, nakon čega ih DHCP klijent mora ponovo zatražiti

 
Opciona dužina
4
decembar
1

 
Vrijednost opcije
86400
decembar
4

 
Broj opcije
82
decembar
1
Opcija 82, ponavlja ono što je stiglo u DHCPDISCOVER

 
Opciona dužina
18
decembar
1

 
Vrijednost opcije
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
decembar
18

 
Kraj paketa
255
decembar
1
255 simbolizira kraj paketa

DHCPREQUEST

Nakon što klijent primi DHCPOFFER, formira paket koji traži mrežne parametre ne svim DHCP serverima na mreži, već samo jednom određenom, čija mu se DHCPOFFER ponuda najviše „sviđa”. Kriterijumi "sviđanja" mogu biti različiti i zavise od implementacije DHCP klijenta. Primalac zahtjeva je specificiran korištenjem MAC adrese DHCP servera. Takođe, DHCPREQUEST paket može poslati klijent bez prethodnog generisanja DHCPDISCOVER-a, ako je IP adresa servera već ranije dobijena.

DHCPREQUEST Tablica strukture paketa

Položaj u paketu
Naziv vrijednosti (uobičajeno)
Primjer:
Uvod
Bajt
Objašnjenje

1
Zahtjev za pokretanje
1
Hex
1
Vrsta poruke. 1 - zahtjev od klijenta do servera, 2 - odgovor od servera do klijenta

2
Tip hardvera
1
Hex
1
Tip hardverske adrese, u ovom protokolu 1 - MAC

3
Dužina hardverske adrese
6
Hex
1
Dužina MAC adrese uređaja

4
hmelja
1
Hex
1
Broj međuputeva

5
ID transakcije
23:cf:de:1d
Hex
4
Jedinstveni identifikator transakcije. Generirano od strane klijenta na početku operacije zahtjeva

7
Second elapsed
0
Hex
4
Vrijeme u sekundama od početka procesa dobivanja adrese

9
Boot flags
8000
Hex
2
Određene zastavice koje se mogu postaviti za označavanje parametara protokola. U ovom slučaju je postavljeno “emitovanje”.

11
IP adresa klijenta
0.0.0.0
Gudački
4
IP adresa klijenta (ako postoji)

15
IP adresa vašeg klijenta
172.16.134.61
Gudački
4
IP adresa koju nudi server (ako je dostupna)

19
IP adresa sljedećeg servera
0.0.0.0
Gudački
4
IP adresa servera (ako je poznata)

23
Relay agent IP adresa
172.16.114.41
Gudački
4
IP adresa relejnog agenta (na primjer, prekidač)

27
MAC adresa klijenta
14:d6:4d:a7:c9:55
Hex
6
MAC adresa pošiljaoca paketa (klijenta)

31
Hardversko popunjavanje adrese klijenta
 
Hex
10
Rezervirano mjesto. Obično je ispunjen nulama

41
Ime servera hosta
 
Gudački
64
Ime DHCP servera. Obično se ne prenosi

105
Ime datoteke za pokretanje
 
Gudački
128
Ime datoteke na serveru koju koriste stanice bez diska prilikom pokretanja

235
Čarobni kolačići
63: 82: 53: 63
Hex
4
“Magični” broj, prema kojem, uklj. možete utvrditi da ovaj paket pripada DHCP protokolu

DHCP opcije. Može ići bilo kojim redom

236
Broj opcije
53
decembar
3
Opcija 53, koja definira tip DHCP paketa 3 - DHCPREQUEST

 
Opciona dužina
1
decembar
1

 
Vrijednost opcije
3
decembar
1

 
Broj opcije
61
decembar
1
ID klijenta: 01 (za Ehernet) + MAC adresa klijenta

 
Opciona dužina
7
decembar
1

 
Vrijednost opcije
01:2c:ab:25:ff:72:a6
Hex
7

 
Broj opcije
60
decembar
 
"Identifikator klase dobavljača". U mom slučaju, prijavljuje verziju DHCP klijenta. Možda drugi uređaji vraćaju nešto drugačije. Windows na primjer prijavljuje MSFT 5.0

 
Opciona dužina
11
decembar
 

 
Vrijednost opcije
udhcp 0.9.8
Gudački
 

 
Broj opcije
55
 
1
Mrežni parametri koje zahtijeva klijent. Sastav može varirati

01 — Mrežna maska
03 - Gateway
06 - DNS
oc — Ime hosta
0f - naziv mrežnog domena
1c - adresa zahtjeva za emitovanje (emitovanje)
42 - Ime TFTP servera
79 - Bezklasna statička ruta

 
Opciona dužina
8
 
1

 
Vrijednost opcije
01:03:06:0c:0f:1c:42:79
 
8

 
Broj opcije
82
decembar
1
Opcija 82, ponavlja ono što je stiglo u DHCPDISCOVER

 
Opciona dužina
18
decembar
1

 
Vrijednost opcije
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
decembar
18

 
Kraj paketa
255
decembar
1
255 simbolizira kraj paketa

DHCPACK

Kao potvrdu „da, tako je, ovo je vaša IP adresa i neću je dati nikome drugome“ sa DHCP servera, paket u DHCPACK formatu sa servera na klijenta. Šalje se kao i drugi paketi. Iako, u kodu ispod za DHCP server implementiran u Python-u, za svaki slučaj, dupliram bilo koji zahtjev za emitiranje slanjem paketa na određeni IP klijenta, ako je već poznat. Štaviše, DHCP server uopšte ne brine da li je DHCPACK paket stigao do klijenta. Ako klijent ne primi DHCPACK, onda nakon nekog vremena jednostavno ponavlja DHCPREQUEST

Tablica strukture DHCPACK paketa

Položaj u paketu
Naziv vrijednosti (uobičajeno)
Primjer:
Uvod
Bajt
Objašnjenje

1
Zahtjev za pokretanje
2
Hex
1
Vrsta poruke. 1 - zahtjev od klijenta do servera, 2 - odgovor od servera do klijenta

2
Tip hardvera
1
Hex
1
Tip hardverske adrese, u ovom protokolu 1 - MAC

3
Dužina hardverske adrese
6
Hex
1
Dužina MAC adrese uređaja

4
hmelja
1
Hex
1
Broj međuputeva

5
ID transakcije
23:cf:de:1d
Hex
4
Jedinstveni identifikator transakcije. Generirano od strane klijenta na početku operacije zahtjeva

7
Second elapsed
0
Hex
4
Vrijeme u sekundama od početka procesa dobivanja adrese

9
Boot flags
8000
Hex
2
Određene zastavice koje se mogu postaviti za označavanje parametara protokola. U ovom slučaju je postavljeno “emitovanje”.

11
IP adresa klijenta
0.0.0.0
Gudački
4
IP adresa klijenta (ako postoji)

15
IP adresa vašeg klijenta
172.16.134.61
Gudački
4
IP adresa koju nudi server (ako je dostupna)

19
IP adresa sljedećeg servera
0.0.0.0
Gudački
4
IP adresa servera (ako je poznata)

23
Relay agent IP adresa
172.16.114.41
Gudački
4
IP adresa relejnog agenta (na primjer, prekidač)

27
MAC adresa klijenta
14:d6:4d:a7:c9:55
Hex
6
MAC adresa pošiljaoca paketa (klijenta)

31
Hardversko popunjavanje adrese klijenta
 
Hex
10
Rezervirano mjesto. Obično je ispunjen nulama

41
Ime servera hosta
 
Gudački
64
Ime DHCP servera. Obično se ne prenosi

105
Ime datoteke za pokretanje
 
Gudački
128
Ime datoteke na serveru koju koriste stanice bez diska prilikom pokretanja

235
Čarobni kolačići
63: 82: 53: 63
Hex
4
“Magični” broj, prema kojem, uklj. možete utvrditi da ovaj paket pripada DHCP protokolu

DHCP opcije. Može ići bilo kojim redom

236
Broj opcije
53
decembar
3
Opcija 53, koja definira tip DHCP paketa 5 - DHCPACK

 
Opciona dužina
1
decembar
1

 
Vrijednost opcije
5
decembar
1

 
Broj opcije
1
decembar
1
Opcija da se DHCP klijentu ponudi mrežna maska

 
Opciona dužina
4
decembar
1

 
Vrijednost opcije
255.255.224.0
Gudački
4

 
Broj opcije
3
decembar
1
Opcija da se DHCP klijentu ponudi podrazumevani gateway

 
Opciona dužina
4
decembar
1

 
Vrijednost opcije
172.16.12.1
Gudački
4

 
Broj opcije
6
decembar
1
Mogućnost ponude DHCP za DNS klijent

 
Opciona dužina
4
decembar
1

 
Vrijednost opcije
8.8.8.8
Gudački
4

 
Broj opcije
51
decembar
1
Životni vijek izdanih mrežnih parametara u sekundama, nakon čega ih DHCP klijent mora ponovo zatražiti

 
Opciona dužina
4
decembar
1

 
Vrijednost opcije
86400
decembar
4

 
Broj opcije
82
decembar
1
Opcija 82, ponavlja ono što je stiglo u DHCPDISCOVER

 
Opciona dužina
18
decembar
1

 
Vrijednost opcije
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
decembar
18

 
Kraj paketa
255
decembar
1
255 simbolizira kraj paketa

postavljanje

Instalacija se zapravo sastoji od instaliranja python modula neophodnih za rad. Pretpostavlja se da je MySQL već instaliran i konfigurisan.

FreeBSD

pkg instalirati python3 python3 -m osiguratipip pip3 instalirati mysql-konektor

Ubuntu

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

Kreiramo MySQL bazu podataka, učitavamo pydhcp.sql dump u nju i konfigurišemo konfiguracioni fajl.

Konfiguracija

Sva podešavanja servera su u xml datoteci. Referentni fajl:

1.0 0.0.0.0 255.255.255.255 192.168.0.71 8600 1 255.255.255.0 192.168.0.1 localhost test test pydhcp opcija_8.8.8.8_hex:sw_port82:1:20 option_22_hex:sw_port82:2:16 option_18_hex:sw_mac:82:26 40 odaberite ip,mask,router,dns od korisnika gdje je upper(mac)=upper('{option_3_AgentRemoteId_hex}') i upper(port)=upper('{option_1_AgentCircuitId_port_hex}') odaberite ip,mask,ruter,dns od korisnika gdje je upper(mac)=upper('{sw_mac}') i upper(port)=upper('{sw_port82}') odaberite ip,mask,router,dns od korisnika gdje je upper(mac)=upper('{ClientMacAddress}') ubaci u historiju (id,dt,mac,ip,comment) vrijednosti (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')

Sada detaljnije o oznakama:

Odjeljak dhcpserver opisuje osnovne postavke za pokretanje servera, i to:

  • host - koju IP adresu server sluša na portu 67
  • broadcast - koji IP je emitiranje za DHCPOFFER i DHCPACK
  • DHCPServer - koji je ip DHCP servera
  • LeaseTime vrijeme zakupa izdate IP adrese
  • ThreadLimit - koliko threadova radi istovremeno za obradu dolaznih UDP paketa na portu 67. Trebalo bi da pomogne u projektima visokog opterećenja 😉
  • defaultMask,defaultRouter,defaultDNS - šta se podrazumevano nudi pretplatniku ako je IP pronađen u bazi podataka, ali za njega nisu specificirani dodatni parametri

mysql odjeljak:

host, korisničko ime, lozinka, osnovno ime - sve govori za sebe. Približna struktura baze podataka je objavljena GitHub

Sekcija upita: ovdje su opisani zahtjevi za primanje PONUDE/ACK:

  • offer_count — broj linija sa zahtjevima koji vraćaju rezultat kao što je ip,mask,router,dns
  • ponuda_n — string upita. Ako je return prazan, izvršava se sljedeći zahtjev za ponudu
  • history_sql - upit koji upisuje, na primjer, u "historiju autorizacije" za pretplatnika

Zahtjevi mogu uključivati ​​bilo koje varijable iz odjeljka opcija ili opcije iz DHCP protokola.

Options section. Ovdje postaje zanimljivije. Ovdje možemo kreirati varijable koje možemo koristiti kasnije u odjeljku upita.

Na primjer:

option_82_hex:sw_port1:20:22

, ova komandna linija preuzima cijeli red koji je došao u opciji DHCP zahtjeva 82, u hex formatu, u rasponu od 20 do 22 bajta uključujući i stavlja ga u novu varijablu sw_port1 (prebaci port odakle je zahtjev došao)

option_82_hex:sw_mac:26:40

, definirajte varijablu sw_mac, uzimajući heksadecimalni iz raspona 26:40

Možete vidjeti sve moguće opcije koje se mogu koristiti u upitima pokretanjem servera sa -d prekidačem. Vidjet ćemo nešto poput ovog dnevnika:

--a DHCPINFORM paket je stigao na port 67, sa 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress0025224'MacAddress764'00'7 te': b'x91 5%"Jxd0d' , 'HType': 'Ethernet', 'HostName': b'x3xa5xe9xa8xa8xa43-x0.0.0.0fx5.0a', 'ReqListDNS': Tačno, 'ReqListDomainName': True, 'ReqListPerfowm'ReqL: True, 'ReqListPerfowm'ReqL': TrueListPerfowm'ReqL qListStaticRoute': Tačno, 'ReqListSubnetM ask': Tačno, 'ReqListVendorSpecInfo': 0025224, 'RequestedIpAddress': '764', 'Prodavac': b'MSFT 172.30.128.13', 'chaddr': '00ad00', 172.30.114.25 308 '6ad1. , 'zastavice': b'x82x12', 'giaddr': '12', 'gpoz': 53, 'hlen': 53, 'hmelj': 55, 'htype': 'MAC', 'magic_cookie' b'cx55Sc ', 'op': 'DHCPINFORM', 'option60': 60, 'option61': 61, 'option82': 82, 'option82': 12, 'option01': 06, 'option00': 04 option_00_byte': b'x01x00x06x02x08x00x06x00x1x9x2x82' b'x12010600040001000602080006001x589x2eXx82exb18xad', 'option_82_hex': '12 'option_01_len': 06 00, 'option_04_str': "b'x00x01x00x06x02x08x00x06x00x1x9x2x768x0.0.0.0x001eXx589exb2xad'", 'rezultat': False', '1sec 'siaddr': '06', 'sw_mac': '89e8eb3ad', 'sw_port897': '8', 'xidbyte': b'

U skladu s tim, možemo umotati bilo koju varijablu u {} i ona će se koristiti u SQL upitu.

Zabilježimo za historiju da je klijent dobio IP adresu:

DHCP+Mysql server u Pythonu

DHCP+Mysql server u Pythonu

Pokretanje servera

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

— d izlazni način konzole DEBUG
- c <ime datoteke> konfiguracijski fajl

Debriefing

A sada više detalja o implementaciji servera u Python-u. To je bol. Python je naučen u hodu. Mnogi momenti su napravljeni u stilu „vau, nekako sam uspeo“. Uopšte nije optimizovan i ostavljen u ovom obliku uglavnom zbog malog iskustva u razvoju Pythona. Zadržaću se na najzanimljivijim aspektima implementacije servera u "kodu".

Parser XML konfiguracijskih datoteka

Koristi se standardni Python modul xml.dom. Deluje jednostavno, ali tokom implementacije primetan je nedostatak jasne dokumentacije i primera na mreži koja koristi ovaj modul.

    tree = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") za elem u mconfig: gconfig["mysql_host"]=elem.getElementsByTagName("host")hida.ta. gconfig["mysql_username"]=elem.getElementsByTagName("username")[0].firstChild.data gconfig["mysql_password"]=elem.getElementsByTagName("password")[0].firstChild.config.damys gconfig["mysql_password"]=elem.getElementsByTagName("password")[0].firstChild. =elem.getElementsByTagName("basename")[0].firstChild.data dconfig=tree.getElementsByTagName("dhcpserver") za elem u dconfig: gconfig["broadcast"]=elem.getElementsByTagName")[0]. firstChild.data gconfig["dhcp_host"]=elem.getElementsByTagName("host")[0].firstChild.data gconfig["dhcp_LeaseTime"]=elem.getElementsByTagName("LeaseTime")[g.da"gconfig[0].firstChi[0]. dhcp_ThreadLimit"]=int(elem.getElementsByTagName("ThreadLimit")[0].firstChild.data) gconfig["dhcp_Server"]=elem.getElementsByTagName("DHCPServer")[0].tafirstChildsk_de.f. = elem.getelementsbytagname ("DefaultMask") [0] .firstchild.data gconfig ["dhcp_defaultrouter"] = elem.getelementsbytagname ("DefEltrouter") [0] .firstchild.data gconfig ["dhcp_defaultdns"] = ELEM.Getelementsbytagname (" defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("query") za elem u qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[1].firstChild.data za num.data. raspon(int(gconfig["offer_count"])): gconfig["offer_"+str(num+1)]=elem.getElementsByTagName("offer_"+str(num+0))[0].firstChild.data gconfig ["history_sql"]=elem.getElementsByTagName("history_sql")[XNUMX].firstChild.data options=tree.getElementsByTagName("options") za elem u opcijama: node=elem.getElementsByTagName("in node") za elem. : optionsMod.append(options.firstChild.data)

Multithreading

Čudno je da je višenitnost u Pythonu implementirana vrlo jasno i jednostavno.

def PacketWork(data,addr): ... # implementacija raščlanjivanja dolaznog paketa i odgovora na njega ... dok je True: data, addr = udp_socket.recvfrom(1024) # čeka se nit UDP paketa = threading.Thread( target=PacketWork , args=(data,addr,)).start() # kako je došlo - pokrećemo prethodno definiranu funkciju PacketWork u pozadini sa parametrima dok threading.active_count() >gconfig["dhcp_ThreadLimit"]: vrijeme. sleep(1) # ako je broj već pokrenutih više niti nego u postavkama, čekamo da ih bude manje

Primite/pošaljite DHCP paket

Da biste presreli UDP pakete koji dolaze preko mrežne kartice, potrebno je da "podignite" soket:

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

, gdje su zastave:

  • AF_INET - znači da će format adrese biti IP: port. Može postojati i AF_UNIX - gdje je adresa data imenom datoteke.
  • SOCK_DGRAM - znači da ne prihvatamo "sirov paket", već onaj koji je već prošao kroz zaštitni zid, i to sa delimično skraćenim paketom. One. primamo samo UDP paket bez “fizičke” komponente omotača UDP paketa. Ako koristite SOCK_RAW zastavicu, tada ćete također morati raščlaniti ovaj “omot”.

Slanje paketa može biti poput emitiranja:

                    udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) #prebacite utičnicu na način slanja emitiranja rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))

, i na adresu “odakle je došao paket”:

                        udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # prebacite soket u režim više slušalaca rz=udp_socket.sendto(packetack, addr)

, gdje SOL_SOCKET znači "nivo protokola" za postavljanje opcija,

, SO_BROADCAST opcija da je paket kacige “emitovan”

  Opcija ,SO_REUSEADDR prebacuje soket u režim “mnogo slušalaca”. U teoriji, u ovom slučaju je nepotrebno, ali na jednom od FreeBSD servera na kojem sam testirao kod nije radio bez ove opcije.

Parsiranje DHCP paketa

Ovdje mi se jako dopao Python. Ispostavilo se da vam omogućava da budete prilično fleksibilni sa bajt kodom. Omogućava da se vrlo lako prevede u decimalne vrijednosti, nizove i heksadecimalne - tj. to je ono što nam je zapravo potrebno da bismo razumjeli strukturu paketa. Tako, na primjer, možete dobiti raspon bajtova u HEX-u i samo bajtove:

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

, spakujte bajtove u strukturu:

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

Dobijte IP iz strukture:

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

I obrnuto:

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

To je sve za sada 😉

izvor: www.habr.com

Dodajte komentar