Kata Pengantar
Saya memutuskan untuk menulis sniffer DNS, untuk berbicara, hanya untuk bersenang-senang. Lihat saja alamat mana yang diselesaikan di sistem saya. Protokol sudah tua, harus ada banyak dokumentasi. Banyak. Tetapi semua artikel sangat tidak lengkap dan berakhir, pada saat yang paling menarik. Ya, ada rfc1035, tapi saya ingin dalam bahasa Rusia dan dengan penjelasan. Sebenarnya pada akumulasi pengalaman dan analisis paket artikel ini telah matang. Ini dirancang untuk mereka yang mengerti apa itu DNS dan mengerti bahwa ada permintaan dan jawaban. Bagi yang ingin mengerti sedikit dalam struktur protokol ini.
Artikel tersebut melibatkan teori, dan kemudian sedikit latihan.
Struktur paket DNS
+---------------------+ | Header | +---------------------+ | Question | +---------------------+ | Answer | +---------------------+ | Authority | +---------------------+ | Additional | +---------------------+
Header -
Header paket DNS, terdiri dari 12 oktet.
Bagian pertanyaan - di bagian ini, klien DNS mengirimkan pertanyaan ke server DNS yang menginformasikan tentang nama apa yang diperlukan untuk menyelesaikan (menyelesaikan) data DNS, serta jenis apa (NS, A, TXT, dll.). Saat merespons, server menyalin informasi ini dan mengembalikannya ke klien di bagian yang sama.
Bagian jawaban - server memberi tahu klien jawaban atau beberapa respons terhadap permintaan, di mana ia melaporkan data di atas.
Bagian Otoritatif - berisi informasi tentang server otoritatif mana yang memperoleh informasi yang termasuk dalam bagian respons DNS.
Bagian Catatan Tambahan - catatan tambahan yang berkaitan dengan permintaan, tetapi tidak sepenuhnya menjawab pertanyaan.
Mungkin ada beberapa atau beberapa entri di bagian. Semuanya ditentukan oleh tajuk.
Struktur header DNS
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
ID (16 bit) - bidang ini digunakan sebagai pengidentifikasi transaksi yang unik. Menunjukkan bahwa paket tersebut milik sesi "permintaan-respons" yang sama dan menempati 16 bit.
QR (1 bit) - bit ini digunakan untuk mengidentifikasi apakah paket tersebut adalah permintaan (QR = 0) atau respons (QR = 1).
Opcode (4 bit) - menggunakan kode ini, klien dapat menentukan jenis permintaan, di mana nilai biasanya adalah:
- 0 - permintaan standar
- 1 - permintaan terbalik,
- 2 - meminta status server.
- 3-15 - dicadangkan untuk masa depan.
AA (1 bit) - bidang ini hanya masuk akal dalam respons DNS dari server dan melaporkan apakah jawabannya otoritatif atau tidak.
TC (1 bit) - flag ini diatur dalam paket respons jika server tidak dapat memasukkan semua informasi yang diperlukan ke dalam paket karena batasan yang ada.
RD (1 bit) - flag satu-bit ini diatur dalam permintaan dan disalin ke respons. Jika bendera diatur dalam permintaan, ini berarti bahwa klien meminta server untuk tidak memberi tahu dia jawaban sedang, tetapi hanya mengembalikan alamat IP.
RA (1 bit) - hanya dikirim dalam tanggapan, dan melaporkan bahwa server mendukung rekursi
Z (3 bit) - dicadangkan dan selalu sama dengan nol.
RCODE (4 bit) - bidang ini digunakan untuk memberi tahu klien jika permintaan berhasil diselesaikan atau dengan kesalahan.
- 0 - berarti permintaan diteruskan tanpa kesalahan;
- 1 - kesalahan disebabkan oleh fakta bahwa server tidak dapat memahami formulir permintaan;
- 2 - kesalahan ini dengan operasi yang salah dari server nama;
- 3 - nama yang memungkinkan klien tidak ada di domain ini;
- 4 - server tidak dapat memenuhi permintaan jenis ini;
- 5 - kode ini berarti bahwa server tidak dapat memenuhi permintaan klien karena batasan keamanan administratif.
QDCOUNT (16 bit) - jumlah rekaman di bagian permintaan
ANCOUNT (16 bit) - jumlah entri di bagian jawaban
NSCOUNT (16 bit) - jumlah entri di Bagian Otoritas
ARCOUNT (16 bit) - jumlah catatan di Bagian Catatan Tambahan
Struktur Bagian Permintaan
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / QNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QTYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
QNAME - Setiap permintaan dan catatan tanggapan dimulai dengan NAME. Ini adalah nama domain tempat catatan ini ditautkan atau yang "milik". Itu dikodekan sebagai serangkaian tag. Pada titik ini, kita harus lebih detail.
Dalam artikel yang saya lihat, mereka lupa mengatakan bahwa protokol DNS asli menyediakan dua jenis label, yang ditentukan oleh dua bit pertama:
00 (label standar) - berarti 6 bit yang tersisa menentukan panjang label, diikuti oleh sejumlah oktet. Oleh karena itu, panjang label tidak boleh lebih dari 63 byte (Misalnya, nslookup akan menampilkan pesan "bukan nama yang sah (label terlalu panjang)" ketika mencoba untuk meredam host dengan label panjang). Rekaman berakhir dengan kode 0x00.
11 (label terkompresi) - maka 14 bit berikutnya mendefinisikan tautan ke alamat awal dari rangkaian label. Seperti yang ditunjukkan oleh pengalaman, itu mungkin juga mengandung label terkompresi ke alamat lain. Dalam permintaan, sebagai suatu peraturan, tidak ada label seperti itu.
Juga, label dapat berisi nilai 0x00 (panjang nol), yang berarti bahwa itu adalah nama domain root (root).
Panjang maksimum NAME adalah <= 255. Ini demi kemudahan implementasi.
QTYPE - Jenis catatan DNS yang kami cari (NS, A, TXT, dll.).
QCLASS - Kelas permintaan yang menentukan (IN untuk Internet).
Struktur Bagian Respon
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / / / NAME / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| / RDATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
NAME - Format yang sama dengan QNAME di bagian permintaan.
TYPE - jenis catatan sumber daya. Menentukan format dan tujuan catatan sumber daya ini.
CLASS - kelas catatan sumber daya; secara teoritis diyakini bahwa DNS dapat digunakan tidak hanya dengan TCP / IP, tetapi juga dengan jenis jaringan lainnya, kode di bidang kelas menentukan jenis jaringan. Pada dasarnya IN untuk Internet (Kode 0x0001)
TTL - (Time To Live) - waktu penyimpanan yang valid untuk catatan sumber daya ini dalam cache dari server DNS yang tidak responsif.
RDLENGTH - panjang bidang data (RDATA).
RDATA - bidang data, format dan konten yang tergantung pada jenis catatan.
Berlatih
Pertimbangkan paket dari permintaan dan respons nyata. Luncurkan sniffer favorit Anda dan selesaikan habrahabr.ru.
Minta
Mari kita menganalisis struktur header dns.
ID Transaksi = 0x9bce
Berikutnya adalah bendera. 01 00 direpresentasikan sebagai nilai biner 0'0000'0'0'1'0'000'0000 (selanjutnya, saya memisahkan bit dengan tanda kutip untuk representasi visual yang lebih baik dari pembagian bendera)
QR = 0 - berarti paket ini adalah permintaan;
Opcode = 0000 - Permintaan standar;
AA = 0 - bidang ini hanya masuk akal dalam jawaban DNS, oleh karena itu selalu 0;
TC = 0 - bidang ini hanya masuk akal dalam jawaban DNS, oleh karena itu selalu 0;
RD = 1 - Harap kembalikan hanya alamat IP;
RA = 0 - hanya dikirim oleh server;
Z = 000 - selalu nol, bidang yang dipesan;
RCODE = 0000 - Semuanya berjalan tanpa kesalahan
QDCOUNT = 00 01 - 1 entri di bagian permintaan
ANCOUNT = 00 00 - Permintaan selalu 0, bagian untuk jawaban
NSCOUNT = 00 00 - Permintaan selalu 0, bagian untuk jawaban
ARCOUNT = 00 00 - Permintaan selalu 0, bagian untuk jawaban
Selanjutnya kita memiliki bagian permintaan dan respons. Dengan satu entri.
Oktet pertama yang kita miliki adalah 0x09, bayangkan sebagai nilai biner 00'001001. Dua bit pertama bernilai 00, yang berarti ini adalah label reguler. Panjang label 9 byte (b001001). "68 61 62 72 61 68 61 62 72". Ini adalah 9 byte. Dikatakan "habrahabr" (dalam heksadesimal). Silakan. Oktet 0x02. Dua bit pertama adalah 00, sekali lagi label biasa dengan panjang 2 byte. Inilah mereka: "72 75." Ada tertulis "ru". Silakan. Oktet 0x00. Ini berarti akhir dari entri host. Kami mendapat dua kata "habrahabr" dan "ru". Kami menyatukan mereka dengan satu poin, kami mendapatkan "habrahabr.ru", ini adalah host yang kami minta.
QTYPE = 0x0001 - Sesuai dengan tipe A (permintaan alamat host)
QCLASS = 0x0001 - Sesuai dengan kelas IN.
Jawabannya
Mari kita menganalisis struktur header dns.
ID Transaksi = 0x9bce. Itu harus persis ID dari permintaan.
Bendera lagi. 81 80 mewakili nilai biner 1'0000'0'0'1'1'000'0000
QR = 1 - berarti paket ini adalah jawabannya;
Opcode = 0000 - Permintaan standar;
AA = 0 - Server tidak resmi untuk domain;
TC = 0 - Semua informasi masuk dalam satu paket;
RD = 1 - Harap kembalikan hanya alamat IP;
RA = 1 - Server mendukung rekursi;
Z = 000 - selalu nol, bidang yang dipesan;
RCODE = 0000 - Semuanya berjalan tanpa kesalahan
QDCOUNT = 00 01 - 1 entri di bagian permintaan
ANCOUNT = 00 01 - Sekarang kami memiliki satu entri dalam jawaban
NSCOUNT = 00 00 - Permintaan selalu 0, bagian untuk jawaban
ARCOUNT = 00 00 - Permintaan selalu 0, bagian untuk jawaban
Selanjutnya kita memiliki bagian permintaan dan respons. Dengan dua entri. Satu catatan permintaan, catatan lain dengan jawabannya. Saya tidak akan melukis bagian permintaan, itu akan selalu 1v1 sama dengan di paket permintaan. Lanjutkan dengan bagian jawaban.
Oktet pertama adalah 0x09, dua bit pertama adalah 00, yang berarti label reguler dengan panjang 9 byte. Baca 9 byte, dapatkan "HABRAHABR". Berikutnya adalah 0XC0 (b11000000). Seperti yang Anda lihat, dua bit pertama memiliki nilai 11, yang berarti bahwa kami memiliki tautan terkompresi. Kami melihat 8 bit berikutnya (kami memiliki 0x16 (b00010110)) dan bergabung dengan 6 bit terakhir saat ini. Kami mendapatkan b00000000010110. Tautan ke byte 22 dari paket DNS (02 72 75 00). Mulai dari oktet 22, kami mendapatkan label lagi. Dengan aturan yang sama. Kami mendapatkannya. Kami menggabungkan semua yang kami terima, ternyata "HABRAHABR.ru" Ini adalah tuan rumahnya, yang akan dibahas lebih lanjut.
QTYPE = 0x0001 - Sesuai dengan tipe A (permintaan alamat host)
QCLASS = 0x0001 - Sesuai dengan kelas IN.
TTL = 0x00000c90 - up-time data 3216 detik.
RDLENGTH = 0x0004 - Panjang data adalah 4 oktet.
RDATA = "b2 f8 ed 44".
Seperti yang telah disebutkan, format dan konten tergantung pada jenis rekaman. Jenis rekaman yang kita miliki adalah "A". Jadi, untuk mendapatkan IP, kita harus membaca 4 byte. Setiap byte adalah oktet yang sesuai dari alamat IP, ditulis dalam heksadesimal.
Kami mendapatkan IP: b2.f8.ed.44 atau "178.248.237.68". Apa yang harus diterima.
Misalnya, untuk tipe NS, formatnya adalah:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / NSDNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Dan kami akan membaca nama sesuai dengan aturan QNAME.