Pelayan DHCP+Mysql dalam Python

Pelayan DHCP+Mysql dalam Python

Tujuan projek ini adalah:

  • Belajar tentang DHCP pada rangkaian IPv4
  • Belajar Python (lebih sedikit daripada dari awal 😉)
  • penggantian pelayan DB2DHCP (garpu saya), asli di sini, yang menjadi semakin sukar untuk dipasang untuk OS baharu. Dan saya tidak suka bahawa ia adalah binari yang tidak ada cara untuk "berubah sekarang"
  • mendapatkan pelayan DHCP yang berfungsi dengan keupayaan untuk memilih alamat IP pelanggan menggunakan gabungan mac pelanggan atau suis mac+port (Pilihan 82)
  • menulis basikal lain (Oh! ini aktiviti kegemaran saya)
  • menerima komen tentang sikap tangan kelab anda di Habrahabr (atau lebih baik lagi, jemputan) 😉

Keputusan: ia berfungsi 😉 Diuji pada FreeBSD dan OS Ubuntu. Secara teorinya, kod itu boleh diminta untuk berfungsi di bawah mana-mana OS, kerana Nampaknya tiada pengikatan khusus dalam kod itu.
Berhati-hati! Banyak lagi yang akan datang.

Pautan ke repositori untuk amatur "sentuh hidup".

Proses memasang, mengkonfigurasi dan menggunakan hasil "mempelajari perkakasan" adalah jauh lebih rendah, dan kemudian sedikit teori tentang protokol DHCP. Untuk diri saya sendiri. Dan untuk sejarah 😉

Sedikit teori

Apa itu DHCP

Ini ialah protokol rangkaian yang membolehkan peranti mengetahui alamat IPnya (dan parameter lain seperti get laluan, DNS, dll.) daripada pelayan DHCP. Paket ditukar menggunakan protokol UDP. Prinsip umum operasi peranti apabila meminta parameter rangkaian adalah seperti berikut:

  1. Peranti (klien) menghantar permintaan siaran UDP (DHCPDISCOVER) ke seluruh rangkaian dengan permintaan "baik, seseorang memberi saya alamat IP." Selain itu, biasanya (tetapi tidak selalu) permintaan berlaku dari port 68 (sumber), dan destinasi adalah port 67 (destinasi). Sesetengah peranti juga menghantar paket dari port 67. Alamat MAC peranti klien disertakan dalam pakej DHCPDISCOVER.
  2. Semua pelayan DHCP yang terletak pada rangkaian (dan mungkin terdapat beberapa daripadanya) membentuk tawaran DHCPOFFER dengan tetapan rangkaian untuk peranti yang menghantar DHCPDISCOVER, dan juga menyiarkannya melalui rangkaian. Pengenalpastian untuk siapa paket ini dimaksudkan adalah berdasarkan alamat MAC pelanggan yang diberikan sebelum ini dalam permintaan DHCPDISCOVER.
  3. Pelanggan menerima paket dengan cadangan untuk tetapan rangkaian, memilih yang paling menarik (kriteria mungkin berbeza, contohnya, masa penghantaran paket, bilangan laluan perantaraan), dan membuat "permintaan rasmi" DHCPREQUEST dengan tetapan rangkaian dari pelayan DHCP yang disukainya. Dalam kes ini, paket pergi ke pelayan DHCP tertentu.
  4. Pelayan yang menerima DHCPREQUEST menghantar paket format DHCPACK, di mana ia sekali lagi menyenaraikan tetapan rangkaian yang dimaksudkan untuk klien ini

Pelayan DHCP+Mysql dalam Python

Di samping itu, terdapat paket DHCPINFORM yang datang daripada klien, dan tujuannya adalah untuk memaklumkan pelayan DHCP bahawa "klien masih hidup" dan menggunakan tetapan rangkaian yang dikeluarkan. Dalam pelaksanaan pelayan ini, paket ini diabaikan.

Format pakej

Secara umum, bingkai paket Ethernet kelihatan seperti ini:

Pelayan DHCP+Mysql dalam Python

Dalam kes kami, kami hanya akan mempertimbangkan data secara langsung daripada kandungan paket UDP, tanpa pengepala protokol lapisan OSI, iaitu struktur DHCP:

DHCPDISCOVER

