2011年4月8日

淺談Linux普通使用者權限安裝軟體,以node.js為例

通常在Linux作業系統安裝新軟體,需要root權限,因為系統目錄都只有root可以讀寫。而普通user則只能讀寫家目錄「/home/*」下自己專屬的資料夾。這種嚴格的權限控管機制,可以讓一台Linux伺服器,開放給很多使用者共用。而沒有root權限的使用者,即使做了不該做的傻事,也不會影響到整個系統,頂多把自己的家目錄給毀了(但熟悉linux的黑客級使用者,還是可以鑽漏洞幹壞事,所以租用多人共享的虛擬主機並不安全就是這樣)。

現代的Linux發行版,會提供很好用的套件管理工具,例如Debian/Ubuntu的apt、Fedora/Suse的yum,一般常用的軟體,只要被收錄到發行版的套件庫,就可以用這些套件管理工具進行安裝/移除。

使用套件管理的好處很多,我們只要確定系統設定的套件來源(repository)是可信任的,就可以比較放心地自動完成新軟體安裝,而不需要這個軟體時,它也會幫我們移除乾淨。而軟體因功能更新或修補漏洞,釋出新版本時,只要簡單下個指令就可以幫我們升級所有已安裝的套件。

以apt來說,常用到的功能有:
  • 更新本地套件清單:apt-get update
  • 尋找某個軟體: apt-cache search 軟體名稱
  • 安裝: apt-get install 軟體名稱
  • 移除: apt-get remove 軟體名稱
  • 升級: apt-get upgrade
有些軟體不存在套件庫,這時候我們就要去抓source或binary的版本,由於安裝過程可能會去更改系統目錄及設定。不透過套件管理工具,自行以其他方式安裝新軟體,具有潛在的風險,因為不同Linux系統的目錄格式可能不同,而網路下載的軟體也可能藏在惡意或疏忽造成的程式碼,會讓系統產生不可預期的影響。

即使軟體本身沒問題,也可以正確安裝到系統目錄下,但需要移除時又會是另一個問題,因為有很多軟體本身並不提供移除功能,系統管理者必須要自己判斷,哪些檔案該刪除、哪些設定該修改成安裝前的樣子。即使軟體有提供移除功能,通常還要使用和安裝時同一個版本,才能正確移除。

就算安裝和移除都不是問題,還要由系統管理者自行解決更新升級的問題。首先,自行安裝的軟體,通常有新版時不會通知,可能因此忽略了安全問題所需要的更新。而到底要先移除在安裝新版,還是可以直接覆蓋成新版,以及新版裝好是不是還要執行什麼程式,才能修正新舊版之間的差異(migration),這些都有賴系統管理者自己熟讀文件。

而套件管理工具,就是由熟悉這些軟體的開發者,幫我們寫好安裝移除所需的script,並依照特定系統版本將編譯好的程式打包,也會考慮到版本升級的問題。所以我們只要用簡單的指令,就可以完成軟體新增移除的工作。

所以即使Linux系統本身有良好的權限控管機制,也以高效能、安全且穩定著稱,最後還是會因為操作者本身不熟悉或疏忽,造成系統使用一段時間後,存在太多混亂的問題,只能以重灌收場。

有許多操作Windows的習慣,不適合用在Linux作業系統。因為一般人使用的Windows,通常為「個人用途」設計,所以網路下載一個免費軟體,就直接裝上去,是很自然的事;雖然近來的Windows也開始有些權限控管機制,但畢竟多數人還是以自己方便為主,會選擇比較鬆散的權限控制,即使是自己和家人共用同一部Windows電腦,也不太會去限制其他人怎麼存取。

但Linux系統一開始的設計就是「多人多工」的伺服器用途,系統本身需要非常穩定,接觸比較久的使用者都會知道,root(超級使用者)權限是非常恐怖的,一不小心做了蠢事,就會難以挽回。所以一個安全的Linux伺服器,必定會限制root帳號不能使用TELNET、FTP甚至SSH直接登入,也不會給root密碼,只能限定特定帳號以sudo方式執行授權的root的工作。

普通使用者是在受到隔離的環境下操作系統,不能存取系統目錄,很多設定檔不只不能編輯,可能連內容都無法看到。但這樣的設計,對於把Linux拿來當作「個人用途」桌面系統的使用者,就會覺得很麻煩,畢竟是自己的電腦、不是伺服器,當然會需要隨時都有足夠的權限去做任何事。

所以現代的Linux作業系統,像是Ubuntu Desktop,當我們進行的一項操作,如果需要root權限,這時候系統就會自動以sudo方式,讓你只要輸入自己的密碼,就能得以root權限進行操作,並且驗證還可能維持一段時間都有效。

而習慣了權限不受限制的Linux使用者,使用學校的Linux伺服器、租用Linux虛擬主機,或是和別人共用Linux作業系統,可能就會覺得沒有root權限很礙手礙腳。但是對於一台需要長時間運作的Linux伺服器,別說要拿到root權限,即使要把軟體裝到系統目錄都是不可能的。

其實從網路下載的tarball(*.tar.gz)的軟體,並不一定要root權限才能安裝,例如常見的tarball安裝過程會包含3道指令。
./configure
make
make install

其中只有「make install」會需要root權限,原因是一些編譯好的程式,需要複製到系統目錄(例如 /usr)下。但是只要在./configure加上--prefix參數,就能把安裝路徑更改成自己的家目錄。
./configure --prefix=/home/xxx
make
make install

以下以node.js為例,說明如何在沒有root權限的Ubuntu Linux Server系統進行安裝。

由於在Server上,很可能連編譯工具都沒有,對極要求安全的伺服器,提供軟體開發工具,等於幫駭客開了方便之門。所以我們可以用虛擬機器,先建立一個和目標伺服器相同架構(x86或amd64)的Linux開發環境,最好能夠版本也相同。

由於是自己的Linux,所以可以用sudo安裝node.js需要的開發工具。
sudo apt-get install g++ curl libssl-dev apache2-utils git-core

接著按照安裝教學文件的方法,把node.js裝到自己的家目錄(請注意--prefix參數)。
git clone git://github.com/joyent/node
cd clone
./configure --prefix=~/pack
make
make install

因為「make install」沒有加sudo,所以使用普通使用者權限進行安裝,而檔案會複製到--prefix參數指定的「~/pack」資料夾下。

安裝完成後,看一下安裝好的檔案。
ls ~/pack

我們可以看到 bin、include、lib、share 這些子目錄被建立在pack目錄下,也就是原本應該裝到系統目錄下的結構,被放到pack目錄下。我們可以將pack打包,指令用tar即可。
cd ~
tar zcvf my-pack.tar.gz pack

接著,把my-pack.tar.gz上傳到Server,再用tar解開。
tar zxvf my-pack.tar.gz

然後,編輯 ~/.profile 再最後加上一行:
export PATH=~/pack/bin:$PATH

重新登入,或是直接在終端機執行上面的export指令,就可以下「node」指令。
node --version

等等,萬一出現LIBRARY找不到的錯誤訊息,怎麼辦?

上面的步驟,是假設Server已經有「node.js」需要的library,例如libssl等,因為我們並沒有自行編譯打包相依的library。所以這種方法,適合想安裝到Server的軟體,該有的基本library都已經存在,把編譯好的程式丟上去就能跑的情況。

如果Server缺東缺西,那麼也只有幾種選擇了...
  1. 請系統管理員裝上(如果是基本該有的library,這算合理要求吧)
  2. 每樣東西都自己編譯打包(但這也太累了吧)
  3. 架一台自己的Server
如果上述都沒問題,以普通使用者權限執行「node.js」會不會有其他問題呢?答案還是有的,因為Linux通常會限制1~1023這些port只能由root權限執行的程式listen,因為這個範圍包含很多常用的重要網路服務,所以要避免被心懷不軌的使用者程式冒用。普通使用者執行的程式,是無法使用這些port,而node.js的範例使用8124就沒問題。

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');

是不是只要別用1~1023這些port就可以呢?答案是不一定,因為注重安全的伺服器還會設定防火牆,所以並不是程式開port成功,就一定能接受遠端的連線。對於多人共享的虛擬主機,即使有開放SSH,廠商當然也不會希望客戶自己跑自己的server程式,因為那會佔用CPU/RAM,使用者自己跑的server程式可能會有些無法控管的行為。

由於目前的虛擬化技術已經很成熟,所以真的有需要架設網路應用程式,除了自己架設伺服器的方案外,也可以向虛擬主機商租用VPS(虛擬專屬主機,行銷的講法叫作雲端伺服器),就能享有全部的管理權限。租用VPS雖然有完全專屬作業系統,可以自己架設需要的服務,但是記憶體、磁碟容量和處理器用量都會有所限制,這時對Linux系統管理的熟悉度,就會影響作業系統和伺服器的最佳化。

沒有留言:

張貼留言

lyhcode by lyhcode
歡迎轉載,請務必註明出處!