2016年12月21日 星期三

DNS 未經過授權 解說

記得在多年前對 DNS 濛濛懂懂的年代在�� nslookup 工具查詢網址時都會有個疑問,那就是在查詢的過程中經常都會遇到查詢的結果顯示 未經授權的回答 Non-authoritative answer ) 的提示,看不懂是什麼意思,最近剛好有人在問我這個問題,所幸就把我知道的給寫出來跟大家分享。
前幾天寫的【釐清 DNS Client 查詢過程的異象 ( 當名稱伺服器停用遞迴時 ) 】文章講的是 DNS 查詢會有遞迴查詢的觀念,當 DNS 伺服器啟用了遞迴查詢的功能後,當使用 DNS Client ( 例如 nslookup ) 就可以透過這台 DNS 伺服器查到任何一個域名(Domain Name)。
以下是使用 nslookup 查詢的一個範例:
C:\>nslookup -type=a www.miniasp.com 168.95.1.1
伺服器:  dns.hinet.net
Address:  168.95.1.1

未經授權的回答:
名稱:    miniasp.com
Address:  58.86.49.47
Aliases:  www.miniasp.com
以下是執行 nslookup 指令時的圖示:


在這裡的 未經授權的回答 (Non-authoritative answer) 是微軟的制式翻譯,這裡的中文翻譯其實很容易被人們誤解為跟「權限」有關的問題,但事實上跟「權限」一點關係都沒有!
其實 DNS 伺服器在啟用遞迴查詢時 (Microsoft DNS 預設是啟用的),其流程如下:
  1. 用戶端 ( DNS Client , nslookup ) 從電腦註冊的 DNS 伺服器 ( Name Server , NS ) 查詢域名。
  2. 當你本機所指定的 DNS 伺服器 ( NS ) 在這台 NS 找不到任何快取記錄時,這時就會開始 遞迴查詢 (Recursive Query) 或 反覆查詢 (Iterative Query) 的過程,透過這個過程幫你找出最終的域名所屬的 IP 位址 ( A 紀錄 ) 或其他類型的 DNS 紀錄。如果已經有快取資料在的話,就會直接回應先前查詢過的結果給用戶端。
以下解釋 遞迴查詢 (Recursive Query) 或 反覆查詢 (Iterative Query) 的差別:
遞迴查詢 是指這台 NS 會幫你透過其他台 NS 查詢資料,也就是透過 DNS 伺服器所設定的 轉寄站 (Forwarder) 幫你查詢出結果,這種設定對你的 NS 的負擔比較輕,因為如此一來你這台 NS 就只要把查詢的任務交給其他台 NS 幫你查詢出結果就行了,一般來說大部分的 NS 都是這樣設定的。
以 Microsoft DNS 來說,只要有設定「轉寄站」的 DNS 伺服器就等於是啟用「遞迴查詢」的方式運作:


反覆查詢 是會直接在這台 NS 幫你一步一步的查詢出這個域名的結果,也就是如下圖的方式一步一步的反覆查詢出結果:
以上圖查詢 girlgirl.gbrmpa.gov.au 這筆 A 紀錄 (Address Record) 為例,其執行反覆查詢的流程如下:
  1. Resolver 向 Name Server 查詢一個域名 ( girlgirl.gbrmpa.gov.au )
  2. 由於 Name Server 並無任何快取紀錄,又沒有 轉寄站 (Forwarder) 可使用時,就會啟用反覆查詢,並且從 根提示 ( Root Hint ) 開始查起,首先先查出 gTLD 或 ccTLD 的 NS 紀錄 ( 如上圖 Refer to au NS 說明 )
  3. 再透過 gTLD 或 ccTLD 查出 gov.au 這筆 NS 紀錄 ( 如上圖 Refer to gov.au NS 說明 )
  4. 再透過 gov.au 這筆 NS 紀錄查出 gbrmpa.gov.au 這筆 NS 紀錄
  5. 再透過 gbrmpa.gov.au 這筆 NS 紀錄查出 girlgirl.gbrmpa.gov.au 這筆 A 紀錄
如上述步驟 1 ~ 5 有個很重要的觀念,也就是從頭到尾都是不斷的向 NS 查詢 girlgirl.gbrmpa.gov.au 這筆 A 紀錄,只是當查不到 A 記錄的時候,就會回傳該 NS 所擁有的 NS 紀錄,如此一來才能都過反覆的方式逐一找到最終要查詢的 A 記錄。
接下來我要對我上述對 DNS 的理解所進行的觀念驗證 ( PoC ) 步驟,以下將會以查詢 blog.miniasp.com 這筆 A 記錄的反覆查詢過程為主,我會使用 nslookup 工具完成所有的反覆查詢動作,以模擬 DNS 伺服器在做反覆查詢時的過程:
由於我們要先從「根提示」所提供的 Root Nameserver 開始查起,所以我們先參考 Microsoft DNS 中定義的 Root NS 開始查詢起,任意選壹台 NS 都可以。

