close

 

前情提要:

 

Fedora 29 架站實務 之 Part 7 安全與權限問題

 

(本篇文長,請務必耐心閱讀)

 

這不是很簡單的事情嗎?:

 

直接放到/usr/share/nginx/html 下不就萬事OK了嗎 ? 但我想這個疑問也是一個剛切換到RedHat Based Linux 的疑問。我剛開始也不信邪,然而奇怪的問題接踵而至: 怎麼從其他地方移動到/html中的網頁都存取不了 ? 甚至最後搬出大絕招,資料夾擁有者改nginx,擁有者也改nginxchmod 777 也無效。縱使突然好了,怎麼樣子都無法讓/html 中的php網頁執行寫入檔案動作。

 

It really grinds up my nerve.

 

難道Fedora 可以Bloody Cutting-Edge 到連Bug 都放這麼大嗎 ?

不,這是一個從其他Linux 發行版(尤其是Debian-based),切換到RedHat Based Linux 的鬼打牆,一個無形警察: SELinux

 

 

開始前請注意:

 

請不要隨意執行setenforce 0 或 透過 /etc/sysconfig/selinux SELINUX=disabled,除非您在進行測試,否則在可能的情形下,以透過更改SELinux 規則或繞道法(我們等一下會提及)來讓您的網頁或程式能在SELinux 執行的模式下提供服務。SELinux 提供了您系統良好的安全性,是做為公開伺服器十分需要的條件之一。

 

 

What is SELinux ?:

 

SELinux用來補足Linux 在權限上管理的不足,你可以對任何目標(例如應用程式、檔案、資料夾等) 規定十分嚴謹的規則,好比nginx / apache 這類的程式,都適用預先規定的httpd_xxx 的各種SELinux規則。

 

如果想要看SELinux 對於httpd 規定了哪些行為:

 

# getsebool -a | grep httpd

 

 

 

接著我們來觀看html 資料夾套用的SELinux限制:

 

# ls -lZ /usr/share/nginx | grep html

 

 

 

我們來看Nginx 的一些重要的預設SELinux 設定(會直接影響架站的):

 

httpd_can_network_connect --> off (是否允許httpd類程式主動連線其他主機 ?)

httpd_can_network_connect_db --> off (是否允許httpd類程式主動連線外部資料庫 ?)

httpd_can_sendmail --> off (httpd類程式是否可以主動進行寄送電子郵件 ?)

httpd_sys_rw_content_t --> httpd類程式能對目標項目(資料夾或檔案)做讀取、執行與寫入。

httpd_sys_content_t --> httpd 類程式只能對目標項目(資料夾或檔案)做讀取與執行,不能寫入(我們可以看到html資料夾就是這個設定)

 

 

我們先來解釋這幾項為什麼會直接影響到架站:

 

httpd_can_network_connect httpd_sys_content_t:

多數的網頁框架軟體(好比WordPress, Drupal, Joomla) 上載檔案、變更設定、安裝外掛、安裝主題等等時,都會對網站資料夾內的內容作出變更。不開放寫入權限會讓這些行為失敗。而又如Wordpress中有線上更新與線上安裝外掛的功能,若系統不開放httpd類程式聯網,這類功能也無法使用。

當然您的網頁可能是靜態的,那這些行為都不需要做,不過仍請翻到更後面說明的: 資料夾SE權限重建。

 

httpd_can_network_connect_db:

如果您的資料庫是在其他台電腦時,這會讓您的網頁執行需要存取其他電腦,此時您必須將此項開啟。否則連線會失敗(包含存取lo(loopback)介面(127.0.0.1)localhost不會)

 

httpd_can_sendmail:

(尤其是論壇類) 如果您的電腦需要寄送信件(好比註冊確認信件等),您必須要讓httpd能夠執行sendmail功能。

 

 

而怎麼變更這些SELinux設定值呢 ?:

 

setsebool [設定項目] [啟動或關閉]

例如: setsebool httpd_can_network_connect on/off

 

在大部分的情況之下,架設個人部落格或小型網站,我們考慮網頁伺服器與資料庫在同一台主機上,故我們只針對httpd_sys_content_t(也就是不能寫入的html資料夾)做處理。

 

 

安裝semanage,SELinux的項目權限管理工具

 

由於系統預設是沒有這項工具的,所以需要安裝:

 

# dnf install policycoreutils-python-utils

 

 

指令語法:

semanage [fcontext (對目標項目永久變更)] [增加(-a)/移除(-d)或修改(-m)] [-t (SE權限)] “[目標(一定要是完整目錄)][(/.*)? 包含目標中所有子項目]”

 

 

一旦對於一個目標或項目做了變更,都必須要求系統更新SELinux狀態:

 

restorecon [-R是否要連目標中所有子項目都要變更] [v要不要顯示每一個子項目做得更改在螢幕上] [目標]

 

範例:

# cd /usr/share/nginx/html/

# ls -lZ

1個項目

drwxr-xr-x. 2 root root unconfined_u:object_r:httpd_sys_content_t:s0 6 326 16:57 testfolder

 