Jadi, proses mendapatkan alamat IP untuk peranti bermula dengan klien DHCP menghantar permintaan siaran dari port 68 ke 255.255.255.255:67. Dalam pakej ini, pelanggan menyertakan alamat MACnya, serta apa sebenarnya yang ingin diterima daripada pelayan DHCP. Struktur pakej diterangkan dalam jadual di bawah.

Jadual Struktur Paket DHCPDISCOVER

Kedudukan dalam pakej
Nama nilai
Contoh
Pengenalan
Byte
Penjelasan

1
Permintaan But
1
Hex
1
Jenis mesej. 1 - permintaan dari klien ke pelayan, 2 - respon dari pelayan ke klien

2
Jenis perkakasan
1
Hex
1
Jenis alamat perkakasan, dalam protokol ini 1 - MAC

3
Panjang alamat perkakasan
6
Hex
1
Panjang alamat MAC peranti

4
Hop
1
Hex
1
Bilangan laluan perantaraan

5
ID Transaksi
23:cf:de:1d
Hex
4
Pengecam transaksi yang unik. Dijana oleh pelanggan pada permulaan operasi permintaan

7
Kedua berlalu
0
Hex
4
Masa dalam beberapa saat dari permulaan proses mendapatkan alamat

9
Bendera but
0
Hex
2
Bendera tertentu yang boleh ditetapkan untuk menunjukkan parameter protokol

11
Alamat IP pelanggan
0.0.0.0
Garisan
4
Alamat IP pelanggan (jika ada)

15
Alamat IP pelanggan anda
0.0.0.0
Garisan
4
Alamat IP yang ditawarkan oleh pelayan (jika ada)

19
Alamat IP pelayan seterusnya
0.0.0.0
Garisan
4
Alamat IP pelayan (jika diketahui)

23
Alamat IP ejen geganti
172.16.114.41
Garisan
4
Alamat IP ejen geganti (contohnya, suis)

27
Alamat MAC pelanggan
14:d6:4d:a7:c9:55
Hex
6
Alamat MAC pengirim paket (pelanggan)

31
Pelapik alamat perkakasan pelanggan
 
Hex
10
Tempat duduk terpelihara. Biasanya diisi dengan sifar

41
Nama hos pelayan
 
Garisan
64
nama pelayan DHCP. Biasanya tidak dihantar

105
Nama fail but
 
Garisan
128
Nama fail pada pelayan yang digunakan oleh stesen tanpa cakera semasa but

235
Kuki ajaib
63: 82: 53: 63
Hex
4
Nombor "Sihir", yang mengikutnya, termasuk. anda boleh menentukan bahawa paket ini tergolong dalam protokol DHCP

Pilihan DHCP. Boleh pergi dalam apa jua pesanan

236
Nombor pilihan
53
disember
1
Pilihan 53, yang menentukan jenis paket DHCP

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

 
Panjang pilihan
1
disember
1

 
Nilai pilihan
1
disember
1

 
Nombor pilihan
50
disember
1
Apakah alamat IP yang ingin diterima oleh pelanggan?

 
Panjang pilihan
4
disember
1

 
Nilai pilihan
172.16.134.61
Garisan
4

 
Nombor pilihan
55
 
1
Parameter rangkaian diminta oleh pelanggan. Komposisi mungkin berbeza-beza

01 — Topeng rangkaian
03 - Gerbang
06 - DNS
oc — Nama hos
0f - nama domain rangkaian
1c - alamat permintaan siaran (siaran)
42 - Nama pelayan TFTP
79 - Laluan Statik Tanpa Kelas

 
Panjang pilihan
8
 
1

 
Nilai pilihan
01:03:06:0c:0f:1c:42:79
 
8

 
Nombor pilihan
82
disember
 
Pilihan 82, yang menghantar alamat MAC peranti pengulang dan beberapa nilai tambahan.

Selalunya, ini ialah port suis di mana klien DHCP akhir dijalankan. Pilihan ini mengandungi parameter tambahan. Bait pertama ialah nombor "suboption", yang kedua ialah panjangnya, kemudian nilainya.

Dalam kes ini, dalam pilihan 82, sub-pilihan bersarang:
ID Litar Agen = 00:04:00:01:00:04, di mana dua bait terakhir ialah port klien DHCP dari mana permintaan itu datang

