關於我遇到的一個DNS問題

clipboard.png

最近遇到一個小問題,在某些用戶的請求中會莫名其妙的出現重定向然後導致404,在這裏分享下導致這種問題的原因。

這裏不會介紹DNS和CDN,如果想了解請google或百度,有好幾斤的數據可以看,我也沒必要再說了。這篇文章主要是從關於客戶端DNS解析和CDN服務解析的整個流程角度去解釋我遇到的這個很幼稚的bug

DNS服務器可以部署在很多階段

DNS對於大多數同學來說都可能知道是幹嘛的,但是深入瞭解工作原理可能有些模糊,首先它它分佈在很多個階段,整體分爲兩大塊:本地DNS服務,遠端DNS服務。

本地(Local Resolver)

每臺電腦本地都會配置一個DNS解析文件,在Nginx上我們可以在 /etc/resolv.conf 中查看,當然也可以從界面中查看。

下面是我在CLI查看我的本地DNS服務配置,即DNS客戶機配置(/etc/resolv.conf)
clipboard.png

下面是我在設置中查看DNS服務配置
clipboard.png

大家會問,這兩個一樣嗎?只不過一個是在文件系統查看一個是在GUI上查看,兩者沒區別吧?嗯,是的沒區別。

實際上,修改本地的DNS解析規則,在Nginx上有三個地方,分別是

hosts文件-->網卡配置文件-->DNS服務器地址配置文件

我們剛纔修改的只是系統的DNS服務器地址配置文件,當然GUI上也是對應的這個文件。前兩個配置方式比較粗暴,在這裏就不講了,有傷大雅。

分析一下配置文件中的字段(實際上還有很多,先說兩個吧):

  1. domain提供一個基本的搜索域,解析失敗的域名會和這個基本的搜索域拼接,再去做DNS解析,看我下面偷的這一句話,就明白它的作用了。例如,如果您指定搜索域爲 apple.com,在您的網頁瀏覽器中鍵入“store”將會前往 store.apple.com。或者,如果使用 campus.university.edu 作爲搜索域,那麼您可以在“訪達”的“連接服務器”對話框中鍵入“server1”來連接到 server1.campus.university.edu。
  2. nameserver,也就是本地的DNS服務器列表,它的格式是IP地址,v4 v6 d都可以,遠端或本地地址都可以,甚至這個地址可以填寫一個本地的服務,然後我們就可以自定義處理DNS解析服務了。

nameserver這個字段就太好玩了,通常家庭版的地址是192.168.0.1,也就是大多數路由器的IP地址,然後用戶可以在自己的路由器設置頁面配置DNS解析服務器的地址。below

clipboard.png

當然,你也可以不使用路由器來轉發你的DNS解析,直接填寫這個根DNS服務器地址,也就是圖上面的222.*。

作爲程序員,突發奇想,我們還可以玩的更浪一些~~~,就比如:

添加一個本地域名解析服務,也就是添加一個127.0.0.1在你的DNS配置文件中,注意一定要添加在第一行,別忘了nameserver是in order的哦。

clipboard.png

然後在本地開一個UDP服務,監聽53端口(爲什麼是UDP爲什麼是53端口,好奇同學請trace here),你就會看到本地的DNS處理記錄:

let dgram = require('dgram');
let socket = dgram.createSocket('udp4');
// 服務端監聽一個端口 數據到來時 可以讀出信息
socket.bind(53,'localhost',function(){
    //讀取消息
    socket.on('message',function(data,rinfo){
        console.log(data.toString());
    })
});

下面這些亂七八糟的,就是DNS解析記錄...

clipboard.png

我們可以修改上面的代碼來自定義解析後的信息,我不知道這個返回狀態應該怎麼設定,沒事閒的同學可以去查查怎麼可以僞造這個信息,聽起來很刺激... 不過我覺得不太可能,53端口受特殊保護,就連監聽和查看它的佔用情況都需要提權,上述代碼linux上出EACCES錯的可以加上sudo,win提權太麻煩不說了。

說了 一大堆沒用的,回正題,現在開始我們假設本地DNS服務接受了一個軟件的解析請求~~

我們假設上述的 hosts文件-->網卡配置文件-->DNS服務器地址配置文件,前兩個不做任何處理的情況下。以下順序處理。

  1. 在DNS解析服務開始之前,系統會找到本地的這個DNS服務器列表,在我這是兩個,10.10. and 10.120. 從第一個開始向這個DNS服務器發送域名解析請求。
  2. 如果第一個處理失敗,或者查詢不到,就用第二個找。也就是 10.120.*。
  3. 如果10.120.*也找不到(最後一個nameserver),那麼使用這個domain來處理了。

