出自 Arch Linux 中文维基

Unbound 是一個具有驗證,遞歸和緩存等功能的 DNS 解析器。根據Wikipedia

Unbound has supplanted the Berkeley Internet Name Domain (BIND) as the default, base-system name server in several open source projects, where it is perceived as smaller, more modern, and more secure for most applications.

安裝

安裝 unbound 軟體包。 此外, expat 是使用DNSSEC驗證請求所必須的。

配置

默認配置已經位於/etc/unbound/unbound.conf文件中。此外,/etc/unbound/unbound.conf.example文件包含了其他的可配置設置項,並以注釋的形式給出了示範設置。以下章節重點解釋和默認配置文件不同的設置項。如需了解更多細節,參見unbound.conf(5)

除非特別聲明,這一節列出的選項都是放置在配置文件的server節中,類似這樣:

/etc/unbound/unbound.conf
server:
  ...
  setting: value
  ...
注意: 請確保你的配置文件中已經設置了do-daemonize: no,否則unbound.service會無法啟動.

本地DNS伺服器

如果你想要使用unbound作為本地DNS伺服器,請把resolv.conf中的域名伺服器(nameserver)設置到迴環地址::1127.0.0.1。你可能想要讓你的配置Domain name resolution#覆蓋 /etc/resolv.conf

提示:實現這個目的的一個簡便方法是安裝openresolv,然後取消文件/etc/resolvconf.conf中包含name_servers="::1 127.0.0.1"的那一行的注釋。然後運行resolvconf -u來重新生成/etc/resolv.conf

要了解如何測試設置項,參見Domain name resolution#Lookup utilities

在把resolv.conf中的設置更改為持久化設置後,請特別注意檢查正在使用的伺服器是::1127.0.0.1

你還需要對「unbound」進行設置,以使它#轉發查詢到你所選擇的DNS伺服器。

訪問控制

你可以通過IP位址來指定響應請求的埠。默認監聽的是localhost

為了在所有埠上監聽,使用以下配置:

interface: 0.0.0.0

為了通過IP位址來控制可以訪問伺服器的系統,使用access-control選項:

access-control: subnet action

例如:

access-control: 192.168.1.0/24 allow

action可以是deny (drop message), refuse (polite error reply), allow (recursive ok), or allow_snoop (recursive and nonrecursive ok)中的任意一個。默認除了localhost之外的所有東西都會被拒絕。

使用DNS over TLS進行轉發

為了使用這個功能,你需要設置tls-cert-bundle選項來指定本地系統的根證書認證包,以使得unbound可以轉發TLS請求並指定允許DNS over TLS的伺服器數量。

對每個伺服器你都需要用 @ 來指定連接的埠,同時你也要用 # 來指明它的域名是什麼。雖然它看起來像注釋,the hashtag name allows for the TLS authentication name to be set for stub-zones and with unbound-control forward control command。在 @ 和 # 之間不應該有空格。

/etc/unbound/unbound.conf
...
server:
...
	tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt
...
forward-zone:
        name: "."
        forward-tls-upstream: yes
        forward-addr: 1.1.1.1@853#cloudflare-dns.com

根域名伺服器

為了查詢一個沒有被緩存成地址的主機,解釋器需要從伺服器樹的根開始、對根伺服器進行請求來知道去哪裡找到目標地址的頂級域名。Unbound內置了一些根節點,但是推薦你提供一個根節點文件給它以免內置的過於老舊。

首先,告訴unbound使用root.hints文件:

root-hints: root.hints

然後把你的root hints文件放進unbound的配置文件夾。實現這個目標最簡單的方法是運行下面的命令:

# curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache

建議每六個月更新一次root.hints來保持根伺服器列表是最新的。你可以手動完成這個任務,也可以使用Systemd/Timers。詳情參見#根域名伺服器與systemd timer

DNSSEC驗證

Tango-view-refresh-red.png本文內容或本節內容已經過期。Tango-view-refresh-red.png

原因: DNSSEC默認啟用.[1]. (在Talk:Unbound討論)

為了使用DNSSEC驗證,你需要在server:節中添加以下設置來告訴unbound伺服器根證書文件的位置:

/etc/unbound/unbound.conf
trust-anchor-file: trusted-key.key

/etc/unbound/trusted-key.key是從依賴項dnssec-anchors所提供的的/etc/trusted-key.key複製而來的,它的PKGBUILD按照unbound-anchor(8)生成了/etc/trusted-key.key

如果總的#轉發查詢設置到了不支持DNSSEC的DNS伺服器,那麼請確保已經把這些DNS伺服器注釋掉,否則DNS請求會失敗。DNSSEC驗證只會在被請求的DNS伺服器支持它的時候成功完成。

注意: 如果使用DNSSEC,在地址被緩存之前DNS查詢時間將會顯著增加。

測試DNSSEC

為了測試DNSSEC是否工作,在starting unbound.service之後:

$ unbound-host -C /etc/unbound/unbound.conf -v sigok.verteiltesysteme.net

得到的回應應該是附帶(secure)字樣的ip地址。

$ unbound-host -C /etc/unbound/unbound.conf -v sigfail.verteiltesysteme.net

這次的回應應該包含(BOGUS (security failure))字樣。

另外你也可以使用「drill」來測試:

$ drill sigok.verteiltesysteme.net
$ drill sigfail.verteiltesysteme.net

第一個命令應該返回NOERRORrcode;而第二個命令應該返回SERVFAILrcode

轉發查詢

如果你只想轉發請求到外部的DNS伺服器,請跳到#轉發所有其餘的請求

允許本地網絡使用DNS

使用openresolv

如果你的網絡管理器支持openresolv,你可以通過設置來使它提供本地DNS伺服器、使用unbound來查詢域名。 [2]

/etc/resolvconf.conf
...
private_interfaces="*"

# Write out unbound configuration file
unbound_conf=/etc/unbound/resolvconf.conf

運行resolvconf -u來生成文件。

配置unbound讀取openresolv生成的文件並允許回應private IP address ranges

/etc/unbound/unbound.conf
include: "/etc/unbound/resolvconf.conf"
...
server:
...
   private-domain: "intranet"
   private-domain: "internal"
   private-domain: "private"
   private-domain: "corp"
   private-domain: "home"
   private-domain: "lan"

   unblock-lan-zones: yes
   insecure-lan-zones: yes
   ...

另外你可能想要對私有DNS域名空間禁用DNSSEC[3]

/etc/unbound/unbound.conf

...
server:
...
   domain-insecure: "intranet"
   domain-insecure: "internal"
   domain-insecure: "private"
   domain-insecure: "corp"
   domain-insecure: "home"
   domain-insecure: "lan"
...
手動制定DNS伺服器

如果你有一個需要DNS請求的本地網絡,同時你想要把請求都轉發給一個本地的DNS伺服器,那麼你需要添加這一行:

private-address: 本地子网/子网掩码

例如:

private-address: 10.0.0.0/24
注意: 你可以使用私有地址來防止DNS劫持攻擊。為了達到這個目的,你可能需要允許RFC1918網絡(10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 169.254.0.0/16 fd00::/8 fe80::/10)。 Unbound的未來版本可能會默認啟用這個功能。
包含本地DNS伺服器

為了包含一個本地DNS伺服器,以用於轉發和反代本地地址,類似下面的一組配置是必要的(請把下面的10.0.0.1替換為本地網絡中提供DNS服務的伺服器的地址):

local-zone: "10.in-addr.arpa." transparent

上面這一行對於讓反向查詢正常工作是非常重要的。

