
Saya suka mengotomatiskan proses dan menulis sepeda motor saya sendiri untuk mempelajari materi ini atau itu. Tujuan baru saya adalah server DHCP, yang akan mengeluarkan alamat di jaringan kecil sehingga konfigurasi awal peralatan dapat dibuat.
Pada artikel ini saya akan berbicara sedikit tentang protokol DHCP dan beberapa seluk-beluk dari bash.
Hasil akhir
Mari kita mulai dari akhir, sehingga jelas apa yang kita perjuangkan.
Demonstrasi kerja:

Repositori dengan skrip:
firemoon777 / bash-dhcp-serverMasalah awal
Konfigurasi yang saya butuhkan dilakukan dengan cara ini: kita terhubung langsung melalui kabel twisted pair ke peralatan, mengeluarkan alamat sementara melalui DHCP, dan mengkonfigurasinya dengan skrip yang sudah dibuat. Dan sepuluh hingga dua puluh kali berturut-turut.
Bagi banyak orang, server-isc-dhcp yang terkenal melakukan tugasnya dengan sempurna, tetapi, sayangnya, itu tidak memberi tahu skrip saya bahwa alamat tersebut dikeluarkan, jadi Anda harus memblokir eksekusi sampai alamat tersebut dikeluarkan.
Solusinya, tampaknya, adalah di permukaan: ping sampai biru di wajah, sampai peralatan merespons:
while ! ping -c1 -W1 "$DHCP" | grep -q "time=" do echo "Waiting for $DHCP..." done
Tetapi keputusan ini jelas tidak memiliki petualangan.
Bagian teoretis
Memperoleh alamat dengan satu server DHCP
Protokol DHCP berfungsi melalui UDP pada port 67 dan 68. Server selalu berfungsi hanya pada 67, dan klien hanya pada 68. Karena klien tidak memiliki alamat (memiliki alamat 0.0.0.0), paket DHCP disiarkan. Yaitu klien selalu mengirim paket ke alamat 255.255.255.255:67 dari alamat 0.0.0.0:68, dan server mengirim dari alamatnya: 67 ke alamat 255.255.255.255.255:68.
Klien
menerima alamat dalam empat paket (
DORA ):
- Klien mencari tahu di mana server DHCP ( D iscover)
- Server merespons dan menawarkan alamatnya ( O ffer)
- Klien meminta alamat yang diusulkan dari server tertentu ( R equest)
- Server setuju dan mengeluarkan alamat ( A ck)
Secara visual, skema dapat direpresentasikan sebagai berikut:

Memperoleh alamat dengan beberapa server DHCP
Ketika klien mengirim Discover, semua server yang dapat mendengar mengirim Penawaran mereka ke klien. Tetapi klien harus memilih satu. Pilihan klien diumumkan dalam pesan Permintaan dengan opsi 54 (server DHCP), yang berisi alamat IP dari server DHCP yang disukai. Meskipun Permintaan juga dikirimkan kepada semua orang di jaringan, hanya server DHCP yang IP-nya ditentukan dalam opsi 54 yang akan merespons.

