Java構(gòu)建TCP/IP協(xié)議:DNS,域名解析協(xié)議系統(tǒng)的運(yùn)行流程
DNS協(xié)議的運(yùn)轉(zhuǎn)需要客戶端和服務(wù)器進(jìn)行交互。由于服務(wù)器端需要存儲(chǔ)大量的域名信息,同時(shí)每天需要應(yīng)答海量的解析請(qǐng)求,因此它的設(shè)計(jì)必須遵循分布式系統(tǒng)。客戶端向一臺(tái)服務(wù)器請(qǐng)求解析服務(wù)時(shí),對(duì)方可能沒有相應(yīng)的域名信息,于是它會(huì)向上一層查詢,獲得擁有給定域名信息的服務(wù)器,然后把對(duì)應(yīng)服務(wù)器的信息歸還給客戶端,然后客戶端再重新發(fā)起請(qǐng)求。
我們還需要關(guān)注域名信息如何在服務(wù)器上存儲(chǔ)。在域名服務(wù)器上,信息存儲(chǔ)有兩種方式,一種是域名信息以二進(jìn)制格式存儲(chǔ),這種格式對(duì)應(yīng)的名稱叫Resource Record Filed Format,同時(shí)為了方便管理員管理,這些信息又通過文本形式展現(xiàn)出來,對(duì)應(yīng)的格式稱為Master File Representation,管理員通過修改后者就能使得對(duì)應(yīng)的二進(jìn)制信息進(jìn)行相應(yīng)變換:
Resource Record 是一種特定數(shù)據(jù)結(jié)構(gòu),專門用于存儲(chǔ)域名解析相關(guān)信息,例如域名對(duì)應(yīng)的服務(wù)器IP,域名解析服務(wù)器地址等,在后面我們解析數(shù)據(jù)包時(shí)再深入探討。
域名解析其實(shí)有三種形式,第一種是我們熟悉的,將域名發(fā)給服務(wù)器然后獲得域名對(duì)應(yīng)IP;第二種叫反向解析,將IP發(fā)給服務(wù)器然后獲得對(duì)應(yīng)域名;第三種叫電子郵件解析,將郵件地址發(fā)給服務(wù)器然后獲得郵件的接收對(duì)象IP。我們將主要關(guān)注第一種形式的原理和實(shí)現(xiàn)。
當(dāng)我們執(zhí)行第一種域名解析時(shí),首先要做的是獲得域名服務(wù)器地址。這個(gè)過程并非一撮而就,有可能我們查詢第一個(gè)服務(wù)器時(shí),它給我們返回另一個(gè)服務(wù)器的地址,然后我們繼續(xù)查詢;第二步是確定服務(wù)器后,我們要解析它返回來的數(shù)據(jù)內(nèi)容。在這個(gè)過程中,第二步相對(duì)容易,而第一步則比較棘手。
在查詢對(duì)應(yīng)域名服務(wù)器時(shí)有兩種方式,一種是循環(huán)式,第一個(gè)域名沒有對(duì)應(yīng)信息,但返回另一個(gè)它認(rèn)為有對(duì)應(yīng)信息的服務(wù)器,接著客戶端向第二個(gè)服務(wù)器請(qǐng)求,第二個(gè)服務(wù)器又返回另一個(gè)服務(wù)器信息,該過程依次循環(huán)直到找到對(duì)應(yīng)服務(wù)器為止:
第二種叫遞歸式,它與一種的區(qū)別在于,服務(wù)器承擔(dān)起客戶端查找對(duì)應(yīng)服務(wù)器的職責(zé),服務(wù)器會(huì)反復(fù)向其他服務(wù)器查詢,直到拿到對(duì)應(yīng)域名信息后,直接返回給客戶端:
接下來我們看看DNS數(shù)據(jù)包的基本格式,首先第一部分叫頭部,用于描述消息類型,以及后續(xù)數(shù)據(jù)結(jié)構(gòu)的相關(guān)信息;第二部分叫”問題“,它用來包含客戶端想向服務(wù)器查詢的信息;第三部分叫”答案“,是服務(wù)器用于回復(fù)客戶端查詢;第四部分叫Authority,如果請(qǐng)求沒有得到全部答復(fù),這部分內(nèi)容告訴客戶端向哪個(gè)服務(wù)器進(jìn)行查詢;第五部分叫Additional,這部分包含客戶端查詢信息的附加說明,它并非必須,所以數(shù)據(jù)包的基本結(jié)構(gòu)如下:
我們用wireshark抓取dns有關(guān)的消息包后,對(duì)照上面描述的條目進(jìn)行解析。啟動(dòng)wireshark,然后使用關(guān)鍵詞dns過濾,然后在瀏覽器里輸入一個(gè)你以前沒有訪問過的網(wǎng)址,如果輸入已經(jīng)訪問過的,瀏覽器會(huì)有緩存,因此不會(huì)走dns協(xié)議。以下是我抓取到的一個(gè)DNS解析請(qǐng)求包:
首先是頭部,它包含12字節(jié),從Transaction ID 到 Additional RRs,每個(gè)字段2字節(jié)。ID用來標(biāo)志一次會(huì)話,一個(gè)會(huì)話內(nèi)的數(shù)據(jù)包擁有相同ID。Flags分為兩部分,第一部分一字節(jié)叫做QR,用來表示該數(shù)據(jù)包是查詢還是回答,如果是查詢就設(shè)置為0,如果是回答就設(shè)置為1.如果是查詢,那么第二個(gè)字節(jié)就是OpCode,進(jìn)一步表明具體查詢,它分為若干部分,前四個(gè)比特位用于表明查詢類型,0表示查詢域名對(duì)應(yīng)IP,1不再使用;2表示查詢域名服務(wù)器狀態(tài);3目前不使用,4用于服務(wù)器之間的交互;5也是用于服務(wù)器之間的交互。
第五個(gè)比特位叫AA,它只在回復(fù)包中設(shè)置,用于表明回復(fù)的權(quán)威性,它的具體內(nèi)容我們暫時(shí)忽略。第六個(gè)比特位叫TC,它用于表明數(shù)據(jù)是否被截?cái)?,用于DNS支持UDP和TCP,但使用UDP時(shí)數(shù)據(jù)包不能超過512字節(jié),如果超過數(shù)據(jù)包就得截?cái)喑啥鄠€(gè)小數(shù)據(jù)包,如果該位設(shè)置成1,它表明雙方需要通過TCP來建立連接。第8位叫RD,如果設(shè)置成1,它意味著客戶端請(qǐng)求遞歸式查詢,也就是讓服務(wù)器幫忙向其他服務(wù)器詢問,得到最終消息后再返還給客戶端。
接下來字節(jié)的比特位是RA,如果設(shè)置為1表示服務(wù)器支持遞歸式查詢,也就是服務(wù)器把所有累活都承擔(dān)了,0則是不支持。接下來三個(gè)比特位必須設(shè)置為0,接著4個(gè)比特位表示返回碼,如果值為0表示返回?cái)?shù)據(jù)正常,非0表示出現(xiàn)錯(cuò)誤,其中取值1表示查詢數(shù)據(jù)包格式錯(cuò)誤;2表示服務(wù)器自身故障;3表示解析錯(cuò)誤;4表示不支持所要求的查詢;5表示拒絕查詢請(qǐng)求;其他值我們暫時(shí)忽略。
接下來用于表示相應(yīng)條目的數(shù)量,Questions表示有幾個(gè)查詢條目,Answer RRs表示有幾個(gè)回復(fù)條目,Authority RRs表示有幾個(gè)權(quán)威信息條目,所謂“權(quán)威”是指真正能夠解析域名的服務(wù)器,如果當(dāng)前服務(wù)器不能解析域名請(qǐng)求,它需要把請(qǐng)求轉(zhuǎn)發(fā)給其他服務(wù)器時(shí),它自己就不是Authoritive,我們家用路由器其實(shí)承擔(dān)域名解析服務(wù)器的職責(zé),但是它本身不可能包含所需要的域名信息,它會(huì)把請(qǐng)求轉(zhuǎn)發(fā)給上一層服務(wù)器,因此路由器就不是”權(quán)威“域名解析服務(wù)器。由此一個(gè)DNS域名解析數(shù)據(jù)包的輪廓如下:
接下來我們看看問題段數(shù)據(jù)結(jié)構(gòu),它結(jié)構(gòu)如下:
首先是問題名字,這個(gè)字段長度可變,存儲(chǔ)的是要查詢的域名,以0作為結(jié)尾。第二個(gè)是問題類型,它是2字節(jié),用于表明查詢的類型,取值1表示查詢域名對(duì)應(yīng)IP,取值2查詢服務(wù)器名稱,具體類型在后面我們用到時(shí)再詳細(xì)討論。最后是問題類別,一般而言寫死為1。
這里我們講解一下Question Name對(duì)應(yīng)的字符串結(jié)構(gòu),例如對(duì)于字符串:www.baidu.com,它的對(duì)應(yīng)格式為[3]www[5]baidu[3]com,其中[]內(nèi)表示接下來字符個(gè)數(shù),例如[3]表示后面跟著3個(gè)字符www,[5]表示接下來跟著5個(gè)字符,注意到這些數(shù)字所在位置正好對(duì)應(yīng)字符串中符號(hào)點(diǎn)所在位置。
接下來我們看Answer Resource Records 的結(jié)構(gòu),服務(wù)器收到客戶端請(qǐng)求,完成解析工作后,把解析信息存儲(chǔ)在該結(jié)構(gòu)里發(fā)回給客戶端。它的結(jié)構(gòu)如下,第一個(gè)是名字字符串,可變長,它對(duì)應(yīng)要解析的域名或服務(wù)器名稱。接著是資源類型,2字節(jié),表明資源的類型,如果取值是5,那么接下來對(duì)應(yīng)著域名服務(wù)器對(duì)應(yīng)的字符串名稱,接著是資源類別,2字節(jié),一般設(shè)置成1;接著是TTL(Time To Live),4字節(jié),表明這些信息能在緩存中存儲(chǔ)多久;接著是RDLength,2字節(jié),用于表明接下來內(nèi)容的長度;最后是相應(yīng)內(nèi)容,如果資源類型是5,那么內(nèi)容就是字符串,如果是1,那么內(nèi)容就是4字節(jié)的IP地址,該數(shù)據(jù)類型對(duì)應(yīng)的格式輪廓如下:
這里值得提到的是,如果資源類型5,那么對(duì)應(yīng)的字符串才是“真正”域名,例如下面顯示內(nèi)容:
它顯示的是,一開始我們使用域名“pan.baidu.com”去進(jìn)行域名解析,此時(shí)解析服務(wù)器沒有直接返回該域名對(duì)應(yīng)的IP,而是返回另一個(gè)域名yiyun.n.shifen.com,前面”pan.baidu.com”其實(shí)是一個(gè)別名,打個(gè)比方,一個(gè)人可以使用假名和真名,假名可以隨時(shí)變,真名則要跟身份證綁定。同樣的道理,pan.baidu.com這個(gè)域名可以根據(jù)需要隨時(shí)變化,例如以后它可以變成pen.baidu.com,但是第二個(gè)域名就唯一綁定一臺(tái)服務(wù)器,我們只有拿這個(gè)域名去查詢才能找到對(duì)應(yīng)的IP。
為了簡(jiǎn)單起見,其他兩種資源的數(shù)據(jù)格式我們暫時(shí)放一放,以后需要的時(shí)候才研究,在下一節(jié)我們將使用代碼實(shí)現(xiàn)本節(jié)描述的DNS域名解析流程。