由於天緣最近使用的比較多的是Red Hat 操作系統,而且自己也是在一台Red Hat 9 下面配置好Bind 9的,因此在下面的例子中就以Red Hat AS3為配置平台進行介紹。天緣所在單位的服務DNS是solaris操作系統,因此寫shell的時候,我爭取做到對Solaris也通用。由於各種因素,我沒能親自在Solaris上進行測試。下面的安裝過程對Red Hat和其他unix操作系統都沒問題,最後附上的自動安裝的shell腳本我只在Red Hat下測試成功,對Solaris大概也基本上顧及到了,如果大家在實際使用那個腳本的時候發現在Solaris下使用存在問題,請及時反饋到此文的留言中,以使我及時更正,方便其他讀者朋友。 首先,在開始以前,讓我們解釋一下標題中出現的chroot 和 bind這兩個詞。 先是chroot,事實上,在很多英文文章中,稱它為”jail”( 監牢, 拘留所, 監獄)。那麼什麼是”Jail”呢?簡單來說,就是把一個事物限制到某個范圍。大家都知道,有時候由於一個應用程序的bug、漏洞等問題,會導致該程序被攻擊者控制,取得相應用戶的權限,進而取得系統管理員級別的權限。例如Windows用戶對一些iis漏洞導致系統最高權限落入攻擊者之手的事情肯定時有耳聞。不管什麼程序,都可能有bug/漏洞,為了防止這樣系統中某程序的漏洞導致系統最高權限被攻擊者竊取的事件發生,就需要限制該程序的權限。 所謂的限制,並不是不讓該程序運行,而是對程序運行時候可以使用的系統資源、用戶權限、所在目錄進行嚴格控制。這樣,在該程序被他人非法控制後,能具有的權限也相當有限,對系統也不會造成更大的危害。舉個形象的例子,架過FTP 服務器的朋友都知道,用戶憑借自己的用戶名/密碼可以進入到自己的空間內進行上傳/下載/添加刪除目錄等操作權限,而對其他用戶的目錄和系統的其他目錄無法進行任何操作(當然,這些權限是管理者合法授權的),這個就可以看做是一個Jail,把ftp用戶限制在自己的目錄裡。在計算機界術語中,我們把這種對程序的Jail,特稱為”chroot”。因此題目中的chroot bind,大家可以理解成“權限受嚴格限制的bind”。 值得一提的是,chroot的程序並不能說是程序本身更安全了,它跟沒有chroot的程序比較,依然有著同樣多的bug/漏洞,依然會被攻擊者利用這些bug/漏洞進行攻擊並得逞。那麼我們辛苦chroot是為了什麼呢?是為了把損失降低到最小。打個比方,購買人生保險並不能保你一生平安,但是可以在你遇到麻煩的時候讓損失少一些。我們的chroot程序也是同樣的道理,當攻擊者取得了該程序的權限的時候,由於程序本身的權限被嚴格限制了,因此攻擊者無法造成更大的破壞,也無法奪取操作系統的最高權限。DNS 服務器由於是作域名解析之用,需要應付來自各地的很多訪問,且一般不限制來訪ip,因此安全隱患和被攻擊的可能性相當大。做一個DNS服務器的資料網絡上到處可尋,而作為網絡管理員,我們需要的除了域名解析,還有“安全”(天緣在以前的網管筆記中提到過,“安全是一種意識”,在做任何事情的時候都提醒自己注意安全,是一個稱職的網絡管理者所應該具備的)! 好了,接下來是第二個名詞“Bind”。Bind 是ISC 公司的軟件,而它也是目前世界上使用最普遍、最通用的DNS軟件,如果說Apache和IIS是兩分Web Server天下的話,那麼Bind 不折不扣是DNS Server事實上的標准了。 接下來開始步入正題,開始我們的Bind安裝之旅。chroot方式安裝軟件,事實上是把一個軟件整體限制到根目錄下的一個子目錄中。即該軟件只在此目錄內具有權限,而一旦跳出該目錄就無任何權限了。在Bind 8的時候,想要把Bind的全部文件放到一個目錄下是一件很麻煩的事,而到了Bind 9開發公司ISC終於順應民心,不光讓Bind 軟件能方便地安裝到同一目錄下進行權限限制作業,而且連遠程控制軟件也加上了,真是超值奉送 1、安裝Bind 9 雖然我所用的Red Hat AS3 中有rpm包,但是為了方便其他操作系統的朋友,我們還是從源代碼包方式安裝。首先從ISC公司的主頁(http://www.isc.org/prodUCts/BIND/)下Bind 9 軟件包。 wget ftp://ftp.isc.org/isc/bind9/9.2.3/bind-9.2.3.tar.gz 接著開始解壓縮(為描述簡單,以下操作如無特殊聲明,都是以root權限進行) tar vzxf bind-9.2.3.tar.gz 卸載Red Hat 中原有的Bind,一共有三個rpm包 rpm -e bind bind-utils caching-nameserver 進入該目錄開始編譯安裝 ./configure --prefix=/usr/local --disable-ipv6 --disable-threads #因為ipv6和線程方式我用不到就去掉了,把Bind 9安裝到/usr/local下 make;make install 到此Bind 9已經安裝完成了,普通的 DNS Server 到此就安裝結束了,而對我們的chroot 而言才剛開始呢。 2、構建chroot 目錄環境 a.創建Bind 工作目錄/chroot/named及下屬工作目錄 rm -rf /chroot/named #刪除原來的舊目錄,之所以加這句是我寫shell的時候調試方便 mkdir -p /chroot/named cd /chroot/named mkdir dev (虛擬/dev) mkdir etc (虛擬/etc) mkdir logs (存放日志) mkdir -p var/run (將來會在這下面放一個named.pid文件) b.建立Bind的組和用戶named groupadd named useradd -g named -d /chroot/named -s /bin/true named pASswd -l named #-l ,Lock,表示鎖定用戶 c.創建虛擬設備(dev),日志記錄的時候有的選項可能用到它們。在默認情況下,是使用/dev目錄下的文件,但是由於我們需要把DNS限制到一個目錄,所以必須完全把/dev下用到的文件(或者說設備)模擬過來才可以。 ls -lL /dev/zero /dev/null /dev/random 看到類似 crw-rw-rw- 1 root root 1, 3 2003-09-15 /dev/null crw-r--r-- 1 root root 1, 8 2003-09-15 /dev/random crw-rw-rw- 1 root root 1, 5 2003-09-15 /dev/zero 這樣的,將其中的1,3這樣的數字記錄下來,這表示主設備號和次設備號(一般來說主設備號用來區分設備的種類;次設備號則是為了作唯一性區分,標明不同屬性——注意,在unix系統中是把設備也當作文件來對待的),在redhat 9下,ls加不加-L參數都無所謂,但是在Solaris下則一定要加上才可以顯示。 mknod dev/null c 1 3 mknod dev/zero c 1 5 mknod dev/random c 1 8 d.復制時鐘文件到我們chroot的etc下,Linux 的時鐘設置文件為:/etc/localtime ,實際上這個文件是 /usr/share/zoneinfo 目錄下對應文件的符號連接。(假設我們所處的地區位於上海,那麼只要運行以下的命令就可以設置時區了。 ln -sf /usr/share/zoneinfo/ASia/Shanghai /etc/localtime;注意在天緣用的solaris 2.6中並沒有此文件,而是該用/usr/share/lib/zoneinfo/GB) cp /etc/localtime etc/ 3、創建和設置BIND 9配置文件 默認情形下,bind以/etc/named.conf文件為配置文件。但由於我們這裡是要做chroot的DNS,因此需要把named.conf放到/chroot/named/conf下去,然後再做一個符號連接到/etc/named.conf。首先創建並編輯named.conf文件(由於介紹DNS的文章大多對named.conf的配置解釋得相當詳細,因此我就不一句句解釋了,大家結合注釋,參考其他文章看看,很容易理解的) vi /chroot/named/etc/named.conf,輸入以下內容(由於每個人的配置都不同,所以天緣在這裡只列出一個做cache only的DNS的設置) options { //注意,由於是chroot方式,所以以下的/conf、/var並不是系統中真正的/conf和/var目錄,而是指/chroot/named下的同名目錄,此配置文件中所有地方都如此 Directory "/conf"; //配置文件所在目錄 pid-file "/var/run/named.pid"; //進程守護文件 statistics-file "/var/run/named.stats"; //狀態輸出文件;在rndc中用到 dump-file "/var/run/named.db"; //輸出數據庫文件,在rndc中用到 //隱藏真實版本號,我這裡寫個4.0作刻意誤導 version "[4.0]"; logging { //日志記錄 channel LAMER_log { file "/logs/DNS-lamer.log" versions 3 size 10m; severity info; print-severity yes; print-time yes; }; channel SEC_log { file "/logs/DNS-sec.log" versions 3 size 10m; severity info; print-severity yes; print-time yes; }; channel STAT_log { file "/logs/DNS-stat.log" versions 3 size 10m; severity info; print-severity yes; print-time yes; }; category cname { null; }; category lame-servers { LAMER_log; }; category security { SEC_log; }; category statistics { STAT_log; }; }; //根解析 zone "." { type hint; file "named.root"; }; // localhost 解析 zone "localhost" { type mASter; file "named.localhost"; notify no; }; // localhost 反向解析 zone "0.0.127.in-addr.arpa" { type mASter; file "named.127.0.0"; notify no; }; 之後進行符號連接到/etc目錄下 ln -s /chroot/named/etc/named.conf /etc/named.conf 好了,接下來,當然就是設置named.root、named.local、named.127.0.0三個文件了,注意,這三個文件的真實位置是在/chroot/named/conf下哦。 首先是named.root的建立 dig @a.root-servers.net . ns > /chroot/named/conf/named.root #這是在redhat下的用法,因為天緣所用的solaris默認(我用的2.6)沒有dig命令,所以在solaris下我們用 cd /chroot/named/conf ftp ftp://ftp.rs.internic.net/domain/named.root 接著是named.local ; ;named.local ; $TTL 86400 @ IN SOA @ root ( 42 ; 版本 3H ; 刷新時間3小時 15M ; 重試時間15分鐘 1W ; 最大期限一周 1D ) ; 最小TTL一天 IN NS @ IN A 127.0.0.1 接著是named.127.0.0 ; ; named.127.0.0 ; $TTL 86400 @ IN SOA localhost. root.localhost. ( ;這裡的root.localost其實是root@localhost,在DNS設置中,將@用.代替1 ; 版本 28800 ; 刷新,這裡和下面的特意以分鐘為單位,和上面的寫法不同,就當多舉個例子吧 14400 ; 重試 3600000 ; 最大期限 86400 ) ; 最小TTL IN NS localhost. 1 IN PTR localhost. 4、設置權限 其實這一步,才是我們作任何chroot 服務真正精華的地方。如何把權限劃分得准確,不至於無法執行服務,也不能大到會威脅到其他程序的安全,實在是一個需要仔細考慮的問題。 a.由於我們的目的是達到讓bind程序以named用戶身份運行,所以必須讓它具有讀配置,無寫配置文件的權限,而且最好其他程序也不能改變我們的配置文件,只有root能改,named用戶能讀。為了滿足這個要求的,自然就想到把文件的擁有者改為root,組用戶設置為named,然後再慢慢仔細劃分權限。 cd /chroot/named chown –R root.named ./ #-R參數表示下屬目錄也依照此權限,-R參數在chown和chmod中經常用到 b.接下來想想各個文件、子目錄的權限。Root組對 文件需要讀寫執行權限,named組對文件需要讀取權限,而對下屬子目錄而言,則必須具有執行權限才能進入其中。因此作以下權限設置。 # 對文件賦予root 讀寫權限,賦予組named讀權限 find . -type f -print xargs chmod u=rw,og=r # 對目錄賦予roo讀寫執行權限,賦予組named讀執行權限(這裡的執行是為了能進入到下級目錄中) find . -type d -print xargs chmod u=rwx,og=rx #對etc目錄下的配置文件,能不讓其他用戶讀取當然是最好的,因此設置 chmod o= etc/*.conf # "secondaries" 子目錄是此DNS服務器作輔助服務器,從主服務器更新消息的時候需要的,會在裡面創建一些新文件。因此它的權限也需要特別設置,在這個目錄下,named組、用戶需要具有讀權限,而不需要用到root用戶,也不想讓其他的用戶身份訪問。 chown root.named conf/secondaries/ #設置secondaries目錄用戶為root,組為named chmod ug=rwx,o= conf/secondaries/ #給予root和named全部權限,以方便訪問下面的文件 touch conf/secondaries/.empty # 去掉舊有的該文件 find conf/secondaries/ -type f -print xargs chown named.named #將用戶組、用戶都設置為named find conf/secondaries/ -type f -print xargs chmod ug=r,o= #只讓named組和用戶有讀權限,而其他用戶無任何權限 接著是為var/目錄設置權限(在這裡會生成進程守護文件named.pid—我們在named.conf中設置了的) chown root.root var/ #這裡可以把named拋棄, chmod u=rwx,og=x var/ #root可以讀寫設置,其他用戶能執行就行,其實我們之所以做一個chroot DNS需要大費周折地單獨設置目錄,就是為了不讓named具有訪問真正的/var的權限。 chown root.named var/run/ #因為在run下面的需要由named身份來寫named.pid文件,所以需要將組改為named好限制權限 chmod ug=rwx,o=rx var/run/ #用戶/組具有讀寫執行權限,其他用戶能讀/執行就可以了,這樣的設置,主要是為了方便我們後面寫shell來判斷DNS目前的狀態。 chown root.named logs/ #日志目錄,設置成這樣的原因不用解釋了吧 chmod ug=rwx,o=rx logs/ #日志允許其他人看比較好,方便以後掛第三方程序 5、啟動並運行bind 9 激動人心的時候到了,即將開始我們的處女bind 9運行了。 運行以下命令 /usr/local/sbin/named -t /chroot/named -u named -c /etc/named.conf 然後再ps –fCnamed 看看??如果出來類似 UID PID PPID C STIME TTY TIME CMD named 14023 1 0 May27 ? 00:00:00 /usr/local/sbin/named -t /chroot/named -u named -c /etc/named.conf 這樣的結果,說明成功了,恭喜你!!! 每次都這樣輸入累不累??所以還是一起來寫個shell吧(其實shell真的粉好用,但是一般真要系統地講解起來又沒有意思,所以我盡量在每篇文章中都把shell用上,慢慢就領會到它的好處咯) vi /chroot/named.start #多cpu的記得加個 "-n " 參數,才能啟用多cpu哦,我也是在別的地方看到的 # # named命令格式: named [-c 配置文件] [-d 除錯級別] [-f-g] [-n cpu個數] # [-p 端口-默認是53] [-s] [-t chroot目錄] [-u 執行該命令的用戶身份] cd /chroot/named #確保除錯的debug文件能夠以named身份寫入 touch named.run #建立該文件 chown named.named named.run #設置文件擁有者為named.named chmod ug=rw,o=r named.run #權限為664 #以named身份,在chroot/named目錄中以/etc/named.conf為配置文件執行named程序 #這裡的/etc/named.conf是我們用ln –s連過去的,參看前文 /usr/local/sbin/named -t /chroot/named -u named -c /etc/named.conf 然後以sh /chroot/named.start 執行此命令就行了,之後在/etc/resolv.conf為自己的DNS地址就可以測試了,當然,也可以用dig命令來查(個人覺得dig命令比nslookup好用,但是Solaris 2.6上默認沒有)。 6. 控制工具rndc的安裝和使用 rndc=remote dnc,以前裝過bind 8的朋友都知道有個ndc工具,而在bind 9中,更是連遠程控制的功能都加上了。說“加上”其實不夠恰當,因為rdnc並不是用ndc改的,而是重新寫的一個通過tcp協議進行DNS控制的軟件。(有什麼用?問問做虛擬主機/系統管理的朋友就知道,DNS一般都是用獨立主機,如果可以遠程reload配置文件,可以方便很多的)。 rndc 原本是應該讀取/usr/local/etc/rndc.conf 作為配置文件的,但我們既然是安裝chroot的DNS,所以有必要把rndc.conf轉到/chroot/named/etc/rndc.conf。好,下面來看看我們的rndc.conf的寫法。 options { default-server localhost; //先配置本地的 default-key "rndckey"; //key的名字 }; server localhost { key "rndckey"; //key的名字 }; include "/chroot/named/etc/rndc.key"; //在這個文件中包含了rndckey的值,之所以這樣,是因為在rndc.conf和named.conf中都用到這個值,用include方便寫自動的shell一些 同樣的道理,在/chroot/named/etc/named.conf的也加上需要的語句 controls { inet 127.0.0.1 allow { localhost; } keys { rndckey; }; //允許localhost連接 }; include "/etc/rndc.key"; 接下來,就是要生成/chroot/named/etc/rndc.key 文件了,它是一個采用bASe-64編碼加密的長字符串key,我們用DNSsec-keygen命令來生成它: cd /chroot/named/etc /usr/local/sbin/DNSsec-keygen -a HMAC-MD5 -b 256 -n HOST rndc 得到一個類似Krndc.+157+30481這樣的返回值,這說明已經在當前目錄下成功建立了Krndc.+157+30481.key和Krndc.+157+30481.private兩個文件。 cat Krndc.+157+30481.private 顯示 Private-key-format: v1.2 Algorithm: 157 (HMAC_MD5) Key: aoqaT1r9Oz29DIj3VPn6+teHcvBudGAc17qLM4nPOqA= 在這裡,Key後面的那串字符就是我們想要的key了,把它復制下來,然後刪除臨時文件 rm Krndc.+157+30481.* vi /chroot/named/etc/rndc.key key "rndckey" { algorithm "hmac-md5"; secret " aoqaT1r9Oz29DIj3VPn6+teHcvBudGAc17qLM4nPOqA="; }; 現在已經配置完成了,建立2個軟連接 ln -s /chroot/named/etc/rndc.conf /usr/local/etc/rndc.conf ln -s /chroot/named/etc/rndc.conf /etc/rndc.conf Ok,接下來對目前運行的named飛起一腿,強迫讓它重新讀配置文件 ps –fCnamed UID PID PPID C STIME TTY TIME CMD named 14023 1 0 May27 ? 00:00:00 /usr/local/sbin/named -t /chroot/named -u named -c /etc/named.conf kill -1 14023 #14023 是named的進程號,至於-1的作用,自己man kill吧 現在來看看我們的rndc是否工作正常 /usr/local/sbin/rndc status 如果現實類似下面的情形就恭喜你咯 number of zones: 2 debug level: 0 xfers running: 0 xfers deferred: 0 soa queries in progress: 0 query logging is OFF server is up and running 如果出現的是rndc: send remote authenticator: permission denied 則肯定上面的步驟中存在問題,請一步步檢查吧。 7、開機執行腳本 每次輸入很長的命令來進行重新啟動,停止DNS實在不是明智的做法,寫個shell腳本來幫助我們吧。 vi /etc/init.d/named #!/bin/sh # eXPort PATH=/usr/local/sbin:$PATH # 把路徑加進去,就不用每次輸入全路徑了 cASe "$1" in start) # 運行Bind echo -n "Starting named: " sh /chroot/named.start echo "done" ;; stop) # 停止 Bind echo -n "Shutting down named: " rndc stop echo "done" ;; reload) # 重新載入配置 echo -n "Reload named: " rndc reload echo "done" ;; status) # 顯示當前狀態 rndc status ;; *) echo "/etc/init.d/named {startstopstatusreload}" exit 1 esac exit 0 然後當然是 chmod a+x /etc/init.d/named 接下來就是對各個啟動模式做符號連接了Red Hat 下: ln -s /etc/init.d/named /etc/rc2.d/S45named ln -s /etc/init.d/named /etc/rc3.d/S45named ln -s /etc/init.d/named /etc/rc5.d/S45named Solaris 2.6 下: ln -s /etc/init.d/named /etc/rc3.d/S45named ln -s /etc/init.d/named /etc/rcS.d/S45named