本地DNS服務的任務就是接受計算機軟件的DNS解析服務,去向根DNS服務器發送請求,獲得最終的IP地址。

如果本地有 DNS resolver 的話,也是可以緩存你的DNS解析的,什麼是Resover?就是咱們剛纔建立在53端口的服務,它就是一個Resolver。

// 驗證是否存在 resolver
sduo lsof -i:53
// or 查看 /etc/resolv.conf 

resolver 有可能緩存上一次DNS解析結果。如果碰到惡意的resolver,看誰不順眼就可以篩選所有某站的主域名(比如競爭對手的...嘿嘿)返回一個不存在的ip地址,然後這個域名在那臺電腦上就over了,除非技術手動撤銷這個resolver,否則卸載重裝,重啓,統統不好使。

所以,友情提醒:儘量不要使用本地的DNS resolver。

根DNS(Root DNS)

接着從上面的本地DNS服務開始說,它把解析請求發送給 20.20.* 服務器,這個服務器就是根DNS,所有DNS解析請求都經過它來轉發
根DNS服務器免費的沒有幾個,國內的114.114*比較快一點,國外的Google的4個8或者4個1,都是普遍使用的。那麼又一個問題,世界上這麼多電腦才這麼幾個服務器,而且每臺電腦的DNS解析請求是非常頻繁的,這幾個服務器受得住嗎?

首先,它確實是接受所有的請求的,但它不負責處理這個解析,只負責分類並返回子DNS服務器IP。然後LocalDNS接收到這個子DNS服務器IP後,再去向子DNS迭代查詢。

這個階段,如果你本地有DNS緩存服務的話,它會記住某個域名與它所屬的子DNS的IP地址,下次請求直接去子DNS地址,而不用經過ROOT DNS處理。

子DNS

子DNS分很多區,這個分類其實就是根據域名的後綴來的,比如,有 COM DNS 服務器,它只負責 com這個後綴的域名解析。當然還有其他類型的,比如 .cn .net。當然,不可能每個後綴都來一臺服務器,流量較少的的後綴應該被分在一個區裏。

子DNS接到LocalDNS請求之後,查詢此域名之後發現它已經交給專屬DNS服務器(也就是你購買域名時設置的域名解析服務器)處理

子DNS的作用就是幫助RootDNS減少很多查庫和處理請求的時間。

服務器DNS

服務器DNS屬於我們域名下的專屬DNS服務器,我們可以使用自己的DNS服務器配置到你的域名上(申請DNS服務器需要到國內註冊局申請辦理)。

如果是本地內網搭建,就沒那麼多規則,可以使用Bind ((Berkeley Internet Name Domain))。

通常,我們在阿里雲購買的域名綁定上域名解析就可以了,默認使用的是萬網的DNS服務器,如果你有自己的DNS服務器的話,可以在域名管理中配置。

最後來張圖通一通。以我司客戶端爲例:

  1. LocalDNS 接收到一個客戶端發送的域名解析請求,看看本地有沒有上次緩存的現成的hetao101域下的DNS服務器。如果沒有,取出第一個nameserver(也就是根DNS服務器),進行迭代查詢。如果有,直接跳到第5步。
  2. 根DNS解析我們的www.hetao101.com地址屬於 com 區,然後把 com 區的子DNS服務器的IP返回給LocalDNS處理。
  3. LocalDNS收到子DNS的IP,然後再次發送迭代查詢向子DNS
  4. 子DNS查詢數據庫,找到www.hetao101.com這個域名對應的服務器DNS地址,然後把地址返回給LocalDNS
  5. LocalDNS發送請求到www.hetao101.com的DNS 服務器,然後返回給它域名對應的IP地址。
  6. LocalDNS拿到IP後非常雞凍(來回串了這麼多服務器終於拿到了),趕緊握握手親熱親熱,然後開始了建立網絡通道(e.g TCP)。

注意,以上的遞歸查詢和迭代查詢的區別,遞歸查詢的是:我向A請求,A你必須得給我一個結果,不到黃河不死心。而迭代查詢是,我向A請求,A有可能沒有這個東西,它把B返回給你,讓你和B問...

clipboard.png

CDN服務器

網絡就是數個燈泡中間的導線,電線長了,電流抵達的速度也就慢了,燈泡亮的速度就慢了。。。

