Node.js ile DNS sunucusu yazma
DNS nasıl çalışır
Bir alan adınızın neden olduğunu hiç düşündünüz mü?
Bilgisayarları tanımlamak için IP adreslerinin kullanıldığını biliyoruz; IPv4 32 bit, IPv6 ise 128 bittir.
IPv4 genellikle ondalık biçimde ifade edilir:
192.10.128.240
IPv6 çok uzundur ve genellikle onaltılık biçimde gösterilir:
3C0B:0000:2667:BC2F:0000:0000:4669:AB4D
IPv4 veya IPv6 olsun, bu sayı dizisini ezberlemek çok zordur ve bir web sayfasını ziyaret ederken böyle bir sayı dizisini girmek oldukça zahmetlidir.
Ayrıca IP sabit değildir. Sunucu odası taşınırsa IP de değişecektir.
Hedef sunucuya nasıl kolay hatırlanan ve sabit bir IP ile sınırlı olmayan bir şekilde erişilebilir?
Bir ad atanabilir ve istemci IP yerine bu ad üzerinden hedef makineye erişebilir.
Ad ile IP arasındaki bağlama ilişkisi değiştirilebilir ve her ziyarette ada karşılık gelen IP'nin çözümleme sürecinden geçmesi gerekir.
Bu ada alan adı denir.
Bu alan adı ile IP arasındaki eşleme ilişkisi nasıl korunur?
En kolay yol, tüm alan adları ile IP'ler arasındaki karşılığı bir dosyada kaydetmek ve her alan adı çözümlemesinde bu dosyayı kontrol etmektir.
Başlangıçta gerçekten de böyle tasarlanmıştı. Böyle bir dosyaya hosts dosyası denir ve dünyadaki tüm ana bilgisayarları kaydeder.
O dönemde dünyada fazla makine yoktu, bu yüzden bu yöntem uygulanabilirdi.
Elbette bu hosts yapılandırması merkezi olarak yönetilir. Yeni bir ana bilgisayar internete bağlanmak istediğinde kendi alan adını ve IP'sini buraya kaydeder. Diğer makineler en son yapılandırmayı çekerek bu ana bilgisayara erişebilir.
Ancak makine sayısı arttıkça bu yöntem iyi çalışmaz ve iki temel sorun ortaya çıkar:
Tüm dünya yapılandırmayı belirli bir makineden senkronize etmek zorundadır ve bu makine aşırı yük altına girer.
Alan adları çoğaldığında isimlendirme çakışmaları yaşanması kolaylaşır.
Bu nedenle alan adı sunucusu dağıtık olmalı, birden fazla sunucu üzerinden hizmet vermeli ve isimlendirme çakışmalarını azaltmak için ad alanına göre bölünmelidir.
Bu amaçla alan adları oluşturuldu. Örneğin baidu.com'daki com üst düzey alan adı, baidu ise com alan adının ikinci düzey alan adıdır.
Bu şekilde, başka bir baidu.xyz olması da mümkündür çünkü xyz ve com farklı alan adlarıdır ve bunların altında ayrı ad alanları bulunur.
Bu durum isimlendirme çakışmalarını azaltır.
Dağıtık bir yapı söz konusuysa, istek baskısını yaymak için alan adını bölmek ve hangi sunucunun işleyeceğini belirlemek gerekir.
Üst düzey alan adı, ikinci düzey alan adı ve üçüncü düzey alan adının analiz için farklı sunuculara yerleştirilmesi mantıklıdır.
Tüm üst düzey alan adı sunucularında ayrıca kök alan adı sunucusu adında bir dizin bulunur.
Böylece bir alan adının IP'si sorgulanırken önce kök alan adı sunucusundan üst düzey alan adının adresi kontrol edilir, ardından ikinci düzey alan adı varsa ilgili sunucunun adresi kontrol edilir ve nihai IP bulunana kadar bu işlem devam eder.
Elbette önceki hosts yöntemi tamamen terk edilmemiştir. Hâlâ önce hosts dosyasını kontrol ederiz, bulamazsak alan adı sunucusuna istekte bulunuruz.
Süreç şöyledir:
Örneğin www.baidu.com alan adının IP'sini kontrol etmek için önce yerel hosts dosyasına bakılır; bulunamazsa kök alan adı sunucusundan com alan adının genel üst düzey alan adı sunucusunun adresi alınır, ardından baidu.com için üst düzey alan adı sunucusu sorgulanır. Nihai IP bulunana kadar üst düzey alan adı sunucusunun adresi katman katman kontrol edilir.
Bu sayede sunucu üzerindeki baskı dağıtık bir şekilde yayılmış olur.
Ancak bu tasarımda hâlâ bir sorun vardır. Her alan adı seviyesi için bir sunucu bulunur. Alan adı seviyeleri çok fazlaysa birden fazla gidiş-dönüş sorgusu gerekir ve verimlilik düşer.
Bu nedenle DNS (Alan Adı Sistemi) yalnızca üç seviyeli alan adı sunucularına bölünmüştür:
Kök alan adı sunucusu: Tüm üst düzey alan adı sunucularının adreslerini kaydeder ve alan adı çözümlemenin giriş noktasıdır.
Üst düzey alan adı sunucusu: Her ikinci düzey alan adına karşılık gelen sunucunun adresini kaydeder.
Yetkili Alan Adı Sunucusu: Alan altındaki ikinci, üçüncü ve daha alt seviye alan adları burada çözümlenir.
Aslında ikinci, üçüncü, dördüncü, beşinci ve hatta daha alt seviye alan adları çözümleme için tek bir sunucuda birleştirilir; buna Yetkili Alan Adı Sunucusu denir.
Bu sayede hem dağıtık yapı sayesinde sunucu yükü azaltılır hem de çok fazla katman nedeniyle yavaşlayan çözümleme önlenir.
Elbette her sorgu hâlâ zaman alır. Sorgu tamamlandıktan sonra sonuç önbelleğe alınmalı ve bir son kullanma süresi belirlenmelidir. DNS sunucusundaki alan adı çözümleme kaydının önbellek süresine TTL (Time-To-Live) denir.
Ancak şu anda bu çözümleme sonucu yalnızca belirli bir makinede önbelleğe alınmaktadır ve belirli bir bölgedeki diğer makineler erişim sırasında hâlâ çözümleme yapmak zorunda kalabilir.
Bu yüzden DNS, alan adı çözümlemeyi tamamlamaktan ve sonuçları önbelleğe almaktan sorumlu bir yerel alan adı sunucusu katmanı tasarlamıştır.
Böylece belirli bir makinenin yalnızca yerel alan adı sunucusuna istek göndermesi yeterlidir; diğer makineler çözümleme sonucunu doğrudan kullanabilir.
Bu tür yerel alan adı sunucuları China Mobile ve China Unicom gibi İSS'ler (İnternet Servis Sağlayıcıları) tarafından sağlanır ve genellikle her şehirde bir tane bulunur. Belirli bir makine bir alan adına eriştiğinde sonuç çözümlemeden sonra önbelleğe alınır ve diğer makineler bu alan adına erişirken tekrar çözümleme yapmak zorunda kalmaz.
Bu yerel alan adı sunucusunun adresi değiştirilebilir. Mac'te Sistem Tercihleri --> Ağ --> Gelişmiş --> DNS yolunu izleyerek yerel alan adı sunucusunun adresini görüntüleyebilir ve değiştirebilirsiniz.
DNS bu şekilde çalışır.
Yerel alan adı sunucusunun yapılandırmasının değiştirilebildiğini gören herkesin kendi DNS sunucusunu uygulama isteği duyup duymadığını merak ediyorum.
Gerçekten de bu DNS sunucusu kendi başınıza uygulanabilir ve şimdi bunu Node.js kullanarak gerçekleştireceğiz.
Önce fikirleri analiz edelim:
DNS Sunucusu Uygulama Fikirlerinin Analizi
DNS bir uygulama katmanı protokolüdür ve protokol içeriğinin iletimi hâlâ taşıma katmanının UDP veya TCP'sinden geçmelidir.
TCP'nin önce üçlü el sıkışma ile bağlantı kurduğunu, ardından veri paketi gönderdiğini ve paket kaybolursa yeniden iletim yaparak verilerin sıralı teslim edilmesini sağladığını biliyoruz.
Birden fazla istek ve yanıt gerektiren bazı iletişim türleri için uygundur çünkü bu iletişim türünde işleme sırasının garanti edilmesi gerekir; tipik örnek HTTP'dir.
Ancak bu güvenilirlik garantisi belirli bir performans fedakarlığına mal olur ve verimlilik nispeten düşüktür.
UDP bağlantı kurmaz, doğrudan karşı tarafa veri paketi gönderir ve daha verimlidir. Sıra garantisi gerektirmeyen bazı senaryolar için uygundur.
Açıkçası DNS'nin her sorgu isteği bağımsızdır, sıra gereksinimi yoktur ve UDP için daha uygundur.
Bu nedenle istemcinin DNS veri paketini almak üzere Node.js ile bir UDP hizmeti başlatmamız, alan adı çözümlemeyi kendimiz gerçekleştirmemiz veya işlem için diğer alan adı sunucularına yönlendirmemiz gerekir. Ardından çözümlenen sonucu istemciye göndeririz.
Node.js'nin dgram paketini kullanarak UDP hizmetleri oluşturun ve veri gönderin.
Şuna benzer:
const dgram = require('dgram');
const server = dgram.createSocket('udp4')
server.on('message', (msg, rinfo) => {
// DNS protokol mesajlarını işle
})
server.on('error', (err) => {
// hataları işle
})
server.on('listening', () => {
// alıcı adresi belirlendiğinde
});
server.bind(53);
Özel kod daha sonra ayrıntılı olarak ele alınacaktır. Burada DNS protokol verilerini almak için UDP hizmetinin etkinleştirilmesi gerektiğini biliyoruz.
DNS sunucusu, alan adları ile IP'ler arasındaki karşılık kayıtlarını saklar. Bu kayıtlar dört türdür:
A: Alan adına karşılık gelen IP
CNAME: Alan adına karşılık gelen takma ad
MX: E-posta adının son ekine karşılık gelen alan adı veya IP
NS: Alan adının çözümleme için başka bir DNS sunucusuna gitmesi gerekir
PTR: IP'ye karşılık gelen alan adı
Aslında anlaması oldukça kolaydır:
A Türü, alan adına karşılık gelen IP'yi sorgulamaktır ve doğrudan istemciye bildirilebilir.
NS Türü, çözümleme için başka bir DNS sunucusuna gitmeyi gerektirir. Örneğin üst düzey alan adı sunucusunun çözümleme için yetkili alan adı sunucusuna daha ileri gitmesi gerekir.
CNAME mevcut alan adı için bir takma addır ve her iki alan adı da aynı IP'ye çözümlenecektir.
PTR, IP tarafından alan adlarını sorgulamak için kullanılır ve DNS ters çözümlemeyi destekler.
MX, @xxx.com gibi e-posta adreslerini çözümlemek için kullanılan posta kutusuna karşılık gelen alan adı veya IP'dir.
DNS sunucusu DNS protokol verilerini aldığında, karşılık gelen kaydı bulmak için bu kayıt tablosuna gider ve ardından DNS protokolü formatında döndürür.
DNS protokolünün formatı nedir?
Muhtemelen şuna benzer:
Hâlâ çok fazla içerik var, birkaç önemli noktaya bakalım:
İşlem Kimliği, isteği yanıtla ilişkilendirmek için kullanılır.
Bayraklar bazı işaret bitleridir:
Örneğin QR, bunun bir istek mi yoksa yanıt mı olduğunu tanımlar. OPCODE, bunun ileri sorgu mu (yani alan adından IP'ye) yoksa ters sorgu mu (yani IP'den alan adına) olduğunu tanımlar.
Ardından soru sayısı, yanıt sayısı, yetkilendirme sayısı ve ek bilgi sayısı gelir.
Sonra soruların ve yanıtların özel içeriği gelir.
Soru bölümünün formatı şöyledir:
İlk olarak sorgunun adı gelir, örneğin baidu.com, ardından yukarıda belirtilen A, NS, CNAME, PTR ve diğer türler olan sorgu türü gelir. Son sorgu sınıfı genellikle 1'dir, bu da internet verisi anlamına gelir.
Yanıtın formatı şöyledir:
Name da sorgulanacak alan adıdır, Type A, NS, CNAME, PTR vb.'dir ve Class soru kısmıyla aynıdır, yani 1'dir.
Ardından Time to live'ı belirtmeniz gerekir, yani bu çözümleme kaydının ne kadar süreyle önbelleğe alınacağı. DNS bunu istemcilerin ve yerel DNS sunucularının önbellek son kullanma süresini kontrol etmek için kullanır.
Son olarak verinin uzunluğu ve içeriği gelir.
DNS protokolünün formatı budur.
UDP hizmetini nasıl başlatacağımızı ve alınan DNS protokol verilerinin hangi formatta olduğunu biliyoruz, o halde DNS sunucusunu uygulamaya başlayabiliriz. Sorun kısmının alan adını ayrıştırın, çözümlemeyi kendiniz uygulayın ve karşılık gelen yanıt verilerini döndürün.
Prensip muhtemelen açıklığa kavuştu, hadi kodu yazalım:
El Yazısı DNS Sunucusu
Öncelikle, DNS protokolü için varsayılan bağlantı noktası olan 53 numaralı bağlantı noktasında dinleyen bir UDP hizmeti oluşturuyoruz.
const dgram = require('dgram')
const server = dgram.createSocket('udp4')
server.on('message', (msg, rinfo) => {
console.log(msg)
});
server.on('error', (err) => {
console.log(`server error: ${err.stack}`)
server.close()
})
server.on('listening', () => {
const address = server.address()
console.log(`server listening ${address.address}:${address.port}`)
})
server.bind(53)
Dgram modülü aracılığıyla bir UDP hizmeti oluşturun, 53 numaralı bağlantı noktasında başlatın, dinlemeye başlama olayını işleyin, sunucu adresini ve bağlantı noktasını yazdırın, hata olayını işleyin ve hata yığınını yazdırın. Bir mesaj alındığında doğrudan yazdırın.
Sistem Tercihlerinde yerel DNS sunucusu adresini bu makineyi gösterecek şekilde değiştirin:
Bu şekilde web sayfasını tekrar ziyaret ettiğimizde hizmet konsolumuz alınan mesajı yazdıracaktır:
Bir sürü Buffer verisi, bu DNS protokolünün mesajıdır.
Bundan sorgulanan alan adını ayrıştırıp yazdırıyoruz, yani şu kısmı:
Sorunun ilk kısmı 12 bayttır, o yüzden onu kesip ayrıştıralım:
server.on('message', (msg, rinfo) => {
const host = parseHost(msg.subarray(12))
console.log(`query: ${host}`)
})
msg, Uint8Array'in bir alt türü olan Buffer türündedir ve işaretsiz bir tamsayıdır. (Tamsayı depolaması işaretli veya işaretsiz olabilir ve işaret olmadan depolanabilen sayı iki kat daha büyük olacaktır.)
İlk 12 baytı kesmek için subarray yöntemini çağırın.
Ardından soru kısmını ayrıştırın:
İlk sorun alan adıdır, sadece alan adını çözümlememiz gerekir.
Alan adının . ile ayrıldığını belirtiyoruz ancak depolandığında böyle değildir, şu şekildedir:
Mevcut alan uzunluğu + mevcut alan içeriği + mevcut alan uzunluğu + mevcut alan içeriği + mevcut alan uzunluğu + mevcut alan içeriği + 0
Bu formatta alan adı 0 ile biter.
Bu yüzden ayrıştırma mantığı şöyledir:
function parseHost(msg) {
let num = msg.readUInt8(0);
let offset = 1;
let host = "";
while (num !== 0) {
host += msg.subarray(offset, offset + num).toString();
offset += num;
num = msg.readUInt8(offset);
offset += 1;
if (num !== 0) {
host += '.'
}
}
return host
}
Buffer'ın readUInt8 yöntemi aracılığıyla işaretsiz bir tamsayı okuyun ve Buffer'ın subarray yöntemi aracılığıyla içeriğin belirli bir segmentini kesin.
Her iki yöntem de ofseti, yani nereden başlanacağını belirtir.
Önce mevcut alanın uzunluğu olan bir sayıyı okuruz, ardından bu uzunluktaki içeriği okuruz ve 0 değerini okuyana kadar bir sonraki paragrafı okumaya devam ederiz; bu alan adının sonu anlamına gelir.
Aradaki alanları . ile bağlayın. Örneğin, 3 www 5 baidu 3 com işlendikten sonra www.baidu.com olur.
Ardından efekti test etmek için sunucuyu yeniden başlatıyoruz:
DNS protokol verilerinden sorgunun alan adını başarıyla ayrıştırdık!
Sorgu kısmını ayrıştırmak yalnızca ilk adımdır, ardından karşılık gelen yanıtı döndürmek gerekir.
Burada yalnızca bazı alan adlarını kendimiz ele alıyoruz ve kalan alan adlarını işlemesi için diğer yerel DNS sunucularına devrediyoruz:
server.on('message', (msg, rinfo) => {
const host = parseHost(msg.subarray(12))
console.log(`query: ${host}`);
if (/guangguangguang/.test(host)) {
resolve(msg, rinfo)
} else {
forward(msg, rinfo)
}
});
Çözümlenen alan adı guangguangguang içeriyorsa kendisi tarafından işlenecek ve karşılık gelen DNS protokol mesajı oluşturulup döndürülecektir.
Aksi takdirde, işlem için başka bir yerel DNS sunucusuna yönlendirilir ve sonuç istemciye döndürülür.
Önce yönlendirme kısmını uygulayalım:
Başka bir DNS sunucusuna yönlendirmek, yani bir UDP istemcisi oluşturmak, alınan mesajı ona iletmek ve mesajı aldıktan sonra istemciye yönlendirmektir.
Şöyledir:
function forward(msg, rinfo) {
const client = dgram.createSocket('udp4');
client.on('error', (err) => {
console.log(`client error: ${err.stack}`);
client.close();
});
client.on('message', (fbMsg, fbRinfo) => {
server.send(fbMsg, rinfo.port, rinfo.address, (err) => {
err && console.log(err)
})
client.close();
});
client.send(msg, 53, '192.168.199.1', (err) => {
if (err) {
console.log(err)
client.close()
}
});
}
Dgram.createSocket aracılığıyla bir UDP istemcisi oluşturun; udp4 parametresi IPv4 adresini temsil eder.
Hataları işleyin, mesajları izleyin ve msg'yi hedef DNS sunucusuna yönlendirin (buradaki DNS sunucusu adresi başka bir şeyle değiştirilebilir).
Döndürülen mesaj alındıktan sonra istemciye iletilir.
İstemcinin IP'si ve bağlantı noktası parametreler aracılığıyla aktarılır.
Bu şekilde DNS protokolünün aktarımı gerçekleştirilir. Önce mevcut efekti test edelim.
Bir alan adının adresini sorgulamak için nslookup komutunu kullanın:
Görüldüğü gibi baidu.com sorgulanarak karşılık gelen IP adresi alınabilir ve tarayıcıda erişilebilir.
Ve guangguangguang.ddd.com için karşılık gelen IP bulunamadı.
Ardından resolve yöntemini uygulayın ve bir DNS protokol mesaj dönüşü oluşturun.
Hâlâ bu formatta:
Kabaca şöyle oluşturulmuştur:
Oturum kimliği iletilen msg'den alınır ve bayraklar da ayarlanır. Soru ve yanıt sayısının her ikisi de 1'dir, yetkilendirme ve ek sayılar ise 0'dır.
Soru alanı ve yanıt alanı ilgili formata göre ayarlanır:
Buffer.alloc ile bir arabellek nesnesi oluşturulmalıdır.
Süreç ayrıca buffer.writeUInt16BE kullanarak bazı işaretsiz çift baytlı tamsayılar yazacaktır.
Buradaki BE Big Endian'dır, yani yüksek mertebe sağa, düşük mertebe sola yerleştirilir.
Örneğin 00000000 00000001 big-endian çift baytlı işaretsiz tamsayı 1'dir. Little-endian 1 ise 00000001 00000000'dır, yani yüksek mertebe sola yerleştirilir.
DNS protokolünün mesajını birleştirmek oldukça zahmetlidir. Sadece bir göz atın:
function copyBuffer(src, offset, dst) {
for (let i = 0; i < src.length; ++i) {
dst.writeUInt8(src.readUInt8(i), offset + i)
}
}
function resolve(msg, rinfo) {
const queryInfo = msg.subarray(12)
const response = Buffer.alloc(28 + queryInfo.length)
let offset = 0
// Transaction ID
const id = msg.subarray(0, 2)
copyBuffer(id, 0, response)
offset += id.length
// Flags
response.writeUInt16BE(0x8180, offset)
offset += 2
// Questions
response.writeUInt16BE(1, offset)
offset += 2
// Answer RRs
response.writeUInt16BE(1, offset)
offset += 2
// Authority RRs & Additional RRs
response.writeUInt32BE(0, offset)
offset += 4
copyBuffer(queryInfo, offset, response)
offset += queryInfo.length
// offset to domain name
response.writeUInt16BE(0xC00C, offset)
offset += 2
const typeAndClass = msg.subarray(msg.length - 4)
copyBuffer(typeAndClass, offset, response)
offset += typeAndClass.length
// TTL, in seconds
response.writeUInt32BE(600, offset)
offset += 4
// Length of IP
response.writeUInt16BE(4, offset)
offset += 2
'11.22.33.44'.split('.').forEach(value => {
response.writeUInt8(parseInt(value), offset)
offset += 1
})
server.send(response, rinfo.port, rinfo.address, (err) => {
if (err) {
console.log(err)
server.close()
}
})
}
Son olarak, birleştirilen DNS protokolünün mesajı karşı tarafa gönderilir.
Bu şekilde guangguangguang alan adının çözümlenmesi gerçekleştirilir.
Yukarıdaki kodda bunu 11.22.33.44 IP'sine çözümlüyorum.
Nslookup ile test edelim:
Görüldüğü gibi, karşılık gelen alan adı çözümlemesi başarılı!
Bu şekilde Node.js aracılığıyla DNS sunucusunu uygulamış olduk.
Tam bir kod yayınlayın, kendiniz çalıştırabilir ve ardından bilgisayarınızın yerel DNS sunucusunu buna yönlendirip deneyebilirsiniz:
const dgram = require('dgram')
const server = dgram.createSocket('udp4')
function parseHost(msg) {
let num = msg.readUInt8(0);
let offset = 1;
let host = "";
while (num !== 0) {
host += msg.subarray(offset, offset + num).toString();
offset += num;
num = msg.readUInt8(offset);
offset += 1;
if (num !== 0) {
host += '.'
}
}
return host
}
function copyBuffer(src, offset, dst) {
for (let i = 0; i < src.length; ++i) {
dst.writeUInt8(src.readUInt8(i), offset + i)
}
}
function resolve(msg, rinfo) {
const queryInfo = msg.subarray(12)
const response = Buffer.alloc(28 + queryInfo.length)
let offset = 0
// Transaction ID
const id = msg.subarray(0, 2)
copyBuffer(id, 0, response)
offset += id.length
// Flags
response.writeUInt16BE(0x8180, offset)
offset += 2
// Questions
response.writeUInt16BE(1, offset)
offset += 2
// Answer RRs
response.writeUInt16BE(1, offset)
offset += 2
// Authority RRs & Additional RRs
response.writeUInt32BE(0, offset)
offset += 4
copyBuffer(queryInfo, offset, response)
offset += queryInfo.length
// offset to domain name
response.writeUInt16BE(0xC00C, offset)
offset += 2
const typeAndClass = msg.subarray(msg.length - 4)
copyBuffer(typeAndClass, offset, response)
offset += typeAndClass.length
// TTL, in seconds
response.writeUInt32BE(600, offset)
offset += 4
// Length of IP
response.writeUInt16BE(4, offset)
offset += 2
'11.22.33.44'.split('.').forEach(value => {
response.writeUInt8(parseInt(value), offset)
offset += 1
})
server.send(response, rinfo.port, rinfo.address, (err) => {
if (err) {
console.log(err)
server.close()
}
})
}
function forward(msg, rinfo) {
const client = dgram.createSocket('udp4')
client.on('error', (err) => {
console.log(`client error: ${err.stack}`)
client.close()
})
client.on('message', (fbMsg, fbRinfo) => {
server.send(fbMsg, rinfo.port, rinfo.address, (err) => {
err && console.log(err)
})
client.close()
})
client.send(msg, 53, '192.168.199.1', (err) => {
if (err) {
console.log(err)
client.close()
}
})
}
server.on('message', (msg, rinfo) => {
const host = parseHost(msg.subarray(12))
console.log(`query: ${host}`);
if (/guangguangguang/.test(host)) {
resolve(msg, rinfo)
} else {
forward(msg, rinfo)
}
});
server.on('error', (err) => {
console.log(`server error: ${err.stack}`)
server.close()
})
server.on('listening', () => {
const address = server.address()
console.log(`server listening ${address.address}:${address.port}`)
})
server.bind(53)
Özet
Bu makalede DNS prensiplerini öğrendik ve Node.js kullanarak kendi yerel DNS sunucumuzu uyguladık.
Alan adı çözümlendiğinde önce hosts dosyası sorgulanır. Bulunamazsa İSS tarafından sağlanan yerel alan adı sunucusuna istekte bulunulur. Genellikle her şehirde bir tane bulunur.
Yerel alan adı sunucusu alan adına karşılık gelen IP'yi çözümlemekten sorumludur. Nihai IP'yi almak ve istemciye döndürmek için sırasıyla kök alan adı sunucusuna, üst düzey alan adı sunucusuna ve yetkili alan adı sunucusuna istekte bulunur.
Bilgisayar yerel alan adı sunucusunun adresini ayarlayabilir ve biz bunu Node.js ile uygulanan yerel alan adı sunucusuna yönlendiririz.
DNS protokolü UDP aktarımına dayalıdır, bu nedenle dgram modülü aracılığıyla 53 numaralı bağlantı noktasında UDP hizmetini başlattık.
Ardından DNS protokolünün formatına göre alan adı ayrıştırılır, hedef alan adı kendisi tarafından işlenir ve DNS protokolünün mesaj dönüşü oluşturulur. Diğer alan adları çözümleme için başka bir yerel DNS sunucusuna yönlendirilir ve onun döndürdüğü mesaj istemciye iletilir.
Bu şekilde Node.js'de yerel bir DNS sunucusu uygulamış olduk.
İlgili Makaleler
-
Veri Depolama İçin 6 İsteğe Bağlı Teknoloji
Bilgi Bankası Ekibi
Daha Fazla Özel Teklifi Keşfedin
-
Kısa Mesaj Servisi (SMS) & E-posta Hizmeti
50.000 e-posta paketi sadece 1,99 USD'den başlayan fiyatlarla, 120 kısa mesaj ise yalnızca 1,00 USD'den başlayan fiyatlarla sunulmaktadır.