Isi paket DHCP
Paket DHCP terdiri dari dua bagian: konstanta, ukuran 236 byte, dan variabel yang membawa opsi (Opsi DHCP).
Tabel dengan semua bidang paket DHCP dari WikipediaLapangan | Deskripsi | Panjang (dalam byte) |
---|
op
| Jenis pesan. Misalnya, dapat mengambil nilai: BOOTREQUEST (0x01, permintaan dari klien ke server) dan BOOTREPLY (0x02, respons dari server ke klien).
| 1
|
htype
| Jenis alamat perangkat keras. Nilai yang valid untuk bidang ini didefinisikan dalam RFC 1700 Assigned Numbers. Misalnya, untuk alamat MAC Ethernet, bidang ini disetel ke 0x01.
| 1
|
hlen
| Panjang alamat perangkat keras dalam byte. Alamat MAC Ethernet adalah 0x06.
| 1
|
hop
| Jumlah router perantara (yang disebut agen relai DHCP ) yang dilaluinya pesan tersebut. Klien menetapkan bidang ini ke 0x00.
| 1
|
xid
| Pengidentifikasi transaksi unik sebesar 4 byte yang dihasilkan oleh klien pada awal proses mendapatkan alamat.
| 4
|
dtk
| Waktu dalam detik sejak dimulainya proses mendapatkan alamat. Mungkin tidak digunakan (dalam hal ini diatur ke 0x0000).
| 2
|
bendera
| Field untuk flag adalah parameter khusus dari protokol DHCP.
| 2
|
ciaddr
| Alamat IP klien. Itu diisi hanya jika klien sudah memiliki alamat IP sendiri dan mampu menanggapi permintaan ARP (ini dimungkinkan jika klien melakukan prosedur untuk memperbarui alamat setelah masa sewa berakhir).
| 4
|
yiaddr
| Alamat IP klien baru yang diusulkan oleh server.
| 4
|
siaddr
| Alamat IP server. Kembali dalam klausa DHCP (lihat di bawah).
| 4
|
giaddr
| Alamat IP agen relai, jika ada yang terlibat dalam proses pengiriman pesan DHCP ke server.
| 4
|
chaddr
| Alamat perangkat keras (biasanya alamat MAC) klien.
| 16
|
sname
| Nama server opsional sebagai string yang diakhiri dengan nol.
| 64
|
file
| Nama file server opsional yang digunakan oleh stasiun kerja tanpa disk saat mengunduh dari jarak jauh. Seperti halnya sname , ia direpresentasikan sebagai string yang diakhiri dengan null.
| 128
|
opsi
| Bidang opsi DHCP . Berbagai opsi konfigurasi tambahan ditunjukkan di sini. Pada awal bidang ini, empat byte khusus dengan nilai 99, 130, 83, 99 ("angka ajaib") ditunjukkan, memungkinkan server untuk menentukan keberadaan bidang ini. Bidang memiliki panjang variabel, tetapi klien DHCP harus siap untuk menerima pesan DHCP 576-byte (dalam pesan ini, bidang opsi panjangnya 340 byte).
| variabel
|
Daftar semua opsi DHCP di RFC 2132Opsi DHCP dikodekan sebagai berikut:
Misalnya, parameter 3 (gateway yang diusulkan) dengan nilai 10.0.0.1:
Jika Anda perlu melewati beberapa parameter, panjang parameter akan meningkat.
Misalnya, dalam parameter 6 (server DNS) kami akan mengirimkan dua alamat (1.1.1.1 dan 8.8.4.4):
Tanda akhir bidang opsi adalah parameter dengan angka 255 (0xFF) dan panjang 0.
Paling sering, klien menempatkan parameter 55 (daftar parameter yang ingin ia terima sebagai respons) di DHCP Discover, namun, kami memiliki hak untuk memberinya bukan semua yang ia minta.
Bagian praktis
Pada awalnya direncanakan untuk menulis server dalam beberapa bahasa yang lebih cocok (C) untuk ini, namun, itu akan menjadi biasa dan sederhana. Entah menulis skrip yang akan mengambil alih fungsi server dhcp.
Penyederhanaan
Karena server yang dikembangkan seharusnya digunakan dalam jaringan dua node yang terhubung oleh sebuah tambalan, penyederhanaan berikut diadopsi:
- dijamin bahwa satu klien di jaringan;
- dijamin tidak ada lagi server dhcp di jaringan
- inisiator memutuskan alamat mana yang akan diterbitkan
- Rilis DHCP dan Penurunan DHCP diabaikan
Pendengar
Pertama-tama, Anda perlu belajar cara menerima paket. Ini membutuhkan pendengar
simpatik yang bersertifikat , misalnya, nc. Tetapi tidak setiap nc cocok untuk tujuan ini. OpenBSD netcat 1.130 dari Debian cocok, tetapi 1,105 dengan Ubuntu hilang. Jalankan nc untuk mendengarkan semua paket UDP yang tiba di port 67.
nc -l 0.0.0.0 -up 67 -w0
Netcat OpenBSD juga diperlukan karena saklar -w dengan nilai 0. Setelah menerima satu paket (UDP Broadcast), nc tradisional tidak menerima lebih banyak paket, tetapi tidak berakhir.
Penanganan byte mentah
Dalam shell, sangat sulit untuk bekerja dengan karakter yang tidak dapat dicetak, seperti karakter nol: itu hanya mengabaikannya. Paket DHCP berisi banyak byte 0x00 (misalnya, bidang file). Solusi untuk masalah ini datang dalam bentuk hex-dump:
nc -l 0.0.0.0 -up 67 -w0 | stdbuf -o0 od -v -w1 -t x1 -An
Satu byte per baris, tanpa mengeluarkan alamat, tanpa melewatkan byte duplikat. Anda juga dapat membumbui stdbuf -o0 sehingga output tidak buffered.
Menerima, menyimpan, dan memproses paket
Dari perintah od stdout, byte diambil oleh perintah read dan ditambahkan ke array.
msg=() for i in {0..235}; do read -r tmp msg[$i]=$tmp done
Meskipun semua nilai ditransmisikan dalam notasi heksadesimal, nomor Opsi DHCP dan panjang opsi paling baik ditampilkan pada layar / dalam log dalam bentuk desimal biasa. Untuk melakukan ini, Anda dapat menggunakan bash'a entri pendek:
$ op=AC $ echo $((16
Paket yang diterima diedit sesuai dengan jenis permintaan (Temukan atau Permintaan) dan dikirim kembali.
Tanggapan
Namun, mengirim paket bukanlah tugas yang mudah. Pertama, Anda perlu mengkonversi byte dari dump ke byte mentah dan mengirim semuanya sekaligus dengan satu paket.
Konversi dapat dilakukan dengan utilitas printf menggunakan urutan melarikan diri. Dan agar tidak ada yang hilang, segera tulis byte ke sebuah file.
Netcat OpenBSD juga digunakan untuk pengiriman. Namun, jika versi 1.105 dengan Ubuntu cocok sebagai pendengar, itu tidak cocok untuk menyiarkan pesan UDP: kami mendapatkan protokol tidak ada kesalahan.
cat /tmp/dhcp.payload | nc -ub 255.255.255.255 68 -s $SERVER -p 67 -w0
Switch -b memungkinkan pesan siaran dikirim, dan ini adalah alasan kedua mengapa server harus dijalankan dari bawah superuser.
Apa batasannya?
Server DHCP ini dirancang dengan penyederhanaan seperti satu klien di jaringan. Namun, ini akan bekerja dengan beberapa klien. Dapatkan saja alamat tercepat.

Kesimpulan
Walaupun skrip bash hampir tidak bisa disebut bahasa pemrograman lengkap, namun, dengan keinginan yang sesuai, Anda bahkan dapat menyelesaikan masalah seperti mengeluarkan alamat IP pada jaringan tanpa menggunakan perangkat lunak yang dirancang khusus untuk ini. Dan memecahkan masalah spesifik tidak hanya membawa kegembiraan, tetapi juga pengetahuan baru yang terbuka pada saat solusi.
Sumber
- DHCP - Wikipedia
- Parameter DHCP dan BOOTP - IANA