Pythonin oppiminen (hieman enemmän kuin tyhjästä 😉)
palvelimen vaihto DB2DHCP (haarukkani), alkuperäinen täällä, jonka kokoaminen uutta käyttöjärjestelmää varten on yhä vaikeampaa. Ja en pidä siitä, että se on binääri, jota ei voi "muuttaa juuri nyt"
toimivan DHCP-palvelimen hankkiminen, jolla on mahdollisuus valita tilaajan IP-osoite käyttämällä tilaajan mac- tai kytkimen mac+portti-yhdistelmää (Vaihtoehto 82)
toisen pyörän kirjoittaminen (Oh! tämä on suosikkiharrastukseni)
saada kommentteja klubikätyydestäsi Habrahabrissa (tai vielä parempaa, kutsu) 😉
Tulos: toimii 😉 Testattu FreeBSD:llä ja Ubuntu OS:llä. Teoriassa koodia voidaan pyytää toimimaan missä tahansa käyttöjärjestelmässä, koska Koodissa ei näytä olevan erityisiä sidoksia.
Huolellisesti! Paljon on vielä tulossa.
Linkki amatöörien arkistoon "kosketa elossa".
Asennus-, konfigurointi- ja käyttöprosessi "laitteiston tutkimisen" tuloksena on paljon alhaisempi, ja sitten vähän teoriaa DHCP-protokollasta. Itselleni. Ja historialle 😉
Vähän teoriaa
Mikä on DHCP
Tämä on verkkoprotokolla, jonka avulla laite voi selvittää IP-osoitteensa (ja muut parametrit, kuten yhdyskäytävä, DNS jne.) DHCP-palvelimelta. Paketit vaihdetaan UDP-protokollaa käyttäen. Laitteen yleinen toimintaperiaate verkkoparametreja pyydettäessä on seuraava:
Laite (asiakas) lähettää UDP-lähetyspyynnön (DHCPDISCOVER) koko verkkoon ja pyytää "no, anna joku IP-osoite". Lisäksi yleensä (mutta ei aina) pyyntö tulee portista 68 (lähde) ja kohde on portti 67 (kohde). Jotkut laitteet lähettävät paketteja myös portista 67. Asiakaslaitteen MAC-osoite sisältyy DHCPDISCOVER-pakettiin.
Kaikki verkossa sijaitsevat DHCP-palvelimet (ja niitä voi olla useita) muodostavat DHCPOFFER-tarjouksen verkkoasetuksineen DHCPDISCOVERin lähettäneelle laitteelle ja lähettävät sen myös verkon yli. Tunnistus siitä, kenelle tämä paketti on tarkoitettu, perustuu aiemmin DHCPDISCOVER-pyynnössä annettuun asiakkaan MAC-osoitteeseen.
Asiakas hyväksyy paketit verkkoasetusehdotuksineen, valitsee houkuttelevimman (kriteerit voivat olla erilaiset, esimerkiksi paketin toimitusaika, välireittien määrä) ja tekee "virallisen pyynnön" DHCPREQUEST verkkoasetuksista. DHCP-palvelimelta, josta se pitää. Tässä tapauksessa paketti menee tietylle DHCP-palvelimelle.
DHCPREQUEST-pyynnön vastaanottanut palvelin lähettää DHCPACK-muotoisen paketin, jossa se listaa jälleen tälle asiakkaalle tarkoitetut verkkoasetukset.
Lisäksi on olemassa asiakkaalta tulevia DHCPINFORM-paketteja, joiden tarkoituksena on ilmoittaa DHCP-palvelimelle, että "asiakas on elossa" ja käyttää annettuja verkkoasetuksia. Tämän palvelimen toteutuksessa nämä paketit ohitetaan.
Paketin muoto
Yleensä Ethernet-pakettikehys näyttää suunnilleen tältä:
Tässä tapauksessa otamme huomioon vain tiedot suoraan UDP-paketin sisällöstä ilman OSI-kerroksen protokollaotsikoita, nimittäin DHCP-rakennetta:
DHCPDISCOVER
Joten IP-osoitteen hankintaprosessi laitteelle alkaa siitä, että DHCP-asiakas lähettää yleislähetyspyynnön portista 68 kohtaan 255.255.255.255:67. Tässä paketissa asiakas sisältää MAC-osoitteensa sekä sen, mitä se tarkalleen haluaa vastaanottaa DHCP-palvelimelta. Pakkauksen rakenne on kuvattu alla olevassa taulukossa.
DHCPDISCOVER-pakettirakennetaulukko
Sijainti pakkauksessa
Arvon nimi
Esimerkki
ajatus
tavu
Selvennys
Vaihtoehto numero
50
joulukuu
1
Minkä IP-osoitteen asiakas haluaa saada?
Vaihtoehto pituus
4
joulukuu
1
Vaihtoehdon arvo
172.16.134.61
Linja
4
Vaihtoehto numero
55
1
Asiakkaan pyytämät verkkoparametrit. Koostumus voi vaihdella
01 — Verkkomaski
03 - Yhdyskäytävä
06 - DNS
oc — Isäntänimi
0f - verkkotunnuksen nimi
1c - lähetyspyynnön osoite (lähetys)
42 - TFTP-palvelimen nimi
79 - Luokkaton staattinen reitti
Vaihtoehto pituus
8
1
Vaihtoehdon arvo
01:03:06:0c:0f:1c:42:79
8
Vaihtoehto numero
82
joulukuu
Vaihtoehto 82, joka lähettää toistinlaitteen MAC-osoitteen ja joitain lisäarvoja.
Useimmiten tämä on kytkimen portti, jossa loppu DHCP-asiakas toimii.Tämä vaihtoehto sisältää lisäparametreja.Ensimmäinen tavu on "alioption" numero, toinen sen pituus, sitten sen arvo.
Tässä tapauksessa vaihtoehdossa 82 alivaihtoehdot on sisäkkäin:
Agent Circuit ID = 00:04:00:01:00:04, jossa kaksi viimeistä tavua ovat DHCP-asiakasportti, josta pyyntö tuli
Agent Remote ID = 00:06:c8:be:19:93:11:48 - DHCP-toistinlaitteen MAC-osoite
Vaihtoehto pituus
18
joulukuu
Vaihtoehdon arvo
01:06
00:04:00:01:00:04
02:08
00:06:c8:be:19:93:11:48
Hex
Paketin loppu
255
joulukuu
1
255 symboloi paketin loppua
DHCPOFFER
Heti kun palvelin vastaanottaa DHCPDISCOVER-paketin ja jos se näkee voivansa tarjota asiakkaalle jotain pyydetystä paketista, se luo siihen vastauksen - DHCPDISCOVER. Vastaus lähetetään porttiin "mistä se tuli", yleislähetyksenä, koska Tällä hetkellä asiakkaalla ei vielä ole IP-osoitetta, joten se voi hyväksyä paketin vain, jos se lähetetään yleislähetyksenä. Asiakas tunnistaa tämän paketin hänelle paketin sisällä olevasta MAC-osoitteestaan sekä tapahtumanumerosta, jonka hän luo ensimmäisen paketin luomisen yhteydessä.
DHCPOFFER-pakettirakennetaulukko
Sijainti pakkauksessa
Arvon nimi (yleinen)
Esimerkki
ajatus
tavu
Selvennys
Linja
64
DHCP-palvelimen nimi. Yleensä ei lähetetä
105
Käynnistystiedoston nimi
Linja
128
Tiedostonimi palvelimella, jota levyttömät asemat käyttävät käynnistettäessä
235
Maaginen eväste
63: 82: 53: 63
Hex
4
”Maginen” numero, jonka mukaan mm. voit määrittää, että tämä paketti kuuluu DHCP-protokollaan
DHCP-asetukset. Voi mennä missä järjestyksessä tahansa
236
Vaihtoehto numero
53
joulukuu
1
Vaihtoehto 53, joka määrittää DHCP 2 -pakettityypin - DHCPOFFER
Vaihtoehto pituus
1
joulukuu
1
Vaihtoehdon arvo
2
joulukuu
1
Vaihtoehto numero
1
joulukuu
1
Mahdollisuus tarjota DHCP-asiakkaalle verkkomaski
Vaihtoehto pituus
4
joulukuu
1
Vaihtoehdon arvo
255.255.224.0
Linja
4
Vaihtoehto numero
3
joulukuu
1
Mahdollisuus tarjota DHCP-asiakkaalle oletusyhdyskäytävä
Vaihtoehto pituus
4
joulukuu
1
Vaihtoehdon arvo
172.16.12.1
Linja
4
Vaihtoehto numero
6
joulukuu
1
Mahdollisuus tarjota DHCP DNS-asiakkaalle
Vaihtoehto pituus
4
joulukuu
1
Vaihtoehdon arvo
8.8.8.8
Linja
4
Vaihtoehto numero
51
joulukuu
1
Annettujen verkkoparametrien käyttöikä sekunneissa, jonka jälkeen DHCP-asiakkaan on pyydettävä niitä uudelleen
Vaihtoehto pituus
4
joulukuu
1
Vaihtoehdon arvo
86400
joulukuu
4
Vaihtoehto numero
82
joulukuu
1
Vaihtoehto 82, toistaa mitä tuli DHCPDISCOVERissa
Vaihtoehto pituus
18
joulukuu
1
Vaihtoehdon arvo
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
joulukuu
18
Paketin loppu
255
joulukuu
1
255 symboloi paketin loppua
DHCPREQUEST
Kun asiakas vastaanottaa DHCPOFFERin, hän muodostaa paketin, joka pyytää verkkoparametreja, ei kaikille verkon DHCP-palvelimille, vaan vain yhdelle tietylle, jonka DHCPOFFER-tarjouksesta hän "tykkäsi" eniten. "Tykkää"-kriteerit voivat olla erilaisia ja riippuvat asiakkaan DHCP-toteutuksesta. Pyynnön vastaanottaja määritetään käyttämällä DHCP-palvelimen MAC-osoitetta. Asiakas voi myös lähettää DHCPREQUEST-paketin generoimatta ensin DHCPDISCOVERia, jos palvelimen IP-osoite on jo hankittu aiemmin.
DHCPREQUEST-pakettirakennetaulukko
Sijainti pakkauksessa
Arvon nimi (yleinen)
Esimerkki
ajatus
tavu
Selvennys
Linja
64
DHCP-palvelimen nimi. Yleensä ei lähetetä
105
Käynnistystiedoston nimi
Linja
128
Tiedostonimi palvelimella, jota levyttömät asemat käyttävät käynnistettäessä
235
Maaginen eväste
63: 82: 53: 63
Hex
4
”Maginen” numero, jonka mukaan mm. voit määrittää, että tämä paketti kuuluu DHCP-protokollaan
DHCP-asetukset. Voi mennä missä järjestyksessä tahansa
236
Vaihtoehto numero
53
joulukuu
3
Vaihtoehto 53, joka määrittää DHCP-pakettityypin 3 - DHCPREQUEST
Vaihtoehto pituus
1
joulukuu
1
Vaihtoehdon arvo
3
joulukuu
1
Vaihtoehto numero
61
joulukuu
1
Asiakastunnus: 01 (Ehernetille) + asiakkaan MAC-osoite
Vaihtoehto pituus
7
joulukuu
1
Vaihtoehdon arvo
01:2c:ab:25:ff:72:a6
Hex
7
Vaihtoehto numero
60
joulukuu
"Toimittajan luokan tunniste". Minun tapauksessani se raportoi DHCP-asiakasversion. Ehkä muut laitteet palauttavat jotain erilaista. Esimerkiksi Windows raportoi MSFT 5.0:n
Vaihtoehto pituus
11
joulukuu
Vaihtoehdon arvo
udhcp 0.9.8
Linja
Vaihtoehto numero
55
1
Asiakkaan pyytämät verkkoparametrit. Koostumus voi vaihdella
01 — Verkkomaski
03 - Yhdyskäytävä
06 - DNS
oc — Isäntänimi
0f - verkkotunnuksen nimi
1c - lähetyspyynnön osoite (lähetys)
42 - TFTP-palvelimen nimi
79 - Luokkaton staattinen reitti
Vaihtoehto pituus
8
1
Vaihtoehdon arvo
01:03:06:0c:0f:1c:42:79
8
Vaihtoehto numero
82
joulukuu
1
Vaihtoehto 82, toistaa mitä tuli DHCPDISCOVERissa
Vaihtoehto pituus
18
joulukuu
1
Vaihtoehdon arvo
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4d:ec
joulukuu
18
Paketin loppu
255
joulukuu
1
255 symboloi paketin loppua
DHCPACK
Vahvistukseksi "kyllä, se on oikein, tämä on IP-osoitteesi, enkä anna sitä kenellekään muulle" DHCP-palvelimelta, DHCPACK-muodossa oleva paketti palvelimelta asiakkaalle palvelee. Se lähetetään lähetyksenä kuten muutkin paketit. Vaikka alla olevassa Pythonissa toteutetun DHCP-palvelimen koodissa kopioin varmuuden vuoksi minkä tahansa yleislähetyspyynnön lähettämällä paketin tiettyyn asiakkaan IP-osoitteeseen, jos se on jo tiedossa. Lisäksi DHCP-palvelin ei välitä ollenkaan, onko DHCPACK-paketti saavuttanut asiakkaan. Jos asiakas ei vastaanota DHCPACK:ia, hetken kuluttua se yksinkertaisesti toistaa DHCPREQUESTin
DHCPACK-pakettirakennetaulukko
Sijainti pakkauksessa
Arvon nimi (yleinen)
Esimerkki
ajatus
tavu
Selvennys
Luomme MySQL-tietokannan, lataamme siihen pydhcp.sql-vedostiedoston ja määritämme asetustiedoston.
kokoonpano
Kaikki palvelinasetukset ovat xml-tiedostossa. Viitetiedosto:
1.0 0.0.0.0 255.255.255.255 192.168.0.71 8600 1 255.255.255.0 192.168.0.1 paikallinen isäntä testata testata 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 valitse ip,mask,router,dns käyttäjiltä, joissa ylempi(mac)=upper('{option_3_AgentRemoteId_hex}') ja ylempi(port)=upper('{option_1_AgentCircuitId_port_hex}') valitse ip,mask,router,dns käyttäjiltä, joissa ylempi(mac)=upper('{sw_mac}') ja ylempi(port)=upper('{sw_port82}') valitse ip,mask,router,dns käyttäjiltä, joissa ylempi(mac)=upper('{ClientMacAddress}') lisää historiaan (id,dt,mac,ip,kommentti) arvot (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')
Nyt tarkemmin tunnisteista:
Dhcpserver-osiossa kuvataan perusasetukset palvelimen käynnistämiseksi, nimittäin:
isäntä - mitä IP-osoitetta palvelin kuuntelee portissa 67
broadcast - mikä IP on DHCPOFFER- ja DHCPACK-lähetys
DHCPServer - mikä on DHCP-palvelimen IP-osoite
Annetun IP-osoitteen LeaseTime-vuokra-aika
ThreadLimit - kuinka monta säiettä on käynnissä samanaikaisesti käsittelemään saapuvia UDP-paketteja portissa 67. Sen oletetaan auttavan korkean kuormituksen projekteissa 😉
defaultMask,defaultRouter,defaultDNS - mitä tilaajalle tarjotaan oletuksena, jos tietokannasta löytyy IP, mutta sille ei ole määritetty lisäparametreja
mysql-osio:
isäntä, käyttäjätunnus, salasana, perusnimi - kaikki puhuu puolestaan. Likimääräinen tietokantarakenne on julkaistu GitHub
Kyselyosio: TARJOUS/ACK-pyynnöt on kuvattu tässä:
offer_count — rivien määrä pyyntöillä, jotka palauttavat tuloksen, kuten ip,mask,router,dns
offer_n — kyselymerkkijono. Jos palautus on tyhjä, suorita seuraava tarjouspyyntö
history_sql - kysely, joka kirjoittaa esimerkiksi tilaajan "valtuutushistoriaan"
Pyynnöt voivat sisältää mitä tahansa muuttujia asetukset-osiosta tai vaihtoehtoja DHCP-protokollasta.
Asetukset-osio. Tästä se tulee mielenkiintoisemmaksi. Täällä voimme luoda muuttujia, joita voimme käyttää myöhemmin kyselyosassa.
Esimerkiksi:
option_82_hex:sw_port1:20:22
, tämä komentorivi ottaa koko rivin, joka tuli DHCP-pyyntövaihtoehdossa 82, heksadesimaalimuodossa, välillä 20–22 tavua ja sijoittaa sen uuteen muuttujaan sw_port1 (vaihtoportti, josta pyyntö tuli)
option_82_hex:sw_mac:26:40
, määritä sw_mac-muuttuja ottamalla heksadesimaaliarvo alueelta 26:40
Näet kaikki mahdolliset vaihtoehdot, joita voidaan käyttää kyselyissä käynnistämällä palvelimen -d-kytkimellä. Näemme jotain tämän kaltaista lokia:
Vastaavasti voimme kääriä minkä tahansa muuttujan {}:ään ja sitä käytetään SQL-kyselyssä.
Tallennetaan historiaan, että asiakas sai IP-osoitteen:
Palvelimen käynnistys
./pydhcpdb.py -d -c config.xml
— d konsolin lähtötila DEBUG
- c <tiedostonimi> määritystiedosto
jälkipuinti
Ja nyt lisätietoja palvelimen toteuttamisesta Pythonissa. Se on tuskaa. Python opittiin lennossa. Monet hetket on tehty tyyliin "vau, jotenkin sain sen toimimaan". Ei optimoitu ollenkaan ja jätettiin tähän muotoon lähinnä vähäisen Python-kehityskokemuksen vuoksi. Pysähdyn palvelimen toteutuksen mielenkiintoisimpiin puoliin "koodissa".
XML-määritystiedoston jäsentäjä
Käytössä on vakio Python-moduuli xml.dom. Se näyttää yksinkertaiselta, mutta toteutuksen aikana oli havaittavissa selkeän dokumentaation ja esimerkkien puute tätä moduulia käyttävästä verkossa.
Kummallista kyllä, monisäikeisyys Pythonissa on toteutettu erittäin selkeästi ja yksinkertaisesti.
def PacketWork(data,addr): ... # saapuvan paketin jäsentämisen ja siihen vastaamisen toteutus ... while True: data, addr = udp_socket.recvfrom(1024) # odottaa UDP-pakettia säie = threading.Thread( target=PacketWork , args=(data,addr,)).start() # sellaisena kuin se tuli - käynnistämme aiemmin määritellyn PacketWork-funktion taustalla parametreilla, kun threading.active_count() >gconfig["dhcp_ThreadLimit"]: aika. sleep(1) # jos numero On enemmän lankoja käynnissä kuin asetuksissa, odotamme kunnes niitä on vähemmän
Vastaanota/lähetä DHCP-paketti
Jotta voit siepata verkkokortin kautta tulevat UDP-paketit, sinun on "nostettava" liitäntä:
AF_INET - tarkoittaa, että osoitemuoto on IP: portti. Saattaa olla myös AF_UNIX - jossa osoite annetaan tiedoston nimellä.
SOCK_DGRAM - tarkoittaa, että emme hyväksy "raakapakettia", vaan sellaisen, joka on jo mennyt palomuurin läpi ja jossa on osittain leikattu paketti. Nuo. vastaanotamme vain UDP-paketin ilman UDP-pakettien kääreen "fyysistä" komponenttia. Jos käytät SOCK_RAW-lippua, sinun on myös jäsennettävä tämä "kääre".
udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # vaihda socket usean kuuntelijan tilaan rz=udp_socket.sendto(packettack, addr)
, jossa SOL_SOCKET tarkoittaa asetusvaihtoehtojen "protokollatasoa",
, SO_BROADCAST vaihtoehto, että kypäräpaketti on "lähetys"
,SO_REUSEADDR vaihtoehto vaihtaa socketin "monet kuuntelijat" -tilaan. Teoriassa se on tarpeeton tässä tapauksessa, mutta yhdessä FreeBSD-palvelimista, jolla testasin, koodi ei toiminut ilman tätä vaihtoehtoa.
DHCP-paketin jäsentäminen
Täällä pidin todella Pythonista. Osoittautuu, että laatikosta otettuna voit olla melko joustava tavukoodin kanssa. Mahdollistaa sen erittäin helposti kääntämisen desimaaliarvoiksi, merkkijonoiksi ja heksadesimaaliarvoiksi - ts. tämä on se, mitä meidän itse asiassa tarvitsemme ymmärtääksemme paketin rakenteen. Joten esimerkiksi voit saada useita tavuja HEX-muodossa ja vain tavuja: