信息来源:邪恶八进制信息安全团队
o 前言
o 這份 HOW-TO 是必要的嗎?
FreeBSD 是一個非常安全的作業系統。也正因為它的 source code 是可以免費的取得,
這個 OS 長久以來不斷的有人改進加強。儘管 FreeBSD 一出廠就非常安全, 但是仍然
有更多加強安全性的措施, 來滿足"偏執狂"的你 :) 這份 HOW-TO 會教你一些步驟, 以
更加強你機器的整體安全。
o 這份文件會說明 tripwire, tcp_wrappers, cops, satan, 和其它的工具嗎?
除了 SSH 之外, 不會。這是一份針對 FreeBSD 的文件 - 除此之外, 已經有很多文件
說明上述的工具了。目前呢, 我只想關心的是關於 BSD 的部份。
o 誰要讀這份 HOW-TO?
任何想讓他的系統更安全的人。這份 HOW-TO 包含了一些很基本的步驟, 和某些很複雜
的步驟。如果你有任何的疑問, 或者想要加以補充, 請 eMail 到維護人
jkb@best.com
又, 儘管大部份的內容是針對 FreeBSD 的, 但仍然會套用到其它的 Unix OSes 上面。
(特別是 OpenBSD 和 NetBSD)
o 這份 HOW-TO 還有其它語言的版本嗎 ?
就我所知, 有俄語版:
http://www.etrust.ru/osa/security.html
和中文版:
http://water.ite.ntnu.edu.tw/doc/cfbhow2.txt
o TODO:
將包含 /etc/login.conf 和 login classes
將提及使用 X 的場合
將會有 html 版
o 網路
o inetd (Inet Daemon)
網路在系統安全上扮演了一個很重要的角色。FreeBSD 的根基是有著內建網路功能, 且
具有最穩最快的 TCP/IP stacks 的 4.4BSD。這個 stack 支援了非常多的協定像是
telnet, ftp, talk, rsh 等... 這些 service 的的主設定檔便是 /etc/inetd.conf。
要編輯這個檔, 請輸入 "vi /etc/inetd.conf" (在這個例子裡, 我使用 vi 。你可以
使用其它你較為上手的編輯器。或許你可以試試 pico)。如果你要使用 pico, 請在啟
動它時加上 -w 選項:
-w 關掉自動斷行。(因此可以容許超過 80 字元的行存在)
這選項在編輯 /etc/inetd.conf 時非常有用。
當然了, 你也可以使用 ee - 它隨著 FreeBSD 一起 "出廠" 的, 而且也是 root 預設
的編輯器。不過, 請再 "echo $EDITOR" 確認一次。 開啟了這個檔案後, 你可以看
到裡面怎麼描述每個 service 怎麼啟動, 要以那位使用者執行等等的資訊。(man 5
inetd.conf)既然這個檔案是許多 internet service 的主要設定檔, 好好的設定它便
是一件十分重要的事。你要關掉一個 service的話,只消在那一行前面加個 "#" 符號。
基本的概念是, 關掉些你不熟悉的 services - 如果你不知道那個 service 是啥, 或
者不知道它可以幹啥。理想狀態下, 你不須要把所有的 service 都打開。例如, 你的
器只是要跑 web server。這種情況下, 你只要啟動 ssh 和 httpd 便夠了。關於啥是
ssh, 下面會說明。如果你啥 service 都不想跑, 最直接乾脆的方法是-關掉 inetd。
做法很簡單, 只要編輯 /etc/rc.conf 並且把
inetd_enable="YES"
改成
inetd_enable="NO"
就可以了。
如此一來沒人可以 telnet, rlogin, 或 ftp 到你的電腦。
如果你決定要啟動你的 inetd 的話, 記得啟動 log 選項, 並提高一個 service 每分
鐘啟動的上限數目。(預設值是 256, 我建議提高到 1024-自行參照下面解說調整吧!)
為什麼要這麼做呢...? 就 modem user 或是低速專線用戶是沒什麼差別。但高速線路
的人, 上限值太低會蹦出一個 DoS attack(Denial of Service)。某個壞心的人可以簡
單的用一個 shell script 同時搞出超過 256 個 connections, 這麼一來你的 inetd
會很不幸的陣亡。換句話說, 如果你想讓每分鐘每個 service 可接受的connection 數
多點, 記得做如下的設定, 不然來個壞心的人就可以搞垮你的電腦。因此, 在這行
inetd_enable="YES"
下面的
inetd_flags=""
要改成:
inetd_flags="-l -R 1024"
這會將連線的動作都 log 下來(-l 參數)而且將同時最大連線數從預設的 256 增加到
1024。你還須要對你的 /etc/syslog.conf 作些修改, 這些等會兒會提到。
o SSH
在以下提到的案例中, 你完全不須要 run inetd。例如, 如果你只有跑 web, news, 或
是 nfs server, 那麼就沒有必要在你的機器上再跑其它的services。但是你一定會問,
"我要怎麼控制我的機器啊!?" 嗯嗯, 所以現在要介紹 SSH。你可以透過 SSH (Secure
Shell) 來登入你的機器。Secure Shell 當初便是設計來取代 rsh, rlogin 等其它的
Berkeley r* 命令。相信你很快就會了解 SSH 是如何有用,而且開始使用它,來代替其
它的程式像是 telnet 和 ftp。SSH 具有很多功能,但是最為人知的是, 它的加密通訊
方式, 也就是防止你的密碼和資料以明碼的方式在網路上傳輸。如果你使用 telnet,你
的通訊內容可能會被"竊聽": 傳輸中的資料被改變, 通訊內容被看到。(不是有 S/Key
可以解決嗎? 很不幸的, 它還是有著插入資料和連接時被破解的問題) 我希望你可以完
全的關掉 inetd 而使用 SSH。如果你認為完全不靠 inetd 來啟動某些 services,是完
完全全不可能的事, 那麼希望你至少啟動 log 功能, 而且要增加每分鐘同一個 servi-
ce 可啟動的次數。 (原因上面有提到)
你可以從
ftp://ftp.funet.fi/pub/unix/security/login/ssh 下載 SSH。
若你想要更簡單的方法:
# cd /usr/ports/security/ssh
# make install
如果你有不是使用 Unix 的使用者, 那麼可以從下面的站台抓到 win32 SSH 程式:
http://fox.doc.ic.ac.uk/~ci2/ssh/
http://www.zip.com.au/~roca/ttssh.html
http://bmrc.berkeley.edu/people/chaffee/winntutil.html
http://public.srce.hr/~cigaly/ssh
SecureCRT from
http://www.vandyke.com
o inetd (part II)
o telnetd
好吧, 你仍然執意要使用 inetd。那麼我們來看看在 inetd.conf 有那些選項, 可以增
進你的系統安全。在攻擊某系統之前, 攻擊者都會先收集該系統的相關資訊。就 teln-
etd 而言, 你可以試試在 telnetd 那行後面加個 -h:
telnet stream tcp nowait root /usr/libexec/telnetd telnetd -h
從 telnetd 的 man page 可以知道:
-h Disable the printing of host-specific information before login
has been completed.
當有很多管道可以獲得系統資訊的同時, 這招和下面的那招是個不錯的解決方案。如果
你認為跑 telnet daemon 是沒有必要的, 那麼只消加個 "#" 在該行的最前面就行了:
#telnet stream tcp nowait root /usr/libexec/telnetd telnetd
有個極不錯的措施是, 你可以拒絕沒有完整 FQDN 的人來連線。要做到這點, 也只要加
個 -U 選項到 telnetd 後面:
telnet stream tcp nowait root /usr/libexec/telnetd telnetd -h -U
這是個小動作, 但是對你的系統安全有莫大的助益。
o ftpd
現在來看看 ftp。 對於 ftp FreeBSD 已經做了一些 log 的動作 。 可以看到在
/etc/inetd.conf 裡面 ftpd 那一行已經加了 "-l"。然而, 你還是要設定你的syslogd
, 使它可以接受 ftp daemon 產生的 log。從 man page 可以得知:
-l Each successful and failed ftp(1) session is logged using syslog
with a facility of LOG_FTP. If this option is specified twice,
the retrieve (get), store (put), append, delete, make directory,
remove directory and rename operations and their filename argu-
ments are also logged. Note: LOG_FTP messages are not displayed
by syslogd(8) by default, and may have to be enabled in syslogd(8)'s
configuration file.
每個成功或是失敗的 ftp 登入嘗試, 都會以 LOG_FTP 機制紀錄起來。如
果這個選項被指定了兩次, 所有的下載 (get), 上載(put), 新增, 刪除,
建立目錄, 及更名的動作和檔案名字都會被紀錄下來。 又: LOG_FTP 訊
息預設是不會被 syslogd(8) 紀錄下來的。你還要在 syslogd(8) 的設定
檔裡面啟動這個功能才行。
讓我們開啟 syslogd 紀錄 ftpd log 的功能吧~ 這個檔案是 /etc/syslog.conf (別忘
了順便看看 man 5 syslog.conf)。把下面這一行加到這個設定檔裡:
ftp.* /var/log/ftpd
也不要忘了執行這個指令 "touch /var/log/ftpdlog", 因為 syslogd 不能寫入到一個
沒有被開啟過的檔案。如果你想要你的 ftpd 提供你更多的 log 訊息, 那麼就在 ftp
那一行多加個 "-l" 吧:
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l -l
如果你想要確定你的使用者們都用 scp (Secure Copy, 附屬在 SSH 裡面), 但是又想
要提供 anonymous ftp 服務, 也只消加個 "-A" 在 ftp 那行後面就行了:
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l -A
你也可以編輯 /etc/ftpwelcome, 說明目前接受 anonymous ftp 登入, 但是系統內的
使用者就得使用 rcp 了。如果你有提供 anonymous ftp, 你可以使用 -S 選項來記錄
傳輸的情形:
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -A -S
o fingerd
Finger 服務預設值還算安全: 它不容許不帶 user name 的 query。這是一件不錯的事
(tm)。然而, 就是有些人無論如何也不想 run fingerd。這種情形下, 你只要簡單的給
它加個 "#" 在這行的最前面就可以了。又, 你想要 log 住誰來 finger 的話, 加個
"-l" 也就行了:
finger stream tcp nowait nobody /usr/libexec/fingerd fingerd -s -l
Fingerd 產生的 log 資訊預設是寫到 /var/log/messages。如果你想要這些資訊寫入
到特定的檔案裡去, 那麼就在 /etc/syslog.conf 加入這一行:
daemon.notice /var/log/fingerd
/* !fingerd anyone? */
$ man 5 syslog.conf
除了 ftp, telnet 和 finger 之外, 你實在不須要在 /etc/inetd.conf 中再多啟動任
何東西了。通常我都會關掉 talk 及 comsat等我個人不須要的東西。如同我之前講的,
如果你不知到某個 servcie 是幹嘛用的, 而且你也不須要它, 那麼就關掉它。一些和
網路有關而且很有用的 man page 是: inetd, ftpd, telnetd, fingerd, syslogd,
comsat, talkd, rshd, rlogind, inetd.conf。並且記得要看 man page 的"SEE ALSO"
部份, 以獲得更多的相關資訊。
o ipfw (IP FrewWall)
IP FireWall 做的是 packet 過濾的工作。沒錯, 就是只有這樣。然而, 你要考慮的事
是, 你的 kernel 要有支援 ipfw。 通常在我管的機器上, 我都會重編核心使其支援
ipfw。大概看起來是這樣:
options IPFIREWALL #finger the net
options IPFIREWALL_VERBOSE #log the net
options IPFIREWALL_DEFAULT_TO_ACCEPT
第一行表示最其本的 IP FireWall 支援。第二行讓 ipfw 可以把接受或拒絕 packets
的紀錄 log 起來。第三行非常重要, 讓 ipfw 預設值是接受任何地方來的 packets 。
如果你不這樣做, 預設值拒絕任何地方來的 packets。我個比比較喜歡後者, 但我又認
為在我自己的工作站上, 或一個讓人登入的工作站, 預設拒絕任何 packets 不是一件
太好的事。
********** NOTE ************
如果你搞不清楚自己在做啥事, 那就不要用這個選項。
就設定 firewall 而言, 這是不甚正確的。預設任何東西都該被擋掉才是正確的。如果
你是要建置一台高安全性的系統, 或一台 firewall 的話,那就千萬不要加入這個選項:
options IPFIREWALL_DEFAULT_TO_ACCEPT
記住一件事: 要預設拒絕任接受任何 packets, 然後再加入 rule 來設定你想要接
受那些 packets。查看 /etc/rc.firewall 以得到更多的資訊。再一次提醒你, 不要使
用這個 option, 除非你只是想要防止 DoS attacks 或暫時把某些 port/network ban
掉。
*****************************
o log_in_vain
你也可以透過 sysctl 命令, 來改變一些有用的系統變數:
# sysctl -w net.inet.tcp.log_in_vain=1
# sysctl -w net.inet.udp.log_in_vain=1
這會把嘗試向你的機器要求你沒有的服務的 connections log 起來。例如, 如果你在
你的機器沒有跑 DNS server, 而又有個人想要向你的機器要求 DNS 服務, 這時候你就
會看到
Connection attempt to UDP yourIP:53 from otherIP:X
(X 是某個 high port #)
你用 "dmesg" 命令就可以看到這一行。Dmesg 秀出的是系統的 kernel message
buffer。然而, 這個 buffer 的空間是有限的, 所以系統也會把這些訊息寫入到
/var/log/messages 裡面去:
# tail -1 /var/log/messages
Jun 12 19:36:03 ugh /kernel: Connection attempt to UDP yourIP:53 from otherIP:X
o final notes
理論上呢, 你的系統現在已經比你裝好它時更安全些了。你現在可以做一些事來確定你
目前的更動:
$ netstat -na | grep LISTEN
這會告訴你那些 service 在那些 port 跑。越少越好 :) 又, 再跑一些其它的 port
scanners (strobe, nmap) 來找出你開了那些 port。
而要確要你的 syslogd 已經開始紀下你剛剛想要 log 的事件, 可以這麼做:
# cd /var/log
# tail -10 fingerd ftpd messages
在 log 檔裡面沒看到任何東西的話, 記得重新啟動 inetd 和 syslogd:
# kill -HUP `cat /var/run/syslog.pig` `cat /var/run/inetd.pid`
o Filesystem
既然 Unix 把什麼東西都當作檔案來看待, 好好的保護你的檔案系統便是很重要的事。
有件事是在你安裝作業系統前便要完成的: 必須要計劃並設計好你的 partition 該怎
麼切割。有幾個很重要的原因讓你要這麼做: 一個是你可以 mount 不同的檔案系統以
賦與不同的選項 (下面有幾個例子)。別一個是,如果你想要把你的 filesystem export
出去, 你須要更加細微的控制。如果你是一個從 Linux 轉入 FreeBSD 的使用者, 你會
發現 Linux 是把任何東西都往 root partition "/" 塞, 而 FreeBSD 預設便要 "/",
"/usr", 和 "/var"。這也使得要使用如 dump 般的工具較容易。且讓我們來討論 se-
curity 吧! 有一件事我通常會做的是, 我會把一般 users 可以寫入的 partition 分
開來割, 而這些 partitons 便可以用 "nosuid" 的方式來 mount。從 mount 的 man
page 可以知道:
nosuid Do not allow set-user-identifier or set-group-identifier
bits to take effect. Note: this option is worthless if a
public available suid or sgid wrapper like suidperl is
installed on your system.
讓 suid 或 sgid bit 失效。又: 對於像 suidperl 這些公開使用
的程式, 設這個選項便沒用。
因此你會有個 partition 給一般使用者使用: /home 或 /usr/home。然後你可以另外
開個 partion 給 /var/tmp 然後再把你的 /tmp 指到這裡:
# rm -rf /tmp
# ln -s /var/tmp /tmp
你可以參考這個例子:
# cat /etc/fstab
# Device Mountpoint FStype Options Dump Pass#
/dev/sd0s1b none swap sw 0 0
/dev/sd0s1a / ufs rw 1 1
/dev/sd0s1g /usr ufs rw 2 2
/dev/sd0s1h /usr/home ufs rw 2 2
/dev/sd0s1f /var ufs rw 2 2
/dev/sd0s1e /var/tmp ufs rw,nosuid 2 2
proc /proc procfs rw 0 0
現在你可以確定一般 users 可以寫入的目錄不是以 "-nosuid" 的方式被 mount, 就是
沒有可以寫入。現在你還要關心的就是 /var/spool/uucppublic"。
你可以把 "/var" 以 "-nosuid" 的方式來 mount , 或下這個命令:
# chmod o-w /var/spool/uucppublic