1. 程式人生 > 程式設計 >Bind進階

Bind進階

還是出於專案的需要,把Bind比較高階的功能做一個梳理,這其中包含:DNS遞迴迭代查詢、DNS子域授權、DNS轉發、DNS主從區域傳輸、DNS資料加密,每一個內容不僅記錄了它的實現原理,也相應的配上了我一行一行程式碼的實踐測試及結果。

所有的測試都是基於我原來的文章:Bind服務搭建及測試上的程式碼來進行的,所以下面的程式碼如果有不理解的,請去看看我之前寫的文章。

DNS遞迴迭代查詢

為什麼要把DNS的查詢稱之為遞迴迭代查詢:

遞迴是因為:

使用者端向我的服務端發起一次查詢請求,那麼服務端如果有結果就返回,如果沒有結果就像上一級伺服器再發一次請求,直到找到使用者需要的IP或者域名,這個過程可以稱之為遞迴。

迭代是因為:

當服務端向上一級伺服器法請求的時候,它並不是一次請求就結束了,先是根域,再是二級域名這樣了,有多次的請求跟返回動作,這個過程可以稱之為迭代。

我在Bind搭建及測試這篇博文裡面,對它們的流程做了更詳細的敘述,這裡就不多寫了。

引數

Bind既然有一個複雜的查詢流程,那麼與之相對應的就會有一系列的配置項來控制這個流程。下面講的引數都是基於Bind的主配置檔案named.conf。

  • recursion : {yes|no} 是否允許遞迴請求
  • allow-recursion : {addressmatchlist|any|none} 允許遞迴請求的範圍
  • recursion-clients : {number(填數字)} 客戶端執行遞迴請求的數量

測試

named.conf配置檔案的內容如下所示:

    options {
        directory "/var/named";
        recursion yes;
    };複製程式碼
    zone "." {
        type hint;
        file "named.ca";
    };複製程式碼
    zone "liumapp.com" {
        type master;
        file "liumapp.com.zone";
    };複製程式碼
    zone "cnametest.com" {
        type master;
        file "cnametest.com.zone";
    };複製程式碼
    zone "32.29.115.in-addr.arpa" {
        type master;
        file "115.29.32.zone";
    };
可以看到,我預設是把遞迴查詢開啟的複製程式碼
開啟遞迴的情況

隨便查詢一個域名,比如“www.qqq.com”1.jpg

可以發現,Bind為了找到www.qqq.com對應的IP地址,往上層域名伺服器迭代了7次才找到最終結果。

關閉遞迴的情況

現在我們將配置檔案的recursion改為no,重啟Bind之後再查詢一個新的域名,比如"www.qqqq.com"(www.qqq.com已經做了快取)

2.jpg

可以看到,關閉遞迴後我們是查不到新域名的解析記錄的。

DNS子域授權

在DNS迭代查詢的情況下,經常會用到NS記錄,同樣的,在DNS子域授權下面,NS記錄也會經常被用到。

子域授權:

比如我的一臺伺服器A負責liumapp.com的權威域名解析,它再授權伺服器B對liumapp.com的子域名:child.liumapp.com進行解析,這就叫做子域授權。

DNS迭代查詢利用的就是子域授權:通過根域,到二級域再依次往下迭代查詢。

測試

我的父伺服器IP為115.29.32.62,其解析的域名為www.liumapp.com,子伺服器IP為106.14.212.41,其解析的域名為www.test.liumapp.com

首先在父伺服器上,我們要對子伺服器進行授權,具體配置liumapp.com.zone檔案,新增如下內容:

    test.liumapp.com. IN NS ns1.test
    ns1.test IN A 106.14.212.41複製程式碼

大意就是給liumapp.com的子域名test.liumapp.com分配許可權給ns1.test,然後指定ns1.test的IP為106.14.212.41

重啟父伺服器,然後進入子伺服器的shell命令面板

首先我們對named.conf做一個備份,然後把它的內容修改為:

    options {
      directory "/var/named";
    };複製程式碼
    zone "test.liumapp.com" {
        type master;
        file "test.liumapp.com.zone";
    };
複製程式碼

然後在/var/named/目錄下新增一個test.liumapp.com.zone檔案,其內容為:

    $TTL 7200
    @ IN SOA test.liumapp.com. liumapp.com.gmail.com. (222 1H 15M 1W 1D)
    @ IN NS dns1.liumapp.com.
    dns1.liumapp.com. IN A 106.14.212.41
    www.test.liumapp.com. IN A 106.14.212.42
複製程式碼

接下來重啟Bind。然後我們進行測試,首先對父伺服器進行解析:

    dig @115.29.32.62 www.test.liumapp.com複製程式碼

結果為:

3.jpg

然後我們對子伺服器進行解析:

    dig @106.14.212.41 www.test.liumapp.com複製程式碼

結果為:

4.jpg

DNS轉發

概念

假設有一個區域網,內部有兩臺DNS伺服器,命名為A和B,區域網通過防火牆對外開放,但是隻有A能夠直接對外提供DNS解析服務,B只能在區域網內的內網進行訪問,那當需要用到B的DNS解析的時候,就是通過A的forwarding轉發來實現。

配置

首先看一下關於轉發的配置項

  • forwarders : {address_list} 表示轉發的伺服器列表
  • forwarder only : 表示只由目的伺服器權威解析
  • forwarder first : 優先轉發查詢

測試

同樣是父伺服器115.29.32.62和子伺服器106.14.212.41,我們現在把父伺服器用來負責DNS的某一個域作為轉發,子伺服器用來負責某一個域的權威解析。

現在我們先配置子伺服器的權威解析:

首先進入/var/named目錄,新建一個檔案dnstest.com.zone(這個域名我並沒有擁有它,只是為了測試方便隨便寫的),其內容為:

    $TTL 7200 
    @ IN SOA dnstest.com. liumapp.com.gmail.com. (222 1H 15M 1W 1D)
    @ IN NS dns.dnstest.com.
    dns.dnstest.com. IN A 106.14.212.41
    www.dnstest.com. IN A 6.6.6.6
複製程式碼

然後修改named.conf,新增下列內容:

    zone "dnstest.com" {
        type master;
        file "dnstest.com.zone";
    };複製程式碼

同時刪除原來的

    zone "test.liumapp.com" {
        type master;
        file "test.liumapp.com.zone";
    };複製程式碼

重啟Bind。

然後進入父伺服器的shell操作面板,在開始之前,我們要注意一點,就是Bind的DNS轉發只有在Bind9版本以上才支援,所以在開始之前,我們先使用命令檢視一下Bind的版本:

    nslookup -q=txt -class=CHAOS version.bind複製程式碼

我的伺服器上出來的結果是:

    [root@iZ28vhwdq63Z ~]# nslookup -q=txt -class=CHAOS version.bind.複製程式碼
    Server:  10.202.72.116複製程式碼
    Address:  10.202.72.116#53複製程式碼
    version.bind  text = "9.9.9-P3-RedHat-9.9.9-2.1.alios6"複製程式碼

然後修改named.conf,新增以下內容:

    zone "dnstest.com" {
      type forward;
      forwarders {106.14.212.41;};
    }複製程式碼

接下來我們在父伺服器上使用dig命令:

    dig @127.0.0.1 www.dnstest.com複製程式碼

請求解析www.dnstest.com域名,結果如下:

5.jpg

同時要注意,forward的正常使用需要遞迴查詢recursion開啟。

DNS主從區域傳輸

區域是DNS伺服器的管轄範圍,是由DNS名稱空間中的單個區域或由具有上下隸屬關係的緊密相鄰的多個子域組成的一個管理單位。 因此,DNS名稱伺服器是通過區域來管理名稱空間的,而並非以域為單位來管理名稱空間,但區域的名稱與其管理的DNS名稱空間的域的名稱是一一對應的。或者說,一個區域對應一系列域名的解析。

DNS主從同步

假設我們有兩臺伺服器,分別為dns主伺服器Master和dns從伺服器slave,那麼他們之間的dns主從同步步驟是這樣的:

  • master傳送notify資訊給slave
  • slave去查詢主伺服器的SOA記錄
  • master將SOA記錄傳送給slave
  • slave根據SOA記錄去檢查serial number是否有遞增更新
  • 如果有的話slave向master發起zone transfer請求,然後master返回響應結果,slave更新記錄。如果沒有的話就說明不需要更新。

DNS主從配置

在開始配置之前,先要注意幾個事項:

  • 確保防火牆的規則不會攔截Bind的監聽埠,預設為53
  • 確保named使用者擁有操作相關目錄的許可權(/var/named)
  • 確保主從伺服器的時鐘一致
  • 搭建完畢後,若修改主伺服器域的配置,serial number必須遞增
伺服器配置

Master伺服器

    zone "liumapp.com" {
      type master;
      notify yes;
      also-notify{106.14.212.41;};
      file "liumapp.com.zone";
    }複製程式碼