所以,我們在導線的中間加上了一個繼電器式的資源服務器。也就是CDN服務器。保證資源快速響應給局部用戶。

CDN服務器通常包括一個源站和子節點(其他區域的資源服務器),上傳文件到CDN服務器首先到達源站,然後源站分發給子節點。

如果源站的資源被替換或者刪除,子節點也會與它同步。

簡單的打了個比方,具體使用場景及原理,可以自行Goog,不多說了廢話了,下面簡單說下我遇到那個問題。

最近遇到一個小問題,在更新資源文件後,在某些用戶的請求中會莫名其妙的出現302然後重定向地址是404,在這裏分享下導致這種問題的原因。

上下文:這個請求是阿里雲OSS的,客戶是河北滄州移動運營商,重定向後的IP地址後面添加相比源路徑多了很多層路徑,位置是河北石家莊的移動網絡。

我一開始的分析是,本地DNS服務或運營商緩存了DNS解析(阿里雲DNS解析後的IP是可以根據客戶端的區域分配就近節點的,所以應該被分到了石家莊節點),然後當我更新這個文件時,由於ISP緩存沒有到期(假定是ISP,還有可能是本地DNS Resolver),然後更新文件後,繼續請求上次的解析後的地址(地址上是有文件的hash的),導致資源404(hash值被更新)。

仔細想一下是不對的,首先DNS解析只會返回域名區段,不會給你添加路徑。第二如果是阿里雲子節點在上傳文件到源站的時候,就會同步到各個子節點,所以不會出現404的情況。

那麼,如果這個重定向的IP地址不是阿里雲的,難道是運營商自己的,它把響應文件緩存起來,然後放到自己的緩存服務器,如果請求在緩存期內就從運營商自己的緩存服務器裏取?我估計這個也不可能,因爲,條件是每次在阿里雲OSS上更新文件時,纔會出現這個問題,所以,有兩種可能:

  1. 因爲資源是和阿里雲源站同步的,所以,可判定這個地址並不是運營商的地址(是阿里雲的)。
  2. DNS劫持,劫持和緩存一樣,區別是前者以攻擊爲目的,給你返回期望之外的IP,後者是給你目標IP。

而當我分析上面說的302返回的重定向地址時,我不太確信這是一個DNS劫持,因爲這地址看起來太正經,如:

http://111.**.135.171/files/317200004364C385/***.oss-cn-beijing.aliyuncs.com/***.zip

第一段 IP,後面的的路徑非常有規律,files下面的file hash,然後是源站的下載地址。

這麼正經的IP不可能是被劫持吧,那麼再說回去,如果302是運營商的DNS緩存導致的,302後的地址也就是這個地址,它是怎麼來的呢??

我分別測試了山東和杭州的網絡,DNS解析***.oss-cn-beijing.aliyuncs.com這個源下載地址並沒有返回動態子節點IP,實際上還是beijing區的源站IP,這說明DNS解析是沒有動態返回節點的。

不是運營商也不是阿里雲,究竟是什麼?

愁了我一個星期,在阿里雲棲社區問了此問題,也沒有收到特別準確的回答,因爲用戶的問題已經使用其他方式修復,所以沒有辦法再次確定問題,目前只能認爲是

  1. DNS劫持。
  2. 運營商緩存文件之後不是直接從他自己文件服務器拿的,而是去向上次阿里雲OSS的地址取(是IP地址,沒有域名),但是我是替換的文件,按道理來說即便是舊的地址運營商向阿里雲請求也可以拿到文件呀,這裏還有一個小知識。那就是DNS解析後的IP是不能直接替換域名的,DNS是爲了取IP,而IP是在建立連接層之根基,但是連接層上還有寫一層,一些服務器上的httpserver,比如Apach或者Nginx會提供一個叫做虛擬站點的功能,簡單來說根據你請求的host(域名)來分撥出不同的文件路徑,也就是說一臺服務器是可以享有多個域名的。當然不僅是分撥路徑,中間還可以去向其他服務請求(有點像proxy,但是根據域名來判斷的proxy分撥),想了解更多請搜索 虛擬站點

如果你對於我的問題有其他看法,請評論。
如果你覺得我說的不對,請糾正(有懸賞)。
如果你想跳槽,請看我的個人資料右上角。
如果你覺還有點幫助,請使勁兒點個贊。
如果你覺得這篇文章浪費了你的時間,沒啥乾貨,請私聊大聲的罵我一頓。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章