ID Jauh Ejen = 00:06:c8:be:19:93:11:48 - Alamat MAC peranti pengulang DHCP

 
Panjang pilihan
18
disember
 

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

 
Akhir pakej
255
disember
1
255 melambangkan penghujung paket

DHCPOFFER

Sebaik sahaja pelayan menerima paket DHCPDISCOVER dan jika ia melihat bahawa ia boleh menawarkan pelanggan sesuatu daripada yang diminta, maka ia menjana respons untuknya - DHCPDISCOVER. Respons dihantar ke pelabuhan "dari mana ia datang", melalui siaran, kerana pada masa ini, pelanggan belum mempunyai alamat IP, oleh itu ia hanya boleh menerima paket jika ia dihantar melalui siaran. Pelanggan menyedari bahawa ini adalah pakej untuknya melalui alamat MACnya di dalam pakej, serta nombor transaksi yang dia hasilkan pada masa pakej pertama dibuat.

Jadual Struktur Paket DHCPOFFER

Kedudukan dalam pakej
Nama nilai (biasa)
Contoh
Pengenalan
Byte
Penjelasan

1
Permintaan But
1
Hex
1
Jenis mesej. 1 - permintaan dari klien ke pelayan, 2 - respon dari pelayan ke klien

2
Jenis perkakasan
1
Hex
1
Jenis alamat perkakasan, dalam protokol ini 1 - MAC

3
Panjang alamat perkakasan
6
Hex
1
Panjang alamat MAC peranti

4
Hop
1
Hex
1
Bilangan laluan perantaraan

5
ID Transaksi
23:cf:de:1d
Hex
4
Pengecam transaksi yang unik. Dijana oleh pelanggan pada permulaan operasi permintaan

7
Kedua berlalu
0
Hex
4
Masa dalam beberapa saat dari permulaan proses mendapatkan alamat

9
Bendera but
0
Hex
2
Bendera tertentu yang boleh ditetapkan untuk menunjukkan parameter protokol. Dalam kes ini, 0 bermaksud jenis permintaan Unicast

11
Alamat IP pelanggan
0.0.0.0
Garisan
4
Alamat IP pelanggan (jika ada)

15
Alamat IP pelanggan anda
172.16.134.61
Garisan
4
Alamat IP yang ditawarkan oleh pelayan (jika ada)

19
Alamat IP pelayan seterusnya
0.0.0.0
Garisan
4
Alamat IP pelayan (jika diketahui)

23
Alamat IP ejen geganti
172.16.114.41
Garisan
4
Alamat IP ejen geganti (contohnya, suis)

27
Alamat MAC pelanggan
14:d6:4d:a7:c9:55
Hex
6
Alamat MAC pengirim paket (pelanggan)

31
Pelapik alamat perkakasan pelanggan
 
Hex
10
Tempat duduk terpelihara. Biasanya diisi dengan sifar

41
Nama hos pelayan
 
Garisan
64
nama pelayan DHCP. Biasanya tidak dihantar

105
Nama fail but
 
Garisan
128
Nama fail pada pelayan yang digunakan oleh stesen tanpa cakera semasa but

235
Kuki ajaib
63: 82: 53: 63
Hex
4
Nombor "Sihir", yang mengikutnya, termasuk. anda boleh menentukan bahawa paket ini tergolong dalam protokol DHCP

Pilihan DHCP. Boleh pergi dalam apa jua pesanan

236
Nombor pilihan
53
disember
1
Pilihan 53, yang mentakrifkan jenis paket DHCP 2 - DHCPOFFER

 
Panjang pilihan
1
disember
1

 
Nilai pilihan
2
disember
1

 
Nombor pilihan
1
disember
1
Pilihan untuk menawarkan topeng rangkaian kepada klien DHCP

 
Panjang pilihan
4
disember
1

 
Nilai pilihan
255.255.224.0
Garisan
4

 
Nombor pilihan
3
disember
1
Pilihan untuk menawarkan klien DHCP gerbang lalai

 
Panjang pilihan
4
disember
1

 
Nilai pilihan
172.16.12.1
Garisan
4

 
Nombor pilihan
6
disember
1
Pilihan untuk menawarkan DHCP kepada klien DNS

 
Panjang pilihan
4
disember
1

 
Nilai pilihan
8.8.8.8
Garisan
4

 
Nombor pilihan
51
disember
1
Jangka hayat parameter rangkaian yang dikeluarkan dalam beberapa saat, selepas itu pelanggan DHCP mesti memintanya semula

 
Panjang pilihan
4
disember
1

 
Nilai pilihan
86400
disember
4

 
Nombor pilihan
82
disember
1
Pilihan 82, mengulangi apa yang terdapat dalam DHCPDISCOVER

 
Panjang pilihan
18
disember
1

 
Nilai pilihan
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4h:ec
disember
18

 
Akhir pakej
255
disember
1
255 melambangkan penghujung paket