1. 先查詢 Root Hints 的資料,當查不到資料時,請注意如下的結果中有個 Served by: 字樣,這就代表這個域名可以透過如下的 Nameserver 找到進一步的資料!
C:\>nslookup -type=a blog.miniasp.com 198.41.0.4
198.in-addr.arpa        nameserver = U.ARIN.NET
198.in-addr.arpa        nameserver = DILL.ARIN.NET
198.in-addr.arpa        nameserver = W.ARIN.NET
198.in-addr.arpa        nameserver = V.ARIN.NET
198.in-addr.arpa        nameserver = X.ARIN.NET
198.in-addr.arpa        nameserver = Z.ARIN.NET
198.in-addr.arpa        nameserver = T.ARIN.NET
198.in-addr.arpa        nameserver = Y.ARIN.NET
伺服器:  UnKnown
Address:  198.41.0.4

名稱:    blog.miniasp.com
Served by:
- i.gtld-servers.net
          192.43.172.30
          com
- a.gtld-servers.net
          192.5.6.30
          2001:503:a83e::2:30
          com
- g.gtld-servers.net
          192.42.93.30
          com
- d.gtld-servers.net
          192.31.80.30
          com
- k.gtld-servers.net
          192.52.178.30
          com
- b.gtld-servers.net
          192.33.14.30
          2001:503:231d::2:30
          com
- j.gtld-servers.net
          192.48.79.30
          com
- l.gtld-servers.net
          192.41.162.30
          com
- f.gtld-servers.net
          192.35.51.30
          com
- e.gtld-servers.net
          192.12.94.30
          com
2. 我們再任意選壹筆他建議的 Nameserver 查詢 blog.miniasp.com 這筆 A 記錄,透過這次的結果已經可以看出這兩台已經看到是由我們公司自行管理的 NS 伺服器了,不過這時還沒查到最終的 A 紀錄,所以還要走一次反覆查詢。
注意: miniasp.com 這個域名的 NS 紀錄必須從 gTLD 查到,而非你自行管理的 DNS 伺服器喔,且該 gTLD 上的紀錄只能透過 域名註冊商 ( domain name registrar ) 那邊幫你註冊進 gTLD 裡,你自己是無法進行登錄的,相關文章請參考【在國內外各家域名註冊商更新 Nameserver 紀錄的注意事項】。
C:\>nslookup -type=a blog.miniasp.com 192.12.94.30
(root)  nameserver = f.root-servers.net
(root)  nameserver = g.root-servers.net
(root)  nameserver = h.root-servers.net
(root)  nameserver = i.root-servers.net
(root)  nameserver = j.root-servers.net
(root)  nameserver = k.root-servers.net
(root)  nameserver = l.root-servers.net
(root)  nameserver = m.root-servers.net
(root)  nameserver = a.root-servers.net
(root)  nameserver = b.root-servers.net
(root)  nameserver = c.root-servers.net
(root)  nameserver = d.root-servers.net
(root)  nameserver = e.root-servers.net
伺服器:  UnKnown
Address:  192.12.94.30

名稱:    blog.miniasp.com
Served by:
- ns2.miniasp.com
          61.56.130.54
          miniasp.com
- ns1kbt.miniasp.com
          58.86.49.53
          miniasp.com
3. 接著,我們再任意選壹筆他建議的 Nameserver 查詢 blog.miniasp.com 這筆 A 記錄,這次的結果就已經正式出爐了,請看下圖 Address 欄位就是我們要的答案,不過這裡顯示的「名稱」欄位卻不是我們指定的域名,我們所查出的域名是出現在 Aliases 欄位,這代表了 blog.miniasp.com 這筆資料的記錄類型並不是一個 A 紀錄,而是一個 CNAME (別名) 紀錄。
C:\>nslookup -type=a blog.miniasp.com 58.86.49.53
伺服器:  UnKnown
Address:  58.86.49.53

名稱:    cisa.miniasp.com
Address:  58.86.49.46
Aliases:  blog.miniasp.com
4. 雖然我們已經查出 blog.miniasp.com 所對應的 IP 位址,但事實上 NS 伺服器在查到這筆記錄後,還會再到如上的這個名稱 cisa.miniasp.com 查詢出最終的 A 紀錄,這時才會完成所有反覆查詢的步驟。
我們先模擬查詢 CNAME 紀錄,得到的 canonical name 結果是 cisa.miniasp.com :
C:\>nslookup -type=cname blog.miniasp.com 58.86.49.53
伺服器:  UnKnown
Address:  58.86.49.53

blog.miniasp.com        canonical name = cisa.miniasp.com
miniasp.com     nameserver = ns1kbt.miniasp.com
miniasp.com     nameserver = ns2.miniasp.com
ns1kbt.miniasp.com      internet address = 58.86.49.53
ns2.miniasp.com internet address = 61.56.130.54
然後再查詢 cisa.miniasp.com 的 A 紀錄,走到這一步所有 DNS 查詢的過程終於執行完畢!
C:\>nslookup -type=a cisa.miniasp.com 58.86.49.53
伺服器:  UnKnown
Address:  58.86.49.53