# semanage fcontext -a -t httpd_sys_rw_content_t “/usr/share/nginx/html/testfolder(/.*)?”

# restorecon -Rv /usr/share/nginx/html/testfolder

Relabeled….

# cd testfolder

# ls -lZ

2個項目

-rw-r--r--. 1 nginx nginx unconfined_u:object_r:httpd_sys_rw_content_t:s0 10 326 17:04 testfile1

-rw-r--r--. 1 nginx nginx unconfined_u:object_r:httpd_sys_rw_content_t:s0 10 326 17:04 testfile2

 

 

 

任何一個已經被賦予SELinux權限的項目若要更換其權限可以有兩種做法:

 

刪除原本的權限(semanage -d) 再新增

或是使用修改(semanage -m)

 

 

系統預設的SELinux檔案權限我可以從哪裡取得 ?:

 

# cat /etc/selinux/targeted/contexts/files/file_contexts

# cat /etc/selinux/targeted/contexts/files/file_contexts.homedir (跟家目錄管理相關的)

 

 

除了系統預設的SELinux檔案權限之外,我要怎麼知道哪些資料夾或檔案早就被我賦予SELinux 權限呢 ?:

 

# cat /etc/selinux/targeted/contexts/files/file_contexts.local

 

 

然而事與願違:

 

# ls -lZ /usr/share/nginx/

 

 

我們可以看到html 資料夾有被賦予SELinux 權限,故我們試圖將其從httpd_sys_content_t 改為httpd_sys_rw_content_t,然而當我們試圖移除權限時:

 

# semanage fcontext -d -t httpd_sys_content_t “/usr/share/nginx/html(/.*)?”

ValueError: /usr/share/nginx/html(/.*)? 的檔案情境已經定義在方針中,無法刪除

 

因為/usr/share/nginx/html 在系統規定的預設情境中。

 

 

備註: 情境是SELinux 對其中一個Profile 的稱呼,系統可以擁有多個情境,每個情境中都有不同的SELinux規則和設定,方便使用者管理與切換。

 

 

這時後要怎麼辦呢 ?

 

兩個解:

自行建立一個資料夾(例如/data/www/) 然後賦予 httpd_sys_rw_content_t

/usr/share/nginx/html/資料夾中,再建立一個資料夾並賦予httpd_sys_rw_content_t,然後把跟目錄改到那裏去。

 

 

我們以比較簡單,容易管理的方法,建立/data/www ,並賦予httpd_sys_rw_content_t來繼續:

 

# mkdir /data/

# mkdir /data/www/

同時寫一個php寫入小程式來測試: 如果正常則會出現空白頁面,失敗則會出現500 Internal Error

# nano /data/www/phpwrite.php

然後在寫一個Hello World html index

# nano /data/www/index.html

 

 

 

phpwrite.php:

<?php

$content = “some text”;

$fp = fopen($_SERVER[‘DOCUMENT_ROOT’], “/myText.txt”, “wb”);

fwrite($fp, $content);

fclose($fp);

?>

 

index.html

<html>

<title>Hello World!</title>

<body>

<p>

<h1> How are you ?</h1>

</p>

</body>

</html>

 

 

把整個目錄內的所有內容全部送給nginx(讓檔案與資料夾屬於nginx):

 

# chown -R nginx.nginx /data/www/

 

 

 

最後賦予這些檔案與目錄有httpd_sys_rw_content_t權限:

 

# semanage fcontext -a -t httpd_sys_rw_content_t “/data/www(/.*)?”

# restorecon -Rv /data/www/

 

 

 

所以了解完SELinux 現在我們得來了解Nginx Config File: /etc/nginx/nginx.conf:

 

 

Nginx Config的大架構:

 

 

備註:

 

好習慣要養成,變更任何config file 前,請先做好一份備份:

# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup

發生問題時才能回到上一次沒問題的狀態。

 

 

講這麼多,基本上就是要把root 那行改成/data/www/ 就行了。

 

但請不要覺得囉嗦,這些也許在未來會成為幫助您完nginx 新把戲的必備:

 

# nano /etc/nginx/nginx.conf

找到 root /usr/share/nginx/html 改成 root /data/www/

儲存並結束

 

 

 

nginx 先檢查您的設定檔是否有語法錯誤:

 

# nginx -t

重新啟動 nginx

# systemctl restart nginx

 

 

 

測試時間! 開啟瀏覽器:

 

輸入: http://[你的IP]

 

 

如果看到這個,你已經完成了正確設定SELinuxnginx 也正常執行了

 

我們接著來測試php寫入功能是否正常:

 

輸入: http://[你的IP]/phpwrite.php

 

 

如果看到空白頁面才是正常的喔。

 

我們來看一下php產生的檔案:

 

 

如果能看到some text

 

那麼恭喜你: 你已經正式的讓Fedora 成為你的架站利器了!

(然後我要去睡覺了~)

arrow
arrow

    狼志浩 發表在 痞客邦 留言(0) 人氣()