DHCPREQUEST

Selepas pelanggan menerima DHCPOFFER, dia membentuk satu paket yang meminta parameter rangkaian bukan kepada semua pelayan DHCP pada rangkaian, tetapi hanya kepada satu pelayan tertentu, yang tawaran DHCPOFFER dia paling "sukai". Kriteria "suka" boleh berbeza dan bergantung pada pelaksanaan DHCP pelanggan. Penerima permintaan ditentukan menggunakan alamat MAC pelayan DHCP. Juga, paket DHCPREQUEST boleh dihantar oleh pelanggan tanpa menjana DHCPDISCOVER terlebih dahulu, jika alamat IP pelayan telah diperolehi sebelum ini.

Jadual Struktur Paket DHCPREQUEST

Kedudukan dalam pakej
Nama nilai (biasa)
Contoh
Pengenalan
Byte
Penjelasan

1
Permintaan But
1
Hex
1
Jenis mesej. 1 - permintaan dari klien ke pelayan, 2 - respon dari pelayan ke klien

2
Jenis perkakasan
1
Hex
1
Jenis alamat perkakasan, dalam protokol ini 1 - MAC

3
Panjang alamat perkakasan
6
Hex
1
Panjang alamat MAC peranti

4
Hop
1
Hex
1
Bilangan laluan perantaraan

5
ID Transaksi
23:cf:de:1d
Hex
4
Pengecam transaksi yang unik. Dijana oleh pelanggan pada permulaan operasi permintaan

7
Kedua berlalu
0
Hex
4
Masa dalam beberapa saat dari permulaan proses mendapatkan alamat

9
Bendera but
8000
Hex
2
Bendera tertentu yang boleh ditetapkan untuk menunjukkan parameter protokol. Dalam kes ini, "siaran" ditetapkan

11
Alamat IP pelanggan
0.0.0.0
Garisan
4
Alamat IP pelanggan (jika ada)

15
Alamat IP pelanggan anda
172.16.134.61
Garisan
4
Alamat IP yang ditawarkan oleh pelayan (jika ada)

19
Alamat IP pelayan seterusnya
0.0.0.0
Garisan
4
Alamat IP pelayan (jika diketahui)

23
Alamat IP ejen geganti
172.16.114.41
Garisan
4
Alamat IP ejen geganti (contohnya, suis)

27
Alamat MAC pelanggan
14:d6:4d:a7:c9:55
Hex
6
Alamat MAC pengirim paket (pelanggan)

31
Pelapik alamat perkakasan pelanggan
 
Hex
10
Tempat duduk terpelihara. Biasanya diisi dengan sifar

41
Nama hos pelayan
 
Garisan
64
nama pelayan DHCP. Biasanya tidak dihantar

105
Nama fail but
 
Garisan
128
Nama fail pada pelayan yang digunakan oleh stesen tanpa cakera semasa but

235
Kuki ajaib
63: 82: 53: 63
Hex
4
Nombor "Sihir", yang mengikutnya, termasuk. anda boleh menentukan bahawa paket ini tergolong dalam protokol DHCP

Pilihan DHCP. Boleh pergi dalam apa jua pesanan

236
Nombor pilihan
53
disember
3
Pilihan 53, yang mentakrifkan jenis paket DHCP 3 - DHCPREQUEST

 
Panjang pilihan
1
disember
1

 
Nilai pilihan
3
disember
1

 
Nombor pilihan
61
disember
1
ID Pelanggan: 01 (untuk Ehernet) + alamat MAC pelanggan

 
Panjang pilihan
7
disember
1

 
Nilai pilihan
01:2c:ab:25:ff:72:a6
Hex
7

 
Nombor pilihan
60
disember
 