forward-zone:
name: "mynetwork.com."
forward-addr: 10.0.0.1
forward-zone:
local-data: "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost."
注意: 轉發空間和根空間之間的區別是,根空間只有在直接連接到一個authoritative DNS伺服器的時候才能正常工作。如果一個BINDDNS伺服器提供authoritative DNS,那麼這個特性對於來自於它的請求有用——但是如果你在把請求指向一個unbound伺服器(內部查詢都被轉發到另一個DNS伺服器),那麼把這個指向定義為該機器上的根空間是不會起作用的。在這種情況下,你必須把它定義為上面所說的轉發空間,因為轉發空間可以通過鏈式查詢去到別的DNS伺服器上,亦即轉發空間可以把請求指向遞歸DNS伺服器。這個區別是很重要的,因為如果你不恰當地使用根空間,你不會得到能夠說明問題的錯誤信息。

你可以通過下面的配置來設定localhost的前向和反向查詢:

local-zone: "localhost." static
local-data: "localhost. 10800 IN NS localhost."
local-data: "localhost. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local-data: "localhost. 10800 IN A 127.0.0.1"
local-zone: "127.in-addr.arpa." static
local-data: "127.in-addr.arpa. 10800 IN NS localhost."
local-data: "127.in-addr.arpa. 10800 IN SOA localhost. nobody.invalid. 2 3600 1200 604800 10800"
local-data: "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost."

轉發所有其餘的請求

使用openresolv

如果你的網絡管理器支持openresolv,你可以通過配置使它提供上游DNS伺服器給unbound。 [4]

/etc/resolvconf.conf
...
# Write out unbound configuration file
unbound_conf=/etc/unbound/resolvconf.conf

運行resolvconf -u來生成文件。

最後配置unound讀取openresolv生成的文件:

include: "/etc/unbound/resolvconf.conf"
手動指定DNS伺服器

為了使本地機器之外的、本地網絡外部的默認轉發區域使用指定的伺服器,請在配置文件中添加一個名字是.的轉發區域。在這個例子裡,所有的請求都被轉發到谷歌的DNS伺服器:

forward-zone:
  name: "."
  forward-addr: 8.8.8.8
  forward-addr: 8.8.4.4

使用

啟動unbound

Start/enable unbound.service systemd服務。

遠程控制unbound

unbound安裝的時候自帶了unbound-control工具,利用這個工具我們可以遠程控制unbound伺服器。它和pdnsdpdnsd-ctl命令很類似。

配置unbound-control

在能夠使用它之前你需要做下面的事情:

1) 首先,運行:

# unbound-control-setup

來為你的伺服器和客戶端生成一個self-signed的證書和private key。生成的文件位於/etc/unbound文件夾。

2) 然後,把下面的內容放進/etc/unbound/unbound.conf文件。control-enable: yes是一定要有的,其餘的內容可以按照所需進行調整。

remote-control:
   # Enable remote control with unbound-control(8) here.
   # 用unbound-control-setup生成的keys and certificates进行配置。
   control-enable: yes
   # 设定监听哪个地址.
   # give 0.0.0.0 and ::0 to listen to all interfaces.
   control-interface: 127.0.0.1
   # 远程控制用的端口.
   control-port: 8953
   # unbound server key file.
   server-key-file: "/etc/unbound/unbound_server.key"
   # unbound server certificate file.
   server-cert-file: "/etc/unbound/unbound_server.pem"
   # unbound-control key file.
   control-key-file: "/etc/unbound/unbound_control.key"
   # unbound-control certificate file.
   control-cert-file: "/etc/unbound/unbound_control.pem"

使用unbound-control

下面是unbound-control可以使用的一部分命令:

  • 不重置數據的情況下查看統計數據
 # unbound-control stats_noreset
  • 把cache dump到stdout
 # unbound-control dump_cache
  • 清空cache並且重新加載配置
 # unbound-control reload

請參考unbound-control(8)來了解unbound-control支持的操作。

提示與技巧

域名黑名單

你可以打開這個網頁adservers,把它的內容保存到/etc/unbound/adservers,然後把下面的配置直接添加到unbound配置文件裡就可以了:

/etc/unbound/unbound.conf
server:
...
  include: /etc/unbound/adservers