名稱:    cisa.miniasp.com
Address:  58.86.49.46
最後,請各位再回顧一下上述 PoC 的過程是否有任何一次查詢出現 未經授權的回答 (Non-authoritative answer) 的訊息?並沒有!因為這些查詢都是 權威的答案 (authoritative answer),也是可靠的答案的意思,也代表這些查詢的結果並非從 NS 的快取中取得的結果,所以其結果是可被相信的!(註:果要解釋成「經授權的回答」可能比較難以理解,所以寫了好長一段解釋 DNS 查詢的過程。
因此,什麼時候在利用 nslookup 查詢時會得到 未經授權的回答 (Non-authoritative answer) 這個提示呢?
  1. 當查詢的 DNS 伺服器在自己這壹台 NS 有快取紀錄時 
    註:因為 DNS 預設都會啟用快取機制,以增加 DNS 查詢的效能
  2. 當查詢的DNS 伺服器有設定  轉寄站 (Forwarder) 時 
    註:因為查詢並非 NS 自己透過反覆查詢出來的,其查詢的結果可能是錯誤的快取資料
除了以上兩個原因外,只要是啟用了遞迴查詢且沒有設定 轉寄站 (Forwarder) 時,本地端又沒有快取時,通常查到的資料就一定是 權威的答案 (authoritative answer),也不會出現 未經授權的回答 (Non-authoritative answer) 的訊息提示!
在 Microsoft DNS 裡有個【如果沒有可用的轉寄站,則使用根提示】的選項,如果有勾選的話,當 轉寄站 (Forwarder) 都無法連線時,就會改以 反覆查詢 (Iterative Query) 的方式從 根提示 ( Root Hint ) 開始查起,如果沒勾選的話,查不到就會直接放棄查詢。

§ 補充說明 §
如果你從壹台 DNS 查詢到的結果永遠都是「未經授權的回答」的話,那麼幾乎可以斷定這台 DNS 的背後還有一個「轉寄站」在幫忙查詢 DNS,估計 168.95.1.1 就是這樣的模式。
心得分享
DNS 的運作機制在網路的世界站著舉足輕重的地位,像是 Active Directory 就極度依賴 DNS 的運作,而我們在替客戶代管域名時,一些 DNS 伺服器設定的細節也經常需要這些基礎知識與觀念支持才能一次正確設定到位,否則就會開始出現一些在 IT 界俗稱的靈異現象。

我在這幾年公司招聘人才的過程中 DNS 運作流程是我每人必考的問題,不過鮮少有人能夠將 DNS 運作流程解釋透徹的,這點實屬可惜,希望透過這篇文章與 PoC 可以讓更多人能理解 DNS 運作的過程。

Windows NTP SERVER

○ Step1:開啟 FireWall Rule:開啟 DC 對要對外校時的 Server IP,Service Port 為 123,UDP。
○ Step2:關掉 Time Service
  命令提示字元(MS-DOS 模式):net stop w32time
○ Step3:設定 NTP Server
  命令提示字元(MS-DOS 模式):net time /setsntp: <servername> <----紅色部分換成公司 NTP server IP address  
  指令範例:
  1. net time /setsntp:clock.stdtime.gov.tw 
  2. net time /setsntp:123.111.0.111
  3. net time /setsntp:”clock.stdtime.gov.tw tick.stdtime.gov.tw 129.6.15.28”
○ Step4:檢查是否有設定成功
  命令提示字元(MS-DOS 模式):net time /querysntp
○ Step5:啟動 Time Service   
    命令提示字元(MS-DOS 模式):net start w32time <--- 這步驟也要做
○ Step6:重開後校時不會立刻生效,須等待一些時間後才會生效。    
設定Windows Server為NTP Server

1.設定成為NTP 伺服器類型

修改登錄檔中"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters"
下面[Type]設定值修改為NTP。

2.設定授權時間伺服器

修改登錄檔中"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config"
[AnnounceFlags]修改設定值為5

3.啟用NTP伺服器

修改登錄檔中"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer"
[Enabled]數值修改為1

4.指定查詢外部NTP 伺服器

修改登錄檔中"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters"
[NtpServer]數值修改為time.stdtime.gov.tw,0x1

5.設定查詢時間間隔

修改登錄檔中"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient"
[SpecialPollInterval]修改數值為"十進位"900

*這邊使用的時間間隔單位為秒,設定900即為每900查詢一次步驟四所指定的時間伺服器。

6.設定時間修正設定
修改登錄檔中"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config"
[MaxPosPhaseCorrection]修改為十進位1800
[MaxNegPhaseCorrection]修改為十進位1800

*這邊單位也是秒

7.重起Windows Time服務。

2016年12月1日 星期四

bach script

[Linux] Bash script 讀檔

摘要:[Linux] Bash script 讀檔
#! /bin/bash

filename=XXX

## 讀檔 word by word
for WORD in `cat $filename`
do
    echo $WORD
done


## 讀檔 line by line
while read LINE
do
    echo $LINE
done < $filename