"Pengecam kelas vendor". Dalam kes saya, ia melaporkan versi klien DHCP. Mungkin peranti lain mengembalikan sesuatu yang berbeza. Windows misalnya melaporkan MSFT 5.0

 
Panjang pilihan
11
disember
 

 
Nilai pilihan
udhcp 0.9.8
Garisan
 

 
Nombor pilihan
55
 
1
Parameter rangkaian diminta oleh pelanggan. Komposisi mungkin berbeza-beza

01 — Topeng rangkaian
03 - Gerbang
06 - DNS
oc — Nama hos
0f - nama domain rangkaian
1c - alamat permintaan siaran (siaran)
42 - Nama pelayan TFTP
79 - Laluan Statik Tanpa Kelas

 
Panjang pilihan
8
 
1

 
Nilai pilihan
01:03:06:0c:0f:1c:42:79
 
8

 
Nombor pilihan
82
disember
1
Pilihan 82, mengulangi apa yang terdapat dalam DHCPDISCOVER

 
Panjang pilihan
18
disember
1

 
Nilai pilihan
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4h:ec
disember
18

 
Akhir pakej
255
disember
1
255 melambangkan penghujung paket

DHCPACK

Sebagai pengesahan bahawa "ya, betul, ini adalah alamat IP anda, dan saya tidak akan memberikannya kepada orang lain" daripada pelayan DHCP, satu paket dalam format DHCPACK dari pelayan kepada pelayan pelanggan. Ia dihantar siaran sama seperti paket lain. Walaupun, dalam kod di bawah untuk pelayan DHCP yang dilaksanakan dalam Python, untuk berjaga-jaga, saya menduplikasi sebarang permintaan penyiaran dengan menghantar paket ke IP klien tertentu, jika ia sudah diketahui. Lebih-lebih lagi, pelayan DHCP tidak peduli sama ada paket DHCPACK telah sampai ke pelanggan. Jika pelanggan tidak menerima DHCPACK, maka selepas beberapa ketika ia hanya mengulangi DHCPREQUEST

Jadual Struktur Paket DHCPACK

Kedudukan dalam pakej
Nama nilai (biasa)
Contoh
Pengenalan
Byte
Penjelasan

1
Permintaan But
2
Hex
1
Jenis mesej. 1 - permintaan dari klien ke pelayan, 2 - respon dari pelayan ke klien

2
Jenis perkakasan
1
Hex
1
Jenis alamat perkakasan, dalam protokol ini 1 - MAC

3
Panjang alamat perkakasan
6
Hex
1
Panjang alamat MAC peranti

4
Hop
1
Hex
1
Bilangan laluan perantaraan

5
ID Transaksi
23:cf:de:1d
Hex
4
Pengecam transaksi yang unik. Dijana oleh pelanggan pada permulaan operasi permintaan

7
Kedua berlalu
0
Hex
4
Masa dalam beberapa saat dari permulaan proses mendapatkan alamat

9
Bendera but
8000
Hex
2
Bendera tertentu yang boleh ditetapkan untuk menunjukkan parameter protokol. Dalam kes ini, "siaran" ditetapkan

11
Alamat IP pelanggan
0.0.0.0
Garisan
4
Alamat IP pelanggan (jika ada)

15
Alamat IP pelanggan anda
172.16.134.61
Garisan
4
Alamat IP yang ditawarkan oleh pelayan (jika ada)

19
Alamat IP pelayan seterusnya
0.0.0.0
Garisan
4
Alamat IP pelayan (jika diketahui)

23
Alamat IP ejen geganti
172.16.114.41
Garisan
4
Alamat IP ejen geganti (contohnya, suis)

27
Alamat MAC pelanggan
14:d6:4d:a7:c9:55
Hex
6
Alamat MAC pengirim paket (pelanggan)

31
Pelapik alamat perkakasan pelanggan
 
Hex
10
Tempat duduk terpelihara. Biasanya diisi dengan sifar

41
Nama hos pelayan
 
Garisan
64
nama pelayan DHCP. Biasanya tidak dihantar

105
Nama fail but
 
