企業(yè) Java 專家 Dennis Sosnoski 從 Java 服務(wù)器技術(shù)如何適合 Linux 來開始闡述他的觀點(diǎn),然后給出在 Linux 上安全地設(shè)定 Tomcat Java servlet 引擎的一點(diǎn)建議。
Linux 平臺(tái)和 Java 平臺(tái)有著久遠(yuǎn)的但有經(jīng)常經(jīng)歷曲折的關(guān)系。建置高效能虛擬機(jī)器的同時(shí)又要跟上日益增長(zhǎng)的核心 Java API 集合,這樣做所帶來的復(fù)雜性在很大程度上使開發(fā) Java 平臺(tái)的開放來源程序代碼「Clean Room」實(shí)作的早期行動(dòng)困難重重。Java 技術(shù)的特許實(shí)作最終可用于 Linux,但這些實(shí)作并不是開放來源程序代碼。因此,大多數(shù) Linux 分發(fā)版沒有包括該特許實(shí)作。
盡管有這些困難,Java 平臺(tái)還是提供了許多好處,從而導(dǎo)致在 Linux 上越來越多地使用該特許實(shí)作,尤其是對(duì)于服務(wù)器應(yīng)用程序。在本文中,我回顧了 Java 平臺(tái)給服務(wù)器應(yīng)用程序帶來的優(yōu)點(diǎn),然后研究了在 Linux 上簡(jiǎn)單且安全地部署 Java 服務(wù)所涉及的問題。作為一個(gè)實(shí)際范例,我將討論設(shè)定 Apache Software Foundation 的廣泛使用的 Tomcat Java servlet 引擎的詳細(xì)信息以用于獨(dú)立作業(yè)。
為什么使用 Java 平臺(tái)?
有許多原因可以解釋為什么 Java 平臺(tái)成為基于服務(wù)器的商業(yè)應(yīng)用程序的廣為接受的選擇。我將主要討論我認(rèn)為對(duì)于該環(huán)境至關(guān)重要的三個(gè)原因︰跨平臺(tái)兼容性、受管執(zhí)行時(shí)環(huán)境和易于開發(fā)。
Java 應(yīng)用程序提供了跨多種操作系統(tǒng)和硬件平臺(tái)的二進(jìn)制兼容性。對(duì)于非 GUI 服務(wù)器應(yīng)用程序尤其是這樣,在此類別應(yīng)用程序中,通常在實(shí)際目標(biāo)系統(tǒng)中需要執(zhí)行非常少的測(cè)試。工作人員可以在任何他們喜歡的平臺(tái)上進(jìn)行編碼和除錯(cuò),同時(shí)仍可以將這些應(yīng)用程序部署到他們也許不能直接控制的環(huán)境中。
Java 虛擬機(jī)器(Java Virtual Machine,JVM)環(huán)境的執(zhí)行時(shí)特性以幾種方式來加強(qiáng)程序安全性。最顯著的方面之一是嚴(yán)格的類別型檢查、數(shù)組邊界檢查和自動(dòng)垃圾收集的組合徹底防止了最具破壞性形式的服務(wù)器程序代碼攻擊︰緩沖區(qū)溢位、重復(fù)釋放的錯(cuò)誤和游離的指針。Java 語言早期用于 applet,經(jīng)過不斷發(fā)展,該語言還有一個(gè)完善的系統(tǒng),用于對(duì)那些已確信存在安全性風(fēng)險(xiǎn)的設(shè)施進(jìn)行細(xì)微的存取控制。這些方法可供獨(dú)立應(yīng)用程序選擇使用,但它們已建置在許多 Java 服務(wù)的架構(gòu)中。
這些執(zhí)行時(shí)程序安全特性還提供了用 Java 語言開發(fā)的便利性。要對(duì)便利性這類別問題作任何精確測(cè)量是困難的,但大多數(shù)具有諸如 C 和 C++ 之類別語言背景而轉(zhuǎn)向 Java 程序化的工作人員都承認(rèn)在轉(zhuǎn)變之后他們的生產(chǎn)力提高了。其中部分是因?yàn)樵诰幾g時(shí)和執(zhí)行時(shí)嚴(yán)格執(zhí)行類別型確定,以及自動(dòng)內(nèi)存管理的簡(jiǎn)單性。另一個(gè)因素是為 Java 平臺(tái)開發(fā)的標(biāo)準(zhǔn) API 擴(kuò)充的集合。這些 API 對(duì)于新的工作人員可能是一個(gè)重大挑戰(zhàn),但是一旦學(xué)會(huì)了,API 會(huì)為各種企業(yè)需求提供優(yōu)秀的跨平臺(tái)支持。
當(dāng)然,對(duì)于某些應(yīng)用程序而言,Java 平臺(tái)可能是一個(gè)糟糕的選擇。盡管 JVM 體系結(jié)構(gòu)在持續(xù)改進(jìn),但 Java 應(yīng)用程序通常會(huì)比使用相同算法的 C 或 C++ 應(yīng)用程序執(zhí)行得稍微慢一點(diǎn)。根據(jù)我的經(jīng)驗(yàn)和測(cè)試,我估計(jì)這個(gè)速度差異對(duì)于在特許 JVM 上執(zhí)行的大多數(shù)服務(wù)器應(yīng)用程序來說大約是在 20% 到 50% 的范圍內(nèi),然而這很大程度上取決于程序代碼的質(zhì)量。與獨(dú)立程序相比,在這些 JVM 上執(zhí)行的 Java 應(yīng)用程序還忍受著比較慢的啟動(dòng),但是這對(duì)于長(zhǎng)時(shí)間執(zhí)行的服務(wù)器應(yīng)用程序通常并不是一個(gè)重大問題。在大多數(shù)情況中,降低的效能和較慢的啟動(dòng)祇是為獲得 Java 平臺(tái)的增強(qiáng)的安全性和更快速的開發(fā)優(yōu)點(diǎn)所付出的微小代價(jià)。
開放來源碼替代選擇
除了標(biāo)準(zhǔn)特許 JVM(免費(fèi)使用,但是來源碼受到限制;可用于 Sun、IBM、BEA 和 Blackdown 組織的 Linux)之外,對(duì)于 Linux 還有其它幾個(gè)替代選擇。這些選擇包括「Clean Room」開放來源碼 JVM 實(shí)作,其中使用最廣泛的可能是 Kaffe(在許多 Linux 分發(fā)版中都包括它)。Kaffe 是一個(gè)非常有意義的項(xiàng)目,它已經(jīng)完成了一些令人驚訝的工作,但它只能提供與目前特許 JVM 有限的兼容性。因此,它通常無法使用于本文所關(guān)注的企業(yè)類別型的服務(wù)器應(yīng)用程序。
用于 Java 程序的本機(jī)程序代碼編譯器的開放來源碼工作也有幾個(gè)替代選擇。這里最重要的項(xiàng)目是 GNU 編譯器集(GNU Compiler Collection)的 GCJ。使用諸如 CGJ 之類別的本機(jī)程序代碼編譯器會(huì)將獨(dú)立于平臺(tái)的 Java 字節(jié)碼在其執(zhí)行之前轉(zhuǎn)換成特定于平臺(tái)的程序代碼(這與在 JVM 中執(zhí)行成對(duì)比,在 JVM 中執(zhí)行通常在執(zhí)行時(shí)將字節(jié)碼轉(zhuǎn)換成特定于平臺(tái)的程序代碼)。
本機(jī)程序代碼編譯顯示出它極有可能成為一種避免在 JVM 中執(zhí)行的 Java 應(yīng)用程序啟動(dòng)較慢的方法。但是,使用這種方法的編譯器通常都不能與當(dāng)代特許 JVM 的穩(wěn)定狀態(tài)效能相匹配。如果 Java 應(yīng)用程序使用 Java 平臺(tái)的動(dòng)態(tài)特性(如使用反射來存取字段或加載在執(zhí)行時(shí)選擇的類別),這種情況尤其突出。根據(jù)所使用的實(shí)作和編譯選項(xiàng),本機(jī)程序代碼編譯也許還會(huì)削弱 Java 平臺(tái)的許多執(zhí)行時(shí)安全特性。最后,由于許可證問題,許多 Java API 不能與已編譯的本機(jī)程序代碼一起使用。由于這些限制,本機(jī)程序代碼編譯目前還不是 Java 平臺(tái)服務(wù)器應(yīng)用程序的一個(gè)好選擇。
C# 怎么樣?
與 Java 執(zhí)行時(shí)環(huán)境有許多共同點(diǎn)的一個(gè)替代方法是 Microsoft 的 C# 語言和相關(guān)的公共語言執(zhí)行時(shí)(Common Language Runtime,CLR)。C# 是 Java 語言的關(guān)系緊密的衍生物,CLR 可能容許 C# 在許多平臺(tái)上使用。CLR 還提供了 JVM 的許多執(zhí)行時(shí)安全特性(盡管有嚴(yán)重削弱安全保證的逃離出口)。Microsoft .Net 實(shí)作還支持預(yù)編譯成本機(jī)程序代碼的選項(xiàng)以獲得更快速啟動(dòng),這與 GCJ 對(duì) Java 字節(jié)碼所做的工作相同。當(dāng)然,Linux 使用者并不能直接使用這項(xiàng)功能,因?yàn)?.Net 只適用于 Windows 系統(tǒng)。
Mono Project 正致力于為多種 Linux 產(chǎn)品建置「CLean Room」開放來源碼 C# 和等價(jià)于 CLR 的產(chǎn)品。現(xiàn)在,該項(xiàng)目中的 C# 編譯器已開發(fā)完成,而且還完成了大部分的 CLR,Microsoft 已發(fā)布將它用于標(biāo)準(zhǔn)化。但是,無論從效能還是功能角度來看,在它成為合理的 Java 平臺(tái)替代選擇之前還有許多工作要做。CLR 只包括了與 Java 核心類別庫等價(jià)的基本內(nèi)容。在可以將它看作是企業(yè)軟件開發(fā)的合理選項(xiàng)之前,還需要用許多額外 API 來補(bǔ)充它。
Mono Project 正在致力于開發(fā) CLR 以外的 .Net 其它部分的移植,如果這些移植成功了 ─ 并且如果 Microsoft 不對(duì) .Net 的這些部分強(qiáng)加它的專利權(quán) ─ 那么它們會(huì)有助于滿足 C# 成為 Linux 上服務(wù)器軟件開發(fā)的可靠平臺(tái)的需要。但要使那些假設(shè)成為現(xiàn)實(shí),還需要做很多工作,同時(shí),Java 程序的本機(jī)程序代碼編譯器和開放來源碼 JVM 向那些確實(shí)想要避免使用特許 JVM 并可以忍受有限功能性的使用者提供了比較穩(wěn)定的替代選擇。
Apache Tomcat
最普遍存在的 Java 平臺(tái)服務(wù)器應(yīng)用程序之一是 Apache Tomcat。Tomcat 是基于最初由 Sun 捐贈(zèng)的來源碼的開放來源碼項(xiàng)目。它是一個(gè) HTTP 服務(wù)器,是 Sun 透過 Java Community Process 開發(fā)的、對(duì)廣泛使用的 servlet 和 JavaServer Page(JSP)技術(shù)的正式參考實(shí)作。我將在本文中使用 Tomcat 作為樣本 Java 應(yīng)用程序,將其部署成 Linux 上的一個(gè)服務(wù)。如果您想要嘗試自己執(zhí)行 Tomcat,那么您將需要在系統(tǒng)上安裝 Java 開發(fā)工具箱(Java Development Kit,JDK),而不是安裝更小的 Java 執(zhí)行時(shí)環(huán)境(Java Runtime Environment,JRE)。
servlet 和 JSP 技術(shù)用于建構(gòu) HTTP 服務(wù)器應(yīng)用程序。雖然 servlet 技術(shù)中加入了許多特性(包括存取安全性、Session管理和執(zhí)行緒控制),但它本身祇是粗略地等價(jià)于為快速直接的 Java 語言呼叫而定制的 CGI 接口。JSP 技術(shù)提供了一種處理動(dòng)態(tài)生成的 HTML 頁面的簡(jiǎn)便方法,這些 HTML 頁面被直接編譯成 servlet 以用于快速執(zhí)行時(shí)作業(yè)。
在這兩種技術(shù)之外,Tomcat 還提供了其它許多特性。憑它本身的效能,它實(shí)際上是全功能 Web 服務(wù)器,但它通常在 Linux 系統(tǒng)上與 Apache Web 服務(wù)器前端共同使用。Apache 向 Tomcat 提供了許多進(jìn)階效能以適合靜態(tài)內(nèi)容。對(duì)于靜態(tài)內(nèi)容所占比例比較高且使用率很高的 Web 應(yīng)用程序,Apache 前端非常有用。但對(duì)于許多簡(jiǎn)單的 Web 應(yīng)用程序,就沒必要使用它了,當(dāng)更易于組態(tài)和管理時(shí),單獨(dú)執(zhí)行 Tomcat 就可提供足夠的效能(至少對(duì)于以前沒有使用過 Apache 的工作人員來說是這樣)。
連接埠難題
單獨(dú)執(zhí)行 Tomcat 的一個(gè)大問題是它無法存取標(biāo)準(zhǔn) HTTP 連接埠 80,除非是作為 root 使用者執(zhí)行。作為 root 使用者執(zhí)行服務(wù)器應(yīng)用程序的想法通常并不是上串流公司所討論的問題,因此我將完全放棄這個(gè)想法﹗使用除 80 以外的連接埠是一個(gè)更好的選擇(例如,Tomcat 缺省連接埠 8080)。這通常適用于測(cè)試,但當(dāng)使用者正在存取服務(wù)時(shí),它會(huì)導(dǎo)致雜亂的 URL,因?yàn)樾枰谡?qǐng)求中清楚地說明連接埠號(hào)。使用非標(biāo)準(zhǔn)連接埠還意味著如果需要外部存取,就需要重新組態(tài)所有的防火墻。
xinetd 解決方案
幸好,Linux 支持一些利用 Tomcat(或任何其它使用者方式應(yīng)用程序)處理連接端口 80 請(qǐng)求的簡(jiǎn)便方式。一種常用方式是透過 xinetd。xinetd 是帶有廣泛存取控制和日志記錄支持的因特網(wǎng)服務(wù)守護(hù)程序,它還擁有方便的重新導(dǎo)向特性。重新導(dǎo)向讓您將系統(tǒng)組態(tài)成接受一個(gè)連接埠上的進(jìn)入請(qǐng)求,然后將請(qǐng)求傳遞到另一個(gè)連接埠或者甚至另一個(gè) IP 地址進(jìn)行處理。
如果您想要在系統(tǒng)上設(shè)定 Tomcat 以處理連接埠 80 請(qǐng)求,就需要加入 xinetd 組態(tài)文件來實(shí)作這一目的。假設(shè)按一般在正常路徑上安裝了 xinetd,那么您可以透過對(duì) /etc/xinetd.d 目錄加入一個(gè)文件(以 root 使用者身份)來執(zhí)行這一作業(yè)。清單 1 提供了用于 Tomcat 的一個(gè)樣本組態(tài)文件。
清單 1. xinetd 重新導(dǎo)向組態(tài)
# Redirects any requests on port 80
# to port 8080 (where Tomcat is listening)
service tomcat
{
socket_type = stream
protocol = tcp
user = root
wait = no
port = 80
redirect = localhost 8080
disable = no
}
在加入了組態(tài)文件之后,需要重新啟動(dòng) xinetd 來真正活化重新導(dǎo)向。在大多數(shù) Linux 安裝上,透過以 root 使用者身份執(zhí)行以下指令來重新啟動(dòng) xinetd︰
/sbin/service xinetd restart
祇要將組態(tài)文件放在 /etc/xinetd.d 目錄中,當(dāng)重新啟動(dòng)系統(tǒng)時(shí),重新導(dǎo)向就會(huì)自動(dòng)啟動(dòng)。如果沒有將 Tomcat 設(shè)定成自動(dòng)啟動(dòng),那么在啟動(dòng) Tomcat 之前,會(huì)拒絕進(jìn)入請(qǐng)求。
iptables 解決方案
xinetd 是處理請(qǐng)求重新導(dǎo)向的一種好方法,但它執(zhí)行了一個(gè)處理序以在連接端口之間實(shí)際轉(zhuǎn)信數(shù)據(jù),這確實(shí)增加了一些開銷。最新的 Linux 內(nèi)核版本透過使用 iptables 來支持一種更好的設(shè)定重新導(dǎo)向的方法。iptables 與 xinetd 的區(qū)別之處在于它是一個(gè)真正的內(nèi)核組件。因此,它可以避免 xinetd 方法增加的開銷。使用 iptables 的唯一缺點(diǎn)是它可能比 xinetd 更難以組態(tài),而且它只可用于相當(dāng)新的內(nèi)核版本。
您需要執(zhí)行支持 iptables 的 2.4.x 或更新的內(nèi)核,以便使用我在這里描述的技術(shù)。組態(tài)和設(shè)定 iptables 是一個(gè)確信由幾篇文章來單獨(dú)描述的主題,所以我不打算在這里嘗試討論該主題。如果對(duì) iptables 的入門需要幫助,請(qǐng)閱讀 Linux 分發(fā)版的手冊(cè)。要快速檢查 iptables 是否在您的系統(tǒng)上執(zhí)行,嘗試以 root 使用者身份執(zhí)行︰
/sbin/service iptables status
如果它正在執(zhí)行,您將會(huì)在控制臺(tái)上看到表和鏈的清單。
iptables 使用幾個(gè)不同的表和封包鏈來處理規(guī)則的。為了將進(jìn)入 HTTP 請(qǐng)求從連接端口 80 重新導(dǎo)向到系統(tǒng)中的另一個(gè)連接埠,您將要使用 nat 表(表示網(wǎng)絡(luò)地址轉(zhuǎn)換,Network Address Translation)和 PREROUTING 鏈。清單 2 提供了要執(zhí)行的實(shí)際指令(以 root 使用者身份),以便于加入一條處理這一請(qǐng)求的規(guī)則。這條規(guī)則的作用是將進(jìn)入包的目標(biāo)連接端口 80 修改成目標(biāo)連接端口 8080,因此祇有在您沒有阻止從外部使用連接埠 8080 時(shí),這條規(guī)則才會(huì)正確工作。一旦執(zhí)行了該指令,您就應(yīng)該能夠立即處理進(jìn)入請(qǐng)求。
清單 2. iptables 重新導(dǎo)向規(guī)則
/sbin/iptables -t nat
-A PREROUTING -j REDIRECT -p tcp
--destination-port 80:80 --to-ports 8080
/sbin/service iptables save
以便于儲(chǔ)存目前 iptables 組態(tài)。
自動(dòng)啟動(dòng) Tomcat
當(dāng)執(zhí)行諸如 Tomcat 之類別的 Java 服務(wù)時(shí)的另一個(gè)問題是當(dāng)系統(tǒng)啟動(dòng)時(shí),如何自動(dòng)啟動(dòng)該應(yīng)用程序,以及當(dāng)系統(tǒng)關(guān)機(jī)時(shí)如何自動(dòng)停止它(換句話說,將它當(dāng)作守護(hù)程序執(zhí)行)。經(jīng)驗(yàn)豐富的 Linux 使用者已經(jīng)知道怎樣做,但如果您還是個(gè) Linux 新手,以下就是一些基礎(chǔ)知識(shí)。
如果您就在您的個(gè)人系統(tǒng)上執(zhí)行它并且想要使用與直接執(zhí)行 Tomcat 一樣的對(duì) Tomcat 的文件和目錄的存取權(quán),那么您可以用您自己的使用者名稱來設(shè)定它。但是,通常,一個(gè)比較好的想法是︰為將要作為守護(hù)程序執(zhí)行的任何程序設(shè)定一個(gè)單獨(dú)的使用者。要針對(duì) Tomcat 執(zhí)行這一作業(yè),以 root 使用者身份執(zhí)行︰
/usr/sbin/useradd tomcat
這將建立一個(gè)名為 tomcat 的使用者賬戶并建立一個(gè)用于 Tomcat 安裝的主目錄 /home/tomcat。所建立的主目錄的所有者是 tomcat 使用者,而且通常只容許這個(gè)使用者存取(當(dāng)然還有 root 使用者)。如果想要從其它賬戶存取 Tomcat 安裝,可以將許可權(quán)變更成包括組存取權(quán),并將 tomcat 組新增到這些其它賬戶。
總之,要將 Tomcat 當(dāng)作守護(hù)程序執(zhí)行,需要將服務(wù)組態(tài)文件新增到 /etc/init.d 目錄中,而您可能要將該文件命名為「tomcat」。清單 3 提供了該文件的樣本。這假設(shè)了 Tomcat 安裝在 /home/tomcat 下,并且該位置中有兩個(gè) shell 指令碼文件,用于處理啟動(dòng)和停止服務(wù)器(tcstart.sh 和 tcstop.sh)。在執(zhí)行實(shí)際的 Tomcat 啟動(dòng)或停止指令碼之前,需要使用這些文件來設(shè)定 Tomcat 所需的環(huán)境變量(包括 JAVA_HOME 和 JDK_HOME)。
清單 3. Tomcat 服務(wù)定義
#!/bin/bash
#
# tomcat Starts Tomcat Java server.
#
#
# chkconfig: 345 88 12
# description: Tomcat is the server for Java servlet applications.
### BEGIN INIT INFO
# Provides: $tomcat
### END INIT INFO
# Source function library.
. /etc/init.d/functions
[ -f /home/tomcat/tcstart.sh ] || exit 0
[ -f /home/tomcat/tcstop.sh ] || exit 0
RETVAL=0
umask 077
start() {
echo -n $"Starting Tomcat Java server: "
daemon su -c /home/tomcat/tcstart.sh tomcat
echo
return $RETVAL
}
stop() {
echo -n $"Shutting down Tomcat Java server: "
daemon su -c /home/tomcat/tcstop.sh tomcat
echo
return $RETVAL
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
restart
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
以下是一個(gè)樣本 tcstart.sh,可以修改它來適合您的安裝。
清單 4. 樣本 tcstart.sh
#!/bin/bash
export JDK_HOME=/usr/java/jdk
export JAVA_HOME=/usr/java/jdk
#run the startup script from Tomcat installation
/home/tomcat/server/bin/startup.sh
chroot︰最大的安全性監(jiān)獄
對(duì)于真正的偏執(zhí)狂,還可能進(jìn)一步討論保護(hù) Java 語言服務(wù)。當(dāng)該服務(wù)提供對(duì)本地文件系統(tǒng)的某種形式的存取權(quán)時(shí),這尤其有用。JVM 執(zhí)行時(shí)安全性特性并不能阻止已經(jīng)有權(quán)存取文件系統(tǒng)的應(yīng)用程序存取除了使用者專用的文件之外的文件。在 Tomcat 的情況中,文件存取是它作為 HTTP 服務(wù)器使用時(shí)所固有的。它通常將為每個(gè) Web 應(yīng)用程序提供服務(wù)的文件限制為該應(yīng)用程序目錄中的那些文件,但 servlet 應(yīng)用程序可以避開這些限制。當(dāng) Tomcat 與諸如 Apache 之類別的前端 Web 服務(wù)器共同執(zhí)行時(shí),也會(huì)發(fā)生這種情況。
透過使用 chroot,您可以阻止 Tomcat(和所有在 Tomcat 下執(zhí)行的 Web 應(yīng)用程序)存取為該服務(wù)器留出的空間以外的任何東西。chroot 并不以任何方式特定于 Java 應(yīng)用程序,但它是為 JVM 提供的安全性加入最終包裝器的簡(jiǎn)便方法。我將在這里為那些不熟悉 chroot 概念的人介紹設(shè)定它的要點(diǎn)。
chroot 所做的類別似于用于執(zhí)行 Java 程序代碼的 JVM 沙箱,但它適用于文件系統(tǒng)本身。chroot 執(zhí)行一條指令并將您指定的位置設(shè)定成有效根目錄。所執(zhí)行的指令(可以是執(zhí)行其它指令(包括應(yīng)用程序)的 shell 指令碼)只能存取所指定的有效根目錄下的文件系統(tǒng)的一部分。文件系統(tǒng)的其余部分對(duì)于該指令來說完全不存在。
要對(duì)諸如 Tomcat 之類別的應(yīng)用程序使用 chroot,需要將一些基本系統(tǒng)應(yīng)用程序和鏈接庫(包括實(shí)際的 Java JDK 安裝)復(fù)制到新的虛擬根目錄下。這可能會(huì)占用許多空間 ─ 也許從一百兆字節(jié)到一千兆字節(jié)或更多 ─ 這取決于您想盡多少努力來將這些應(yīng)用程序和鏈接庫減少到最小。設(shè)定它的最簡(jiǎn)單方法也最浪費(fèi)空間︰祇要將整個(gè) /bin、/lib、/usr/bin 和 /usr/lib 目錄樹以及 Java 安裝復(fù)制到新的根目錄下,使 root 使用者成為對(duì)所有文件的擁有者和唯一授權(quán)的寫入者。如果想要讓磁盤使用率保持到最小,可以有選擇地只復(fù)制 chroot 中需要的指令(包括基本指令,如 ls、rm、echo 和 cat 等,以及實(shí)際的 Java 安裝)以及那些指令使用的庫(透過使用 ldd 可以找到那些庫)。
接下來,您將需要建立一些額外目錄作為一般系統(tǒng)的縮減版本。這包括 /dev,以及設(shè)備 /dev/null 和 /dev/zero;/etc 以及 /etc/passwd 和 /etc/group 文件的已編輯版本(只保留 root 和 tomcat 項(xiàng)),也許還有主機(jī)。如果正在多處理器系統(tǒng)上執(zhí)行,您還需要在新的根目錄下掛裝 /proc 系統(tǒng),因?yàn)?JVM 使用該系統(tǒng)來協(xié)調(diào)各個(gè)處理器。
最后,為了在設(shè)定了 chroot 后仍作為使用者 tomcat 執(zhí)行,也許需要建置一個(gè)可以在虛擬根目錄下執(zhí)行的 su 指令版本(許多分發(fā)版的一般版本不容許這樣做)。要這樣做,可以從 GNU 項(xiàng)目獲取 sh-utils 來源碼并根據(jù)該來源碼直接建置 su,然后將它復(fù)制到新的根目錄的 /bin 目錄中。
完成了所有這些設(shè)定后,可以嘗試以 root 使用者身份執(zhí)行(假設(shè)新的根目錄位于 /home/tomcat)︰
/usr/sbin/chroot /home/tomcat /bin/su tomcat
如果設(shè)定正確,這應(yīng)該讓您在新的根目錄下作為 tomcat 執(zhí)行,而且您可以嘗試使用您的指令碼來啟動(dòng)和停止 Tomcat。在證實(shí)了所有東西都工作之后,最后一步就是將清單 3 中的 Tomcat 服務(wù)定義變更成使用 chroot 來代替 su,將 su 指令移到 tcstart.sh 指令碼和 tcstop.sh 指令碼。還需要確保只能由 root 使用者修改這些指令碼。
希望這篇概述的解釋很清楚,這個(gè)過程并不適合膽小的人﹗如果您選擇走使用 chroot 這條路線,但以前沒有使用過 chroot,那么您一定要參考網(wǎng)上的 chroot 參考數(shù)據(jù)之一,以獲取詳細(xì)信息。但是這確實(shí)會(huì)給您的 Java 服務(wù)器程序代碼可能最好的隔離,而且在某些情況下,帶來的內(nèi)心的寧靜值得這樣做。
結(jié)語
Linux 和 Java 技術(shù)都正在贏得商業(yè)系統(tǒng)的市場(chǎng)份額。盡管開放來源碼 Linux 和特許 Java 技術(shù)之間存在著原理上的差異,但這兩者在一起確實(shí)配合得很好。Linux 對(duì)于 Java 應(yīng)用程序,尤其是對(duì)于服務(wù)器類別型的應(yīng)用程序是一個(gè)極好的部署環(huán)境,而 Java 技術(shù)是作為企業(yè)軟件開發(fā)的先進(jìn)方法而建立且得到了認(rèn)可。
透過正確的預(yù)防措施,在 Linux 上執(zhí)行的 Java 服務(wù)器應(yīng)用程序可以提供非常高的安全性程度 ─ 甚至高于本機(jī)應(yīng)用程序 ─ 因?yàn)?Java 技術(shù)消除了服務(wù)器應(yīng)用程序中許多弱點(diǎn)的常見來源。Java 技術(shù)的跨平臺(tái)性質(zhì)所帶來的是包括企業(yè)工作人員和 Linux 立即就緒的應(yīng)用程序的巨大資源集合。Java 服務(wù)器應(yīng)用程序開始在日益增長(zhǎng)的 Linux 的服務(wù)器市場(chǎng)份額中扮演重要角色,而且這種趨勢(shì)在將來只會(huì)幫助這兩種技術(shù)。
我要感謝 Miles Sabin 向我指出了 /proc 文件系統(tǒng),來解決在多處理器系統(tǒng)上 chroot Java 的問題。