上面的notify yes表示開啟notify這個功能,also-notify{}裡面放的是slave伺服器的IP列表。

Slave伺服器

    options{複製程式碼
     directory  "/var/named";複製程式碼
     allow-query  { any; };複製程式碼
     recursion  yes;複製程式碼
    };
    zone "liumapp.com" {複製程式碼
     type  slave;複製程式碼
     file  "slaves/liumapp.com.zone";複製程式碼
     masters {115.29.32.62;};複製程式碼
    };複製程式碼

上面的file表示從主伺服器同步過來的資訊存放地址,我這裡就表示存放在/var/named/slaves/liumapp.com.zone

我把IP為115.29.32.62的dns server作為我的master,IP為106.14.212.41的dns server作為我的slave。

首先我們按照上面兩段程式碼進行主從伺服器的配置。

然後重啟兩臺伺服器的Bind,重啟之後,應該就能夠在從伺服器的/var/named/slaves/下找到一個liumapp.com.zone檔案,它的內容應該跟主伺服器的/var/named/liumapp.com.zone一致。

所以,這個時候我們不管使用命令

    dig @115.29.32.62 www.liumapp.com複製程式碼

向主伺服器請求www.liumapp.com的解析還是

    dig @106.14.212.41 www.liumapp.com複製程式碼

向從伺服器請求www.liumapp.com的解析,得到的結果最終都是一樣的。

測試

現在我們按照上面的配置走完了一遍之後,來測試一下主從伺服器之間的同步。

在Master伺服器的/var/named/liumapp.com.zone檔案上,我們新增一條解析記錄:

    liumei.liumapp.com. IN A 8.8.5.6複製程式碼

然後新增一下它的serial number值,也就是:

    liumapp.com.  IN  SOA  liumapp.com.  liumapp.com.gmail.com8 (225  1H  15M  1W 1D)複製程式碼

這條記錄裡面的倒數第5個數“225”,我們把它改為226即可。

重啟伺服器之後,敲命令:

    dig @106.14.212.41 liumei.liumapp.com複製程式碼

即可成功在子伺服器上解析到liumei.liumapp.com的記錄為8.8.5.6

DNS區域傳輸限制

首先,我們在本地一臺電腦上使用一個命令:

    dig @115.29.32.62 axfr liumapp.com複製程式碼

不出意外,應該能夠得到liumapp.com在115.29.32.62這臺DNS server上的所有解析記錄

6.jpg

但是從安全形度來講,我肯定不希望這樣的事情發生,所以就要用到傳輸限制。

方法

  • 基於主機的訪問控制
    通過主機IP來限制訪問。複製程式碼
    * allow-transfer : {address_list | none},允許域傳輸的機器列表
複製程式碼
  • 事務簽名
    通過金鑰對資料進行加密。
    事務簽名的測試我會放在後面的DNS資料加密裡面來做。
複製程式碼
測試

我們在主伺服器上的named.conf配置檔案中進行修改:

    zone "liumapp.com" {複製程式碼
     type  master;複製程式碼
     notify  yes;複製程式碼
     also-notify {106.14.212.41;};複製程式碼
     allow-transfer{106.14.212.41;};複製程式碼
     file "liumapp.com.zone";複製程式碼
    };複製程式碼

重啟Bind之後,回到本地電腦上,繼續使用命令:

    dig @115.29.32.62 axfr liumapp.com複製程式碼

結果如下,請求已被拒絕。

7.jpg

但是通過106.14.212.41是可以獲取資料的:

    dig @106.14.212.41 axfr liumapp.com複製程式碼

結果如下:

8.jpg

DNS資料加密

加密方式

  • DES 對稱加密
    * 概述:檔案加密和解密使用相同的金鑰,簡單快捷。
    * 流程:假定有傳送方A和接收方B,A和B有相同的金鑰,A傳送明文給B之前,通過金鑰和加密演演算法,將明文加密成密文,傳送給B,B再通過金鑰和解密演演算法,將密文解密成明文。複製程式碼
  • IDEA 非對稱加密
    * 概述:金鑰包括公鑰和私鑰,安全性較DES方式高。
    * 流程:假定有傳送方A和接收方B,B有自己的私鑰和公鑰,A需要獲取B的公鑰,獲取之後,A首先自己生成一個會話金鑰,然後這個會話金鑰通過B的公鑰進行加密,加密後傳送給B,B再通過自己的私鑰對它進行解密,從而得到A生成的會話金鑰。之後,A通過自己的會話金鑰將要傳送的明文進行加密,傳送給B,B通過事先得到的會話金鑰對傳送過來的密文進行解密從而得到明文。複製程式碼