Garisan
128
Nama fail pada pelayan yang digunakan oleh stesen tanpa cakera semasa but

235
Kuki ajaib
63: 82: 53: 63
Hex
4
Nombor "Sihir", yang mengikutnya, termasuk. anda boleh menentukan bahawa paket ini tergolong dalam protokol DHCP

Pilihan DHCP. Boleh pergi dalam apa jua pesanan

236
Nombor pilihan
53
disember
3
Pilihan 53, yang mentakrifkan jenis paket DHCP 5 - DHCPACK

 
Panjang pilihan
1
disember
1

 
Nilai pilihan
5
disember
1

 
Nombor pilihan
1
disember
1
Pilihan untuk menawarkan topeng rangkaian kepada klien DHCP

 
Panjang pilihan
4
disember
1

 
Nilai pilihan
255.255.224.0
Garisan
4

 
Nombor pilihan
3
disember
1
Pilihan untuk menawarkan klien DHCP gerbang lalai

 
Panjang pilihan
4
disember
1

 
Nilai pilihan
172.16.12.1
Garisan
4

 
Nombor pilihan
6
disember
1
Pilihan untuk menawarkan DHCP kepada klien DNS

 
Panjang pilihan
4
disember
1

 
Nilai pilihan
8.8.8.8
Garisan
4

 
Nombor pilihan
51
disember
1
Jangka hayat parameter rangkaian yang dikeluarkan dalam beberapa saat, selepas itu pelanggan DHCP mesti memintanya semula

 
Panjang pilihan
4
disember
1

 
Nilai pilihan
86400
disember
4

 
Nombor pilihan
82
disember
1
Pilihan 82, mengulangi apa yang terdapat dalam DHCPDISCOVER

 
Panjang pilihan
18
disember
1

 
Nilai pilihan
01:08:00:06:00
01:01:00:00:01
02:06:00:03:0f
26:4h:ec
disember
18

 
Akhir pakej
255
disember
1
255 melambangkan penghujung paket

Pemasangan

Pemasangan sebenarnya terdiri daripada memasang modul python yang diperlukan untuk kerja. Adalah diandaikan bahawa MySQL telah dipasang dan dikonfigurasikan.

FreeBSD

pkg pasang python3 python3 -m ensurepip pip3 pasang mysql-connector

Ubuntu

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

Kami mencipta pangkalan data MySQL, memuat naik dump pydhcp.sql ke dalamnya dan mengkonfigurasi fail konfigurasi.

Konfigurasi

Semua tetapan pelayan berada dalam fail xml. Fail rujukan:

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 ujian ujian 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 pilih ip,mask,router,dns daripada pengguna di mana upper(mac)=upper('{option_3_AgentRemoteId_hex}') dan upper(port)=upper('{option_1_AgentCircuitId_port_hex}') pilih ip,mask,router,dns daripada pengguna di mana upper(mac)=upper('{sw_mac}') dan upper(port)=upper('{sw_port82}') pilih ip,mask,router,dns daripada pengguna di mana upper(mac)=upper('{ClientMacAddress}') masukkan ke dalam nilai sejarah (id,dt,mac,ip,comment) (null,now(),'{ClientMacAddress}','{RequestedIpAddress}','DHCPACK/INFORM')

Sekarang dengan lebih terperinci mengenai tag:

Bahagian dhcpserver menerangkan tetapan asas untuk memulakan pelayan, iaitu:

  • hos - alamat IP yang didengari pelayan pada port 67
  • broadcast - ip yang manakah adalah siaran untuk DHCPOFFER dan DHCPACK
  • DHCPServer - apakah ip pelayan DHCP
  • Masa pajakan masa pajakan alamat IP yang dikeluarkan
  • ThreadLimit - berapa banyak benang berjalan serentak untuk memproses paket UDP masuk pada port 67. Ia sepatutnya membantu pada projek beban tinggi 😉
  • defaultMask,defaultRouter,defaultDNS - apa yang ditawarkan kepada pelanggan secara lalai jika IP ditemui dalam pangkalan data, tetapi parameter tambahan tidak dinyatakan untuknya

bahagian mysql:

hos, nama pengguna, kata laluan, nama asas - semuanya bercakap untuk dirinya sendiri. Struktur pangkalan data anggaran disiarkan pada GitHub