提示:
  • 為了在查詢這些hosts的時候返回OK狀態指示,你可以更改默認的127.0.0.1重定向,改成重定向到你所控制的伺服器並讓那台伺服器返回空的204回應,參考[5]
  • 如果需要把其他格式的hosts文件轉換成unbound的格式的,請運行這個命令:
    $ grep '^0\.0\.0\.0' hostsfile | awk '{print "local-zone: \""$2"\" always_nxdomain"}' > /etc/unbound/adservers

添加一個authoritative DNS伺服器

Tango-inaccurate.png本文或本章節的事實準確性存在爭議。Tango-inaccurate.png

原因: 同時運行兩個DNS伺服器並不一定比只運行一個提供所有功能的DNS伺服器更安全。 (在 Talk:Unbound 中討論)


對於想要在一台機器上同時兩個DNS伺服器(一個是提供驗證、遞歸、緩存功能的DNS伺服器,另一個是authoritative DNS伺服器)的用戶來說,參考NSD的維基頁面可能會有所幫助。那個頁面提供了一個示範配置。一個伺服器專門響應authoritative DNS請求,另一個伺服器提供驗證、遞歸、緩存等DNS功能,這樣會比一個伺服器提供所有功能會更安全。很多用戶已經在使用Bind作為DNS伺服器,而針對從Bind變成Bind和NSD協同工作的過程的幫助在NSD頁面有提供。

WAN facing DNS

通過更改配置文件和伺服器所監聽的接口(地址)來允許來自本地網絡之外的機器的DNS請求進入本地網絡(LAN)內的某台特定機器,這個想法是可行的。這個功能對於公開的網站伺服器和郵件伺服器是非常有用的。這個在bind上已經實現了多年的技術,通過正確配置防火牆機器上的埠轉發——轉發這些請求到正確的機器上——也可以在unbound上實現。

根域名伺服器與systemd timer

下面是一個systemd服務和timer的示例文件,它用來每隔一個月更新一次root.hints,所用的方法與#根域名伺服器中的相同:

/etc/systemd/system/roothints.service
[Unit]
Description=Update root hints for unbound
After=network.target

[Service]
ExecStart=/usr/bin/curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache
/etc/systemd/system/roothints.timer
[Unit]
Description=Run root.hints monthly

[Timer]
OnCalendar=monthly
Persistent=true

[Install]
WantedBy=timers.target

最後Start/enable roothints.timer systemd timer就可以了。

疑難解答

有關num-threads的問題

unbound.conf的man page提到:

     outgoing-range: <number>
           Number of ports to open. This number of file  descriptors  can  be  opened  per thread.

網上的一些人建議num-threads這個參數應該設置成你的CPU的核心數量。示範配置文件unbound.conf.example裡關於這個選項只有下面這兩行:

       # number of threads to create. 1 disables threading.
       # num-threads: 1

但是人為地把num-threads提高到比1就一定會造成unbound在啟動的時候在log裡寫一個warning提示說exceeding the number of file descriptors。實際上對於大多數在小型網絡或是單機上運行unbound的用戶來說,通過讓num-threads超過1來得到性能提升是徒勞的。如果你一定要這麼做,那麼請參考official documentation。下面這條經驗法則應該對你有所幫助:

Set num-threads equal to the number of CPU cores on the system. E.g. for 4 CPUs with 2 cores each, use 8.

outgoing-range設置得儘可能大,參考上面的連結來突破總數是1024這個限制。這樣就會使得unbound可以同時為更多客戶端提供服務。1個核心設置950,2個核心設置450,四個核心設置200num-queries-per-thread最好設置成outgoing-range的一半。

因為outgoing-range是有限制的,同時num-queries-per-thread也因此受到了限制,所以最好在編譯的時候帶上libevent,這樣就不會有1024限制了。如果你有一個高負荷DNS伺服器使得你不得不這樣編譯,你需要從源碼編譯unbound而不是直接安裝unbound

參閱