DNS事務簽名

事務簽名可以通過兩種加密方式來實現,分別是:

  • TSIG:對稱方式
  • SIGO:非對稱方式

現在比較常用的是TSIG這種方法。

TSIG事務簽名

引數:

  • allow-transfer : {key keyfile}(key及key的檔案位置); 事務簽名的key

測試

首先我們進入主伺服器,然後生成key:

在主伺服器的/usr/key目錄下,注意賦予key目錄named使用者的讀許可權

輸入以下命令:

    dnssec-keygen -a HMAC-MD5 -b 128 -n HOST liumapp-key複製程式碼
  • -a : 加密演演算法
  • -b : 加密位數
  • -n : 可以選擇ZONE或者HOST
  • liumapp-key:金鑰名稱

我生成的公鑰檔案和私鑰檔案其內容如下所示:

9.jpg

然後我們複製私鑰裡面的那段key的內容,再進入/var/named/chroot/etc目錄,新建一個liumapp-key檔案

其內容為:

    key "liumapp-key" {複製程式碼
     Algorithm hmac-md5;複製程式碼
     secret "ghWgud4mhN11PKBIITgxbg==";複製程式碼
    };複製程式碼

上面的secret的值是從生成的私鑰檔案中複製來的。

然後編寫named.conf檔案,新增以下內容:

    include  "/var/named/chroot/etc/liumapp-key";複製程式碼

注意,這段內容要放在zone "liumapp.com"之前。

然後修改zone "liumapp.com"的配置,最終配置結果如下:

    include "/var/named/chroot/etc/liumapp-key";複製程式碼
    zone "liumapp.com" {
            type master;
            notify yes;
            also-notify {106.14.212.41;};
            allow-transfer{key "liumapp-key";};
            file "liumapp.com.zone";
    };複製程式碼

上面的allow-transfer的key的值是我命名的那個值。

然後我們重啟Bind,接下來是配置slave從伺服器,不過在配置之前,需要先把我們的配置檔案liumapp-key拷貝過去:

使用命令:

    scp liumapp-key [email protected]:`pwd`複製程式碼

結果如下所示:

10.jpg

然後在從伺服器的named.conf中進行配置,一個是把liumapp-key包含進去,然後配置key,最終結果如下所示:

    options{複製程式碼
     directory  "/var/named";複製程式碼
     allow-query  { any; };複製程式碼
     recursion  yes;複製程式碼
    };複製程式碼
    include  "/var/named/chroot/etc/liumapp-key";複製程式碼
    server  115.29.32.62 {複製程式碼
     keys {"liumapp-key";};複製程式碼
    };複製程式碼
    zone "dnstest.com" {複製程式碼
     type  master;複製程式碼
     file  "dnstest.com.zone";複製程式碼
    };複製程式碼
    zone "liumapp.com" {複製程式碼
     type  slave;複製程式碼
     file  "slaves/liumapp.com.zone";複製程式碼
     masters {115.29.32.62;};複製程式碼
    };複製程式碼

重啟從伺服器的Bind服務,然後我們再回到主伺服器:

新增一條liumapp.com.zone下的A記錄,當然還需要遞增一下serial number也不知道加了多少,總之最後我的這個ZONE的內容如下所示:

    $TTL 7200複製程式碼
    liumapp.com.  IN  SOA  liumapp.com.  liumapp.com.gmail.com8 (226  1H  15M  1W 1D)複製程式碼
    liumapp.com.  IN  NS  dns1.liumapp.com.複製程式碼
    dns1.liumapp.com.  IN  A  115.29.32.62複製程式碼
    www.liumapp.com.  IN  A  106.14.212.41複製程式碼
    liumei.liumapp.com.  IN  A  8.8.5.6複製程式碼
    heiheihei.liumapp.com.  IN  A  9.9.9.9複製程式碼
    @ IN  MX  10  mail複製程式碼
    mail  IN  A  115.29.32.63複製程式碼
    test.liumapp.com.  IN  NS  ns1.test複製程式碼
    ns1.test  IN  A  106.14.212.41複製程式碼

然後重啟bind,再使用命令:

    tail -f /var/log/messages複製程式碼

得到的資訊如下所示:

11.jpg

可以看到,我修改了liumapp.com.zone之後,主伺服器馬上同步到了從伺服器上,而他們之間的交流,就是用到了TSIG事務簽名。