Bahagian pertanyaan: permintaan untuk menerima TAWARAN/ACK diterangkan di sini:

  • offer_count — bilangan baris dengan permintaan yang mengembalikan hasil seperti ip,mask,router,dns
  • offer_n — rentetan pertanyaan. Jika pulangan kosong, maka laksanakan permintaan tawaran berikut
  • history_sql - pertanyaan yang menulis, sebagai contoh, kepada "sejarah kebenaran" untuk pelanggan

Permintaan boleh termasuk sebarang pembolehubah dari bahagian pilihan atau pilihan daripada protokol DHCP.

Bahagian pilihan. Di sinilah ia menjadi lebih menarik. Di sini kita boleh mencipta pembolehubah yang boleh kita gunakan kemudian dalam bahagian pertanyaan.

Sebagai contoh:

option_82_hex:sw_port1:20:22

, baris arahan ini mengambil keseluruhan baris yang datang dalam pilihan permintaan DHCP 82, dalam format hex, dalam julat dari 20 hingga 22 bait termasuk dan meletakkannya dalam pembolehubah baharu sw_port1 (tukar port dari tempat permintaan itu datang)

option_82_hex:sw_mac:26:40

, tentukan pembolehubah sw_mac, mengambil hex daripada julat 26:40

Anda boleh melihat semua kemungkinan pilihan yang boleh digunakan dalam pertanyaan dengan memulakan pelayan dengan suis -d. Kita akan melihat sesuatu seperti log ini:

