瀏覽器輸入一個網(wǎng)址發(fā)生了什么(一) :揭秘 DNS 請求和解析全流程
從本系列文章開始將圍繞著“往瀏覽器輸入網(wǎng)址后發(fā)生了什么”介紹計算機(jī)網(wǎng)絡(luò)的相關(guān)基礎(chǔ)知識。
本文將介紹往瀏覽器中輸入一個網(wǎng)址后客戶端如何封裝http消息和發(fā)送dns請求查詢目標(biāo)主機(jī)的ip的過程。
一、客戶端(如瀏覽器)解析url
url的組成部分如下所示:
客戶端會按照 協(xié)議、域名、文件路徑以及請求參數(shù) 對url進(jìn)行解析(就是解析出以上信息)。
url如果沒有以/結(jié)尾表示訪問一個指定文件,以/結(jié)尾表示訪問指定目錄下的默認(rèn)文件,例如:
- http://www.lab.glasscom.com/dir/ 訪問的是/dir 目錄下的index.html文件。
- http://www.lab.glasscom.com/dir 訪問的是 /dir文件。但是如果不存在 /dir文件,則會把它當(dāng)做是目錄處理,因而會訪問/dir/下的默認(rèn)文件
二、生成http請求消息
解析完url后,客戶端會根據(jù)請求的類型(這里以GET和POST為例)生成http請求消息。http請求消息和響應(yīng)消息如下所示:
PS:get請求沒有消息體,post才有。
- 消息頭就是我們所說的header字段,包含諸如Content-Type、Cookie、Host等內(nèi)容。
- 請求行的URI包括文件路徑和請求參數(shù)。
- 請求消息和響應(yīng)消息的不同僅在第一行
- 一個請求消息中只能寫一個URI。
如下為get和post請求報文格式:
客戶端會根據(jù)上述(a)的格式生成http消息。
頭信息列舉
通用頭:
請求頭:
響應(yīng)頭:
響應(yīng)消息中的狀態(tài)碼概述:
三、向DNS服務(wù)器查詢域名對應(yīng)IP
客戶端生成http消息后會委托操作系統(tǒng)將消息發(fā)送給web服務(wù)器。操作系統(tǒng)拿到http報文后為了將其發(fā)送給web服務(wù)器,會先根據(jù)域名查詢目標(biāo)主機(jī)的IP地址。
1.簡單了解IP相關(guān)知識
在網(wǎng)絡(luò)中,所有設(shè)備都會被分配一個IP地址,IP地址相當(dāng)于是服務(wù)器的坐標(biāo),客戶端得知這個坐標(biāo)才能將消息發(fā)送到服務(wù)器主機(jī)。
實際的IP是一串32比特的數(shù)字(IPv4標(biāo)準(zhǔn)),并按8比特分為4組,每組用原點隔開,每組以十進(jìn)制表示。除了IPv4標(biāo)準(zhǔn)外還有IPv6標(biāo)準(zhǔn),IPv6下的IP地址則是128比特的長度用于支持更多可能的地址,這里只介紹IPv4下的內(nèi)容。
IP地址分為網(wǎng)絡(luò)號和主機(jī)號兩部分,網(wǎng)絡(luò)號代表主機(jī)所在的子網(wǎng)網(wǎng)絡(luò),子網(wǎng)與子網(wǎng)間通過路由器和集線器連接和通信,主機(jī)號代表某臺主機(jī)在子網(wǎng)中的具體位置。
IP地址被分為A~E類,每類的網(wǎng)絡(luò)號和主機(jī)號長度是不定的,例如C類IP的前3個字節(jié)是網(wǎng)絡(luò)號,第4個字節(jié)是主機(jī)號;而B類IP地址前2個字節(jié)是網(wǎng)絡(luò)號,后兩個字節(jié)是主機(jī)號。
IP地址會用附加信息來表示哪部分是IP的網(wǎng)絡(luò)號,哪部分是IP的主機(jī)號。這個附加信息就是子網(wǎng)掩碼。子網(wǎng)掩碼是一串與IP長度相同的32比特數(shù)字,也分為主機(jī)號和網(wǎng)絡(luò)號,其中左邊一半全為1,右邊一半全為0,全為1的部分為網(wǎng)絡(luò)號,全為0的部分為主機(jī)號。
例如:10.11.12.13/255.255.255.0 中 255.255.255.0就是子網(wǎng)掩碼,它的前3字節(jié)是1,第四字節(jié)為0,因此表示10.11.12.13中前3字節(jié)是網(wǎng)絡(luò)號,第4字節(jié)是主機(jī)號。
此外還可以用 網(wǎng)絡(luò)號比特數(shù) 表示子網(wǎng)掩碼,如 24。24表示前三字節(jié)為網(wǎng)絡(luò)號(8*3),16表示前兩個字節(jié)為網(wǎng)絡(luò)號(8*2),8表示只有第一個字節(jié)是網(wǎng)絡(luò)號。
域名也代表某一服務(wù)器的地址,但域名的使用是為了方便人類的記憶,而IP才是服務(wù)器所在主機(jī)的真正位置。
回到正題。
- 從域名解析為IP就涉及到DNS(域名解析)
- 為了得到域名對應(yīng)的IP,客戶端(瀏覽器)在將http請求委托給操作系統(tǒng)發(fā)送前會查詢?yōu)g覽器的DNS緩存找域名對應(yīng)IP,如果命中緩存則客戶端會將IP帶給操作系統(tǒng),沒有命中則操作系統(tǒng)會查找本機(jī)的DNS緩存,如果還是沒有命中,操作系統(tǒng)就會通過DNS解析器向DNS服務(wù)器發(fā)起DNS請求。
2.關(guān)于DNS解析器
DNS解析器本質(zhì)上是操作系統(tǒng)socket庫中的一段程序,用于向dns服務(wù)器發(fā)送查詢請求并獲取域名對應(yīng)的IP并返回給客戶端。而socket庫是用于調(diào)用網(wǎng)絡(luò)功能的通用程序組件。
客戶端通過DNS解析器發(fā)起dns請求的過程如下所示:
客戶端(瀏覽器)委托操作系統(tǒng)調(diào)用socket庫的gethostbyname()這個系統(tǒng)調(diào)用函數(shù),此時用戶程序(瀏覽器)的工作會暫停并切換到操作系統(tǒng)的dns解析器運行,即用戶態(tài)切換到內(nèi)核態(tài)。
DNS解析器根據(jù)瀏覽器提供的域名生成DNS查詢消息(DNS查詢報文)并交給操作系統(tǒng)中的TCP/IP協(xié)議棧,由協(xié)議棧通過網(wǎng)卡以UDP傳輸?shù)姆绞桨l(fā)送給DNS服務(wù)器。在這里,操作系統(tǒng)必須得知道DNS服務(wù)器的IP,這樣操作系統(tǒng)才該把報文發(fā)送給那個DNS服務(wù)器,而這個DNS服務(wù)器的IP是已經(jīng)事先設(shè)置好的,如下所示:
而這個設(shè)置好的DNS服務(wù)器一般是距離客戶端主機(jī)所在城市內(nèi)不遠(yuǎn)處的一個DNS服務(wù)器,我們稱之為本地DNS服務(wù)器。
發(fā)送DNS查詢報文后,DNS服務(wù)器會返回對應(yīng)域名的IP地址給協(xié)議棧(至于DNS服務(wù)器根據(jù)域名返回對應(yīng)ip的過程會在之后介紹),并按原路返回給DNS解析器,解析器將IP寫入到瀏覽器指定的內(nèi)存地址中(從內(nèi)核態(tài)切回用戶態(tài)),這樣當(dāng)該瀏覽器待會再想知道這個域名的IP時就直接從用戶程序內(nèi)存中取即可,無需在做DNS查詢。此外,操作系統(tǒng)和瀏覽器還會對這個域名與IP的映射關(guān)系做緩存,即使關(guān)閉了瀏覽器下次再打開并請求也無需做DNS查詢請求。除非緩存時間過期。
得到IP的值的瀏覽器終于可以開始發(fā)送HTTP請求消息。
四、DNS報文在多個DNS服務(wù)器間的傳遞
當(dāng)客戶主機(jī)的操作系統(tǒng)將DNS查詢報文發(fā)送給本地DNS服務(wù)器到DNS服務(wù)器返回IP給客戶端主機(jī)這段期間發(fā)生了什么?這里需要介紹一下DNS查詢報文的內(nèi)容和DNS服務(wù)器。
1.DNS查詢報文和回答報文
DNS 查詢和回答報文的格式是一致的,如下所示:
報文頭部的12個字節(jié)包含了一些控制信息如,報文是查詢還是回答報文,回答報文中告訴客戶端它訪問的是否為權(quán)威DNS服務(wù)器,客戶端是否希望DNS服務(wù)器提供遞歸查詢,以及該DNS服務(wù)器是否支持遞歸查詢,回答的RR數(shù)等。
查詢報文的實體部分需要包括2個部分:要查詢的域名和記錄類型。
記錄類型表示域名對應(yīng)何種類型的記錄(即告訴DNS服務(wù)器,根據(jù)傳過來的域名,它應(yīng)該返回什么類型的響應(yīng)內(nèi)容)。
dns服務(wù)器中保存著多條資源記錄(RR),資源記錄不只包括域名與IP的映射,但包括域名與其他信息的映射,而資源記錄中保存的到底是域名與什么信息的映射取決于記錄類型。
- 如類型是A表示該條記錄是域名對應(yīng)的IP地址;
- 類型為MX,是該域名對應(yīng)的郵箱服務(wù)器域名;
- 類型為CNAME,該記錄是一個別名域名對應(yīng)的真正域名;
- 類型為NS時該記錄存著要查詢的域名是由哪個DNS服務(wù)器解析的(也就是記錄著一個目標(biāo)DNS服務(wù)器的域名),此時這個DNS服務(wù)器應(yīng)該還保存著目標(biāo)DNS服務(wù)器的域名與IP的映射。
如下所示:
- baidu.com IN NS ns1.domain.com
- baidu.com IN NS ns2.domain.com
- ns1.domain.com IN A 111.222.111.111
- ns2.domain.com IN A 123.111.222.111
除了上述類型,還有其他的記錄類型。感興趣的朋友可以自行查閱。
回答報文會包含多條資源記錄(RR),每條資源記錄包括4個字段:(Name, Value, Type, TTL)。分別是域名,域名對應(yīng)的值(如IP、權(quán)威DNS域名、郵箱域名等),記錄類型,記錄的有效時間。
2.域名層級
一個域名的層級從左到右依次提升,每個層級用.分開。以www.abc.com為例,com是頂級域名,com域的下一層是abc域,再下一層是www這個名字。
3.DNS服務(wù)器
DNS服務(wù)器本質(zhì)是一個存儲著域名與相應(yīng)信息映射關(guān)系的具有層級的、分布式數(shù)據(jù)庫集群。
(1) 存儲著域名與相應(yīng)信息映射關(guān)系
DNS服務(wù)器里面保存的數(shù)據(jù)我們稱之為資源記錄,如下所示:
當(dāng)帶有 域名、class和記錄類型 的請求報文到達(dá)DNS服務(wù)器后,它會根據(jù)這3個信息從資源記錄中找到這3個字段都匹配的記錄返回給客戶端。相當(dāng)于 select `響應(yīng)數(shù)據(jù)` from 表 where `域名`="xxx" and `class`="xxx" and `記錄類型`="xxx";
(2) 具有層級的、分布式數(shù)據(jù)庫集群
- 分布式:無論從服務(wù)器負(fù)載、數(shù)據(jù)備份和故障時高可用的角度來說,所有的域名信息不可能保存到一臺DNS服務(wù)器上,而是由多臺分布到世界上多臺DNS服務(wù)器共同維護(hù)。
- 具有層級:DNS服務(wù)器是具有層級的,其層級是根據(jù)域名的層級來劃分,由上到下分為 根域名DNS服務(wù)器、頂級域名DNS服務(wù)器和權(quán)威DNS服務(wù)器。
全世界的根域DNS服務(wù)器大概有十幾臺。
每一臺根域名服務(wù)器都知道所有頂級域名DNS服務(wù)器的域名和IP,而且不管哪一個本地域名服務(wù)器要對某個域名進(jìn)行解析而自己無法解析都會首先求助于根域名服務(wù)器。
每一層DNS服務(wù)器都保存著下一層DNS服務(wù)器的所有IP地址,并且所有層級的每一臺DNS服務(wù)器會保存所有根域的DNS服務(wù)器IP。這么一來就能做到在本地DNS服務(wù)器能找到根域DNS服務(wù)器IP,再從根據(jù)服務(wù)器逐層往下找到其他DNS服務(wù)器。
當(dāng)某一臺權(quán)威DNS服務(wù)器不能給出最后的查詢回答,就會告訴請求者下一步應(yīng)該找到哪個權(quán)威DNS服務(wù)器。
用戶主機(jī)向本地域名服務(wù)器的查詢都是采用遞歸查詢(所以用戶主機(jī)只用發(fā)出一次DNS請求即可得到想要的IP地址,其他的請求交給本地DNS服務(wù)器和其他DNS服務(wù)器即可),本地域名服務(wù)器向根域名服務(wù)器的查詢通常采用迭代查詢,但也可以采用遞歸查詢。
如下圖所示:
有了上面的擴(kuò)展知識后,我們再來說DNS報文發(fā)送到本地DNS服務(wù)器后發(fā)生了什么:
以www.lab.glasscom.com為例:
- DNS查詢報文到達(dá)本地DNS服務(wù)器后,如果本地DNS服務(wù)器沒有記錄目標(biāo)域名對應(yīng)的IP,則會將查詢轉(zhuǎn)發(fā)給根DNS服務(wù)器;
- 根域DNS服務(wù)器也沒有該域名的資源記錄,但判斷出其頂級域為com,所以會把com域的DNS服務(wù)器的IP返回給本地DNS服務(wù)器;
- 本地DNS服務(wù)器再根據(jù)這個IP向com域的DNS服務(wù)器發(fā)起查詢請求,但com域的DNS服務(wù)器也沒有www.lab.glasscom.com的資源記錄,但判斷出該域名的權(quán)威域名為glasscom.com,找到了glasscom.com域的DNS服務(wù)器的IP地址并返回。
- 本地DNS服務(wù)器向glasscom.com域的DNS服務(wù)器發(fā)起DNS查詢請求,查到了www.lab.glasscom.com的IP
- 最終本地DNS服務(wù)器將目標(biāo)IP返回給客戶端主機(jī),同時本地DSN服務(wù)器也會對該域名的IP映射進(jìn)行緩存。下一次被訪問到相同的域名時直接查詢DNS緩存而不再向根域DNS服務(wù)器發(fā)起請求
上面這種DNS查詢方式是迭代查詢,每次都是由本地DNS服務(wù)器發(fā)起請求,此外還有其他查詢方式如遞歸查詢,以及直接查詢DNS緩存。
下面我們看看遞歸查詢和迭代查詢的區(qū)別:
- 遞歸查詢:由本機(jī)查詢本地DNS服務(wù)器,本地DNS服務(wù)器如果沒有命中目標(biāo)域名則向根服務(wù)器請求,根服務(wù)器根據(jù)頂級域名找到對應(yīng)的頂級域名服務(wù)器的IP并向該頂級域名服務(wù)器發(fā)送請求,同理頂級域名服務(wù)器再向?qū)?yīng)的權(quán)威域名服務(wù)器發(fā)送DNS查詢請求的到目標(biāo)地址IP,并將其原路返回給本機(jī)。
如下圖展示了遞歸查詢過程:
- 迭代查詢:迭代查詢就是上文中提到過的查詢方式,本機(jī)請求本地域名服務(wù)器,本地域名服務(wù)器請求根域名服務(wù)器拿到頂級域名服務(wù)器的ip,本地域名服務(wù)器再去請求頂級域名服務(wù)器拿到權(quán)威域名服務(wù)器的ip,本地域名服務(wù)器再去請求權(quán)威域名服務(wù)器拿到目標(biāo)ip,再返回給本機(jī)。
如下圖:
下節(jié)預(yù)告:瀏覽器輸入一個網(wǎng)址發(fā)生了什么(二) TCP模塊封裝和傳輸機(jī)制