--paket DHCPINFORM tiba pada port 67, daripada 0025224ad764 , b'x91xa5xe0xa3xa5xa9-x8fx8a' , ('172.30.114.25', 68) {'ClientMacAddress': '0025224'764address00x7', '%'ClientMacAddress': '91'5ad0x3d5 9h' , ' HType': 'Ethernet', 'HostName': b'x8xa8xe43xa0.0.0.0xa5.0xa0025224-x764fx172.30.128.13a', 'ReqListDNS': True, 'ReqListRomainName': True, 'ReqListPerfowmRouterDiscover': True, 'L TruistRouterReq': True, 'ReqListRouterReq': True, 'ReqListRouterReq': 'ReqListSubnetM ask ': True, 'ReqListVendorSpecInfo': 00, 'RequestedIpAddress': '00', 'Vendor': b'MSFT 172.30.114.25', 'chaddr': '308ad6', '1': '82' , 'bendera': b'x12x12', 'giaddr': '53', 'gpoz': 53, 'hlen': 55, 'hops': 55, 'htype': 'MAC', 'magic_cookie': b'cx60Sc ', 'op': 'DHCPINFORM', 'option60': 61, 'option61': 82, 'option82': 82, 'option12': 01, 'option06': 00, 'option04': 00, ' option_01_byte': b'x00x06x02x08x00x06x00x1x9x2x82x12010600040001000602080006001' b'x589x2x82eXx18exb82xad', 'option_12_hex': '01 tion_06_len': 00 04, 'option_00_str': "b'x01x00x06x02x08x00x06x00x1x9x2x768x0.0.0.0x001x589eXx2exb1xad'", 'hasil': Salah, 'secs,' 'siaddr': '06', 'sw_mac': '89e8eb3ad', 'sw_port897': '8', 'xidbyte': b'

Sehubungan itu, kita boleh membungkus sebarang pembolehubah dalam {} dan ia akan digunakan dalam pertanyaan SQL.

Marilah kita merekodkan sejarah bahawa klien menerima alamat IP:

Pelayan DHCP+Mysql dalam Python

Pelayan DHCP+Mysql dalam Python

Memulakan pelayan

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

— d mod keluaran konsol DEBUG
- c <nama fail> fail konfigurasi

Debriefing

Dan kini butiran lanjut tentang melaksanakan pelayan dalam Python. Ia adalah satu kesakitan. Python dipelajari dengan cepat. Banyak detik dibuat dalam gaya "wow, entah bagaimana saya berjaya melakukannya." Tidak dioptimumkan sama sekali, dan ditinggalkan dalam bentuk ini terutamanya disebabkan oleh sedikit pengalaman dalam pembangunan Python. Saya akan memikirkan aspek yang paling menarik dalam pelaksanaan pelayan dalam "kod".

Penghurai fail konfigurasi XML

Modul Python standard xml.dom digunakan. Nampaknya mudah, tetapi semasa pelaksanaan terdapat kekurangan dokumentasi dan contoh yang jelas pada rangkaian menggunakan modul ini.

    tree = minidom.parse(gconfig["config_file"]) mconfig=tree.getElementsByTagName("mysql") untuk elem dalam 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") untuk elem dalam 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["skp"_default =elem.getElementsByTagName("defaultMask")[0].firstChild.data gconfig["dhcp_defaultRouter"]=elem.getElementsByTagName("defaultRouter")[0].firstChild.data gconfig["dhcp_defaultDNS"]=elem.getNameElementsBy defaultDNS")[0].firstChild.data qconfig=tree.getElementsByTagName("query") untuk elem dalam qconfig: gconfig["offer_count"]=elem.getElementsByTagName("offer_count")[0].firstChild.data untuk num in julat(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") untuk elem dalam pilihan: node=elem.getElementsByTagName("option") untuk pilihan dalam nod : optionsMod.append(options.firstChild.data)

Multithreading

Anehnya, multithreading dalam Python dilaksanakan dengan sangat jelas dan ringkas.

def PacketWork(data,addr): ... # pelaksanaan menghuraikan paket masuk dan bertindak balas kepadanya ... manakala True: data, addr = udp_socket.recvfrom(1024) # menunggu benang paket UDP = threading.Thread( target=PacketWork , args=(data,addr,)).start() # semasa ia datang - kami melancarkan fungsi PacketWork yang ditakrifkan sebelum ini di latar belakang dengan parameter semasa threading.active_count() >gconfig["dhcp_ThreadLimit"]: masa. sleep(1) # jika bilangan Terdapat lebih banyak utas yang sudah berjalan daripada dalam tetapan, kami tunggu sehingga bilangannya lebih sedikit

Terima/hantar paket DHCP

Untuk memintas paket UDP yang datang melalui kad rangkaian, anda perlu "menaikkan" soket:

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

, di mana bendera adalah:

  • AF_INET - bermakna format alamat akan menjadi IP: port. Mungkin juga terdapat AF_UNIX - di mana alamat diberikan oleh nama fail.
  • SOCK_DGRAM - bermakna kami tidak menerima "paket mentah", tetapi yang telah melalui tembok api, dan dengan paket yang dipangkas separa. Itu. kami hanya menerima paket UDP tanpa komponen "fizikal" pembungkus paket UDP. Jika anda menggunakan bendera SOCK_RAW, maka anda juga perlu menghuraikan "pembungkus" ini.

Menghantar paket boleh menjadi seperti siaran:

                    udp_socket.setsockopt(soket.SOL_SOCKET, socket.SO_BROADCAST, 1) #tukar soket kepada mod siaran rz=udp_socket.sendto(packetack, (gconfig["broadcast"],68))

, dan ke alamat "dari mana pakej itu datang":

                        udp_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # tukar soket kepada mod berbilang pendengar rz=udp_socket.sendto(packetack, addr)

, di mana SOL_SOCKET bermaksud "tahap protokol" untuk pilihan tetapan,

, SO_BROADCAST pilihan bahawa pakej topi keledar adalah "disiarkan"

  Pilihan SO_REUSEADDR menukar soket kepada mod "banyak pendengar". Secara teori, ia tidak perlu dalam kes ini, tetapi pada salah satu pelayan FreeBSD yang saya uji, kod itu tidak berfungsi tanpa pilihan ini.

Menghuraikan paket DHCP

Di sinilah saya sangat menyukai Python. Ternyata di luar kotak ia membolehkan anda menjadi agak fleksibel dengan bytecode. Membenarkan ia diterjemahkan dengan mudah ke dalam nilai perpuluhan, rentetan dan heks - i.e. inilah yang sebenarnya kita perlukan untuk memahami struktur pakej. Jadi, sebagai contoh, anda boleh mendapatkan julat bait dalam HEX dan hanya bait:

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

, bungkus bait ke dalam struktur:

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

Dapatkan IP daripada struktur:

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

Dan begitu juga sebaliknya:

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

Itu sahaja buat masa ini 😉

Sumber: www.habr.com

Tambah komen