1. 程式人生 > >Linux就該這麼學_第10章 使用Apache伺服器部署靜態網站

Linux就該這麼學_第10章 使用Apache伺服器部署靜態網站

本章講解了如下內容:

  • 網站服務程式;
  • 配置服務檔案引數;
  • SELinux安全子系統;
  • 個人使用者主面功能
  • 虛擬主機功能
  • Apache的訪問控制

本章先向讀者科普什麼是 Web 服務程式,以及 Web 服務程式的用處,然後通過對比當前 主流的 Web 服務程式來使讀者更好地理解其各自的優勢及特點,最後通過對 httpd 服務程式 中“全域性配置引數”、“區域配置引數”及“註釋資訊”的理論講解和實戰部署,確保讀者學會 Web 服務程式的配置方法,並真正掌握在 Linux 系統中配置服務的技巧。 劉遄老師還會在本章講解 SELinux 服務的作用、三種工作模式以及策略管理方法,確 保讀者掌握 SELinux 域和 SELinux 安全上下文的配置方法,並依次完成多個基於 httpd 服 務程式實用功能的部署實驗,其中包括 httpd 服務程式的基本部署、個人使用者主頁功能和 口令加密認證方式的實現,以及分別基於 IP 地址、主機名(域名)、埠號部署虛擬主機 網站功能。

10.1 網站服務程式

1970 年,作為網際網路前身的 ARPANET(阿帕網)已初具雛形,並開始向非軍用部門開 放,許多大學和商業部門開始接入。雖然彼時阿帕網的規模(只有 4 臺主機聯網執行)還不 如現在的區域網成熟,但是它依然為網路技術的進步打下了紮實的基礎。 想必我們大多數人都是通過訪問網站而開始接觸網際網路的吧。我們平時訪問的網站服務 就是 Web 網路服務,一般是指允許使用者通過瀏覽器訪問到網際網路中各種資源的服務。如圖 10- 1 所示,Web 網路服務是一種被動訪問的服務程式,即只有接收到網際網路中其他主機發出的 請求後才會響應,最終用於提供服務程式的 Web 伺服器會通過 HTTP(超文字傳輸協議)或 HTTPS(安全超文字傳輸協議)把請求的內容傳送給使用者。 目前能夠提供 Web 網路服務的程式有 IIS、Nginx 和 Apache 等。其中,IIS(Internet  Information Services,網際網路資訊服務)是 Windows 系統中預設的 Web 服務程式,這是一款 圖形化的網站管理工具,不僅可以提供 Web 網站服務,還可以提供 FTP、NMTP、SMTP 等服務。但是,IIS 只能在 Windows 系統中使用,而我們這本書的名字是《Linux 就該這麼學》, 所以它也就不在我們的學習範圍之內了。

2004 年 10 月 4 日,為俄羅斯知名門戶站點而開發的 Web 服務程式 Nginx 橫空出世。 Nginx 程式作為一款輕量級的網站服務軟體,因其穩定性和豐富的功能而快速佔領伺服器市 場,但 Nginx 最被認可的還當是系統資源消耗低且併發能力強,因此得到了國內諸如新浪、 網易、騰訊等門戶站的青睞。本書將在第 20 章講解 Nginx 服務程式。 Apache 程式是目前擁有很高市場佔有率的 Web 服務程式之一,其跨平臺和安全性廣 泛被認可且擁有快速、可靠、簡單的 API 擴充套件。圖 10-2 所示為 Apache 服務基金會的著名 Logo,它的名字取自美國印第安人的土著語,寓意著擁有高超的作戰策略和無窮的耐性。 Apache 服務程式可以執行在 Linux 系統、UNIX 系統甚至是 Windows 系統中,支援基於 IP、域名及埠號的虛擬主機功能,支援多種認證方式,整合有代理伺服器模組、安全 Socket 層(SSL),能夠實時監視服務狀態與定製日誌訊息,並有著各類豐富的模組支援。

總結來說,Nginx 服務程式作為後起之秀,已經通過自身的優勢與努力贏得了大批站長 的信賴。本書配套的線上學習站點 http://www.linuxprobe.com 就是基於 Nginx 服務程式部署 的,不得不說 Nginx 也真的很棒! 但是,Apache 程式作為老牌的 Web 服務程式,一方面在 Web 伺服器軟體市場具有相當高的 佔有率,另一方面 Apache 也是 RHEL 7 系統中預設的 Web 服務程式,而且還是 RHCSA 和 RHCE 認證考試的必考內容,因此無論從實際應用角度還是從應對紅帽認證考試的角度,我們都有必要 好好學習 Apache 服務程式的部署,並深入挖掘其可用的豐富功能。

10.2 配置服務檔案引數

需要提醒大家的是,前文介紹的 httpd 服務程式的安裝和執行,僅僅是 httpd 服務程式的 一些皮毛,我們依然有很長的道路要走。在 Linux 系統中配置服務,其實就是修改服務的配 置檔案,因此,還需要知道這些配置檔案的所在位置以及用途,httpd 服務程式的主要配置文 件及存放位置如表 10-1 所示。

大家在首次開啟 httpd 服務程式的主配置檔案,可能會嚇一跳—竟然有 353 行!這得至 少需要一週的時間才能看完吧?!但是,大家只要仔細觀看就會發現劉遄老師在這裡調皮了。 因為在這個配置檔案中,所有以井號(#)開始的行都是註釋行,其目的是對 httpd 服務程式 的功能或某一行引數進行介紹,我們不需要逐行研究這些內容。 在 httpd 服務程式的主配置檔案中,存在三種類型的資訊:註釋行資訊、全域性配置、區域配置,如圖 10-4 所示。

各位讀者在學習第 4 章時已經接觸過註釋資訊,因此這裡主要講解全域性配置引數與區域 配置引數的區別。顧名思義,全域性配置引數就是一種全域性性的配置引數,可作用於對所有的 子站點,既保證了子站點的正常訪問,也有效減少了頻繁寫入重複引數的工作量。區域配置 引數則是單獨針對於每個獨立的子站點進行設定的。就像在大學食堂裡面打飯,食堂負責打 飯的阿姨先給每位同學來一碗標準大小的白飯(全域性配置),然後再根據每位同學的具體要求 盛放他們想吃的菜(區域配置)。在 httpd 服務程式主配置檔案中,最為常用的引數如表 10-2 所示。

 從表 10-2 中可知,DocumentRoot 引數用於定義網站資料的儲存路徑,其引數的預設值 是把網站資料存放到/var/www/html 目錄中;而當前網站普遍的首頁面名稱是 index.html,因 此可以向/var/www/html 目錄中寫入一個檔案,替換掉 httpd 服務程式的預設首頁面,該操作

會立即生效。在執行上述操作之後,再在 Firefox 瀏覽器中重新整理 httpd 服務程式,可以看到該程式的首 頁面內容已經發生了改變,如圖 10-5 所示。

[[email protected] ~]# echo "Welcome To LinuxProbe.com" > /var/www/html/index.html

圖 10-5 httpd 服務程式的首頁面內容已經被修改

大家在完成這個實驗之後,是不是信心爆棚了呢?!在預設情況下,網站資料是儲存在 /var/www/html 目錄中,而如果想把儲存網站資料的目錄修改為/home/wwwroot 目錄,該怎麼 操作呢?且看下文。

第1步:建立網站資料的儲存目錄,並建立首頁檔案。

[[email protected] ~]# mkdir /home/wwwroot
[[email protected] ~]# echo "The New Web Directory" > /home/wwwroot/index.html
[[email protected] ~]# 

第2步:開啟 httpd 服務程式的主配置檔案,將約第 119 行用於定義網站資料儲存路徑的 引數 DocumentRoot 修改為/home/wwwroot,同時還需要將約第 124 行用於定義目錄許可權的參 數 Directory 後面的路徑也修改為/home/wwwroot。配置檔案修改完畢後即可儲存並退出。

[[email protected] ~]# vim /etc/httpd/conf/httpd.conf
………………省略部分輸出資訊………………
113
114 #
115 # DocumentRoot: The directory out of which you will serve your
116 # documents. By default, all requests are taken from this directory, but
117 # symbolic links and aliases may be used to point to other locations.
118 #
119 DocumentRoot "/home/wwwroot"
120
121 #
122 # Relax access to content within /var/www.
123 #
124 <Directory "/home/wwwroot">
125 AllowOverride None
126 # Allow open access:
127 Require all granted
128 </Directory>
………………省略部分輸出資訊………………
[[email protected] ~]#

第3部::重新啟動 httpd 服務程式並驗證效果,瀏覽器重新整理頁面後的內容如圖 10-6 所示。

奇怪!為什麼看到了 httpd 服務程式的預設首頁面?按理來說,只有在網站的首頁面檔案不存 在或者使用者許可權不足時,才顯示 httpd 服務程式的預設首頁面。我們在嘗試訪問 http://127.0.0.1/index.html 頁面時,竟然發現頁面中顯示“Forbidden,You don't have permission  to access /index.html on this server.”。而這一切正是 SELinux 在搗鬼。

[[email protected] ~]# systemctl restart httpd

 圖 10-6 httpd 服務程式的預設首頁面

10.3  SELinux安全子系統

SELinux(Security-Enhanced Linux)是美國國家安全域性在 Linux 開源社群的幫助下開發的 一個強制訪問控制(MAC,Mandatory Access Control)的安全子系統。RHEL 7 系統使用 SELinux 技術的目的是為了讓各個服務程序都受到約束,使其僅獲取到本應獲取的資源。 例如,您在自己的電腦上下載了一個美圖軟體,當您全神貫注地使用它給照片進行美顏 的時候,它卻在後臺默默監聽著瀏覽器中輸入的密碼資訊,而這顯然不應該是它應做的事情 (哪怕是訪問電腦中的圖片資源,都情有可原)。SELinux 安全子系統就是為了杜絕此類情況而 設計的,它能夠從多方面監控違法行為:對服務程式的功能進行限制(SELinux 域限制可以確 保服務程式做不了出格的事情);對檔案資源的訪問限制(SELinux 安全上下文確保檔案資源 只能被其所屬的服務程式進行訪問)。 劉遄老師經常會把“SELinux 域”和“SELinux 安全上下文”稱為是 Linux 系統中的雙保 險,系統內的服務程式只能規規矩矩地拿到自己所應該獲取的資源,這樣即便黑客入侵了系 統,也無法利用系統內的服務程式進行越權操作。但是,非常可惜的是,SELinux 服務比較復 雜,配置難度也很大,加之很多運維人員對這項技術理解不深,從而導致很多伺服器在部署 好 Linux 系統後直接將 SELinux 禁用了;這絕對不是明智的選擇。 SELinux 服務有三種配置模式,具體如下。

➢ enforcing:強制啟用安全策略模式,將攔截服務的不合法請求。 ➢ permissive:遇到服務越權訪問時,只發出警告而不強制攔截。 ➢ disabled:對於越權的行為不警告也不攔截。

本書中的所有實驗都是在強制啟用安全策略模式下進行的,雖然在禁用 SELinux 服務後 確實能夠減少報錯機率,但這在生產環境中相當不推薦。建議大家檢查一下自己的系統,查 看 SELinux 服務主配置檔案中定義的預設狀態。如果是 permissive 或 disabled,建議趕緊修改 為 enforcing。

[[email protected] ~]# vim /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted

SELinux 服務的主配置檔案中,定義的是 SELinux 的預設執行狀態,可以將其理解為系 統重啟後的狀態,因此它不會在更改後立即生效。可以使用 getenforce 命令獲得當前 SELinux 服務的執行模式:

[[email protected] ~]# getenforce
Enforcing

為了確認圖 10-6 所示的結果確實是因為 SELinux 而導致的,可以用 setenforce [0|1]命令 修改 SELinux 當前的執行模式(0 為禁用,1 為啟用)。注意,這種修改只是臨時的,在系統 重啟後就會失效:

[[email protected] ~]# setenforce 0
[[email protected] ~]# getenforce
Permissive

再次重新整理網頁,就會看到正常的網頁內容了,如圖 10-7 所示。可見,問題確實是出在了 SELinux 服務上面。

圖 10-7 頁面內容按照預期顯示

現在,我們來回憶一下前面的操作中到底是哪裡出問題了呢? httpd 服務程式的功能是允許使用者訪問網站內容,因此 SELinux 肯定會預設放行使用者對網站的請求操作。但是,我們將網站資料的預設儲存目錄修改為了/home/wwwroot,而這就產生 問題了。在 6.1 小節中講到,/home 目錄是用來存放普通使用者的家目錄資料的,而現在,httpd 提供的網站服務卻要去獲取普通使用者家目錄中的資料了,這顯然違反了 SELinux 的監管原則。 現在,我們把 SELinux 服務恢復到強制啟用安全策略模式,然後分別檢視原始網站資料 的儲存目錄與當前網站資料的儲存目錄是否擁有不同的 SELinux 安全上下文值:

[[email protected] ~]# setenforce 1
[[email protected] ~]# ls -Zd /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html
[[email protected] ~]# ls -Zd /home/wwwroot
drwxrwxrwx. root root unconfined_u:object_r:home_root_t:s0 /home/wwwroot

在檔案上設定的 SELinux 安全上下文是由使用者段、角色段以及型別段等多個資訊項共同 組成的。其中,使用者段 system_u 代表系統程序的身份,角色段 object_r 代表檔案目錄的角色, 型別段 httpd_sys_content_t 代表網站服務的系統檔案。由於 SELinux 服務實在太過複雜,現在 大家只需要簡單熟悉 SELinux 服務的作用就可以,劉遄老師未來會在本書的進階篇中單獨拿 出一個章節仔細講解 SELinux 服務。 針對當前這種情況,我們只需要使用 semanage 命令,將當前網站目錄/home/wwwroot 的 SELinux 安全上下文修改為跟原始網站目錄的一樣就可以了。

10.3.1 semanage命令

semanage 命令用於管理 SELinux 的策略,格式為“semanage [選項] [檔案]”。 SELinux 服務極大地提升了 Linux 系統的安全性,將使用者許可權牢牢地鎖在籠子裡。 semanage 命令不僅能夠像傳統 chcon 命令那樣—設定檔案、目錄的策略,還可以管理網路 埠、訊息介面(這些新特性將在本章後文中涵蓋)。使用 semanage 命令時,經常用到的幾個 引數及其功能如下所示: ➢ -l 引數用於查詢; ➢ -a 引數用於新增; ➢ -m 引數用於修改; ➢ -d 引數用於刪除。 例如,可以向新的網站資料目錄中新新增一條 SELinux 安全上下文,讓這個目錄以及裡 面的所有檔案能夠被 httpd 服務程式所訪問到:

[[email protected] ~]# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot
[[email protected] ~]# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/*

注意,執行上述設定之後,還無法立即訪問網站,還需要使用 restorecon 命令將設定好的 SELinux 安全上下文立即生效。在使用 restorecon 命令時,可以加上-Rv 引數對指定的目錄進 行遞迴操作,以及顯示 SELinux 安全上下文的修改過程。最後,再次重新整理頁面,就可以正常 看到網頁內容了,結果如圖 10-8 所示。

[[email protected] ~]# restorecon -Rv /home/wwwroot/
restorecon reset /home/wwwroot context unconfined_u:object_r:home_root_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
restorecon reset /home/wwwroot/index.html context unconfined_u:object_r:home_root_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0

圖 10-8 正常看到網頁內容

真可謂是一波三折!原本認為只要把 httpd 服務程式配置妥當就可以大功告成,結果卻反 復受到了 SELinux 安全上下文的限制。所以,建議大家在配置 httpd 服務程式時,一定要細 心、耐心。一旦成功配妥 httpd 服務程式之後,就會發現 SELinux 服務並沒有那麼難。

 10.4 個人使用者主頁功能

如果想在系統中為每位使用者建立一個獨立的網站,通常的方法是基於虛擬網站主機功能 來部署多個網站。但這個工作會讓管理員苦不堪言(尤其是使用者數量很龐大時),而且在使用者 自行管理網站時,還會碰到各種許可權限制,需要為此做很多額外的工作。其實,httpd 服務程 序提供的個人使用者主頁功能完全可以以勝任這個工作。該功能可以讓系統內所有的使用者在自 己的家目錄中管理個人的網站,而且訪問起來也非常容易。

第1步:在 httpd 服務程式中,預設沒有開啟個人使用者主頁功能。為此,我們需要編輯下 面的配置檔案,然後在第 17 行的 UserDir disabled 引數前面加上井號(#),表示讓 httpd 服務 程式開啟個人使用者主頁功能;同時再把第 24 行的 UserDir public_html 引數前面的井號(#)去 掉(UserDir 引數表示網站資料在使用者家目錄中的儲存目錄名稱,即 public_html 目錄)。最後, 在修改完畢後記得儲存。

第2步:在使用者家目錄中建立用於儲存網站資料的目錄及首頁面檔案。另外,還需要把 家目錄的許可權修改為 755,保證其他人也有許可權讀取裡面的內容。

[[email protected] ~]# su - jingpan
上一次登入:一 10月 15 17:06:28 CST 2018pts/0 上
[[email protected] ~]$ mkdir public_html
[[email protected] ~]$ echo "This is linuxprob's website" > public_html/index.html
[[email protected] ~]$ echo "This is jingpan's website" > public_html/index.html
[[email protected] ~]$ chmod -Rf 755 /home/jingpan

第3步:重新啟動 httpd 服務程式,在瀏覽器的位址列中輸入網址,其格式為“網址/~用 戶名”(其中的波浪號是必需的,而且網址、波浪號、使用者名稱之間沒有空格),從理論上來講就 可以看到使用者的個人網站了。不出所料的是,系統顯示報錯頁面,如圖 10-9 所示。這一定還 是 SELinux 惹的禍。

圖 10-9 禁止訪問使用者的個人網站

第4步:思考這次報錯的原因是什麼。httpd 服務程式在提供個人使用者主頁功能時,該用 戶的網站資料目錄本身就應該是存放到與這位使用者對應的家目錄中的,所以應該不需要修改 家目錄的 SELinux 安全上下文。但是,前文還講到了 Linux 域的概念。Linux 域確保服務程式 不能執行違規的操作,只能本本分分地為使用者提供服務。httpd 服務中突然開啟的這項個人用 戶主頁功能到底有沒有被 SELinux 域預設允許呢?

接下來使用 getsebool 命令查詢並過濾出所有與 HTTP 協議相關的安全策略。其中,off 為 禁止狀態,on 為允許狀態。

[[email protected] jingpan]# getsebool -a | grep http httpd_anon_write --> off httpd_builtin_scripting --> on httpd_can_check_spam --> off httpd_can_connect_ftp --> off httpd_can_connect_ldap --> off httpd_can_connect_mythtv --> off httpd_can_connect_zabbix --> off httpd_can_network_connect --> off httpd_can_network_connect_cobbler --> off httpd_can_network_connect_db --> off httpd_can_network_memcache --> off httpd_can_network_relay --> off httpd_can_sendmail --> off httpd_dbus_avahi --> off httpd_dbus_sssd --> off httpd_dontaudit_search_dirs --> off httpd_enable_cgi --> on httpd_enable_ftp_server --> offhttpd_enable_homedirs --> off httpd_execmem --> off httpd_graceful_shutdown --> on httpd_manage_ipa --> off httpd_mod_auth_ntlm_winbind --> off httpd_mod_auth_pam --> off httpd_read_user_content --> off httpd_run_ipa --> off httpd_run_preupgrade --> off httpd_run_stickshift --> off httpd_serve_cobbler_files --> off httpd_setrlimit --> off httpd_ssi_exec --> off httpd_sys_script_anon_write --> off httpd_tmp_exec --> off httpd_tty_comm --> off httpd_unified --> off httpd_use_cifs --> off httpd_use_fusefs --> off httpd_use_gpg --> off httpd_use_nfs --> off httpd_use_openstack --> off httpd_use_sasl --> off httpd_verify_dns --> off named_tcp_bind_http_port --> off prosody_bind_http_port --> off

面對如此多的 SELinux 域安全策略規則,實在沒有必要逐個理解它們,我們只要能通過 名字大致猜測出相關的策略用途就足夠了。比如,想要開啟 httpd 服務的個人使用者主頁功能, 那麼用到的 SELinux 域安全策略應該是 httpd_enable_homedirs 吧?大致確定後就可以用 setsebool 命令來修改 SELinux 策略中各條規則的布林值了。大家一定要記得在 setsebool 命令 後面加上-P 引數,讓修改後的 SELinux 策略規則永久生效且立即生效。隨後重新整理網頁,其效 果如圖 10-10 所示。

[[email protected] ~]# setsebool -P httpd_enable_homedirs=on

圖 10-10 正常看到個人使用者主頁面中的內容

有時,網站的擁有者並不希望直接將網頁內容顯示出來,只想讓通過身份驗證的使用者訪 客看到裡面的內容,這時就可以在網站中新增口令功能了。

第1步:先使用htpasswd命令生成密碼資料庫。-c 引數表示第一次生成;後面再分 別新增密碼資料庫的存放檔案,以及驗證要用到的使用者名稱稱(該使用者不必是系統中已有的 本地賬戶)。

[[email protected] ~]# htpasswd -c /etc/httpd/passwd linuxprobe
New password:
Re-type new password:
Adding password for user linuxprobe

第2步:編輯個人使用者主頁功能的配置檔案。把第 31~35 行的引數資訊修改成下列內 容,其中井號(#)開頭的內容為劉遄老師新增的註釋資訊,可將其忽略。隨後儲存並退出配 置檔案,重啟 httpd 服務程式即可生效。

[[email protected] ~]# vim /etc/httpd/conf.d/userdir.conf
27 #
28 # Control access to UserDir directories. The following is an example
29 # for a site where these directories are restricted to read-only.
30 #
31 <Directory "/home/*/public_html">
32 AllowOverride all
#剛剛生成出來的密碼驗證檔案儲存路徑
33 authuserfile "/etc/httpd/passwd"
#當用戶嘗試訪問個人使用者網站時的提示資訊
34 authname "My privately website"
35 authtype basic
#使用者進行賬戶密碼登入時需要驗證的使用者名稱稱
36 require user linuxprobe
37 </Directory>
[[email protected] ~]# systemctl restart httpd

此後,當用戶再想訪問某個使用者的個人網站時,就必須要輸入賬戶和密碼才能正常訪問 了。另外,驗證時使用的賬戶和密碼是用 htpasswd 命令生成的專門用於網站登入的口令密碼, 而不是系統中的使用者密碼,請不要搞錯了。登入介面如圖 10-11 所示。

圖 10-11 網站提示需要輸入賬戶和密碼才能訪問

10.5 虛擬主機功能

如果每臺執行 Linux 系統的伺服器上只能執行一個網站,那麼人氣低、流量小的草 根站長就要被迫承擔著高昂的伺服器租賃費用了,這顯然也會造成硬體資源的浪費。在 虛擬專用伺服器(Virtual Private Server,VPS)與雲端計算技術誕生以前,IDC 服務供應商 為了能夠更充分地利用伺服器資源,同時也為了降低購買門檻,於是紛紛啟用了虛擬主 機功能。 利用虛擬主機功能,可以把一臺處於執行狀態的物理伺服器分割成多個“虛擬的服 務器”。但是,該技術無法實現目前雲主機技術的硬體資源隔離,讓這些虛擬的伺服器共 同使用物理伺服器的硬體資源,供應商只能限制硬碟的使用空間大小。出於各種考慮的 因素(主要是價格低廉),目前依然有很多企業或個人站長在使用虛擬主機的形式來部署 網站。 Apache 的虛擬主機功能是伺服器基於使用者請求的不同 IP 地址、主機域名或埠號,實 現提供多個網站同時為外部提供訪問服務的技術,如圖 10-12 所示,使用者請求的資源不同,最終獲取到的網頁內容也各不相同。如果大家之前沒有做過網站,可能不太理解其中的原理, 等一會兒搭建出實驗環境並看到實驗效果之後,您一定就會明白了。

 10.5.1 基於 IP 地址

如果一臺伺服器有多個 IP 地址,而且每個 IP 地址與伺服器上部署的每個網站一一對應, 這樣當用戶請求訪問不同的 IP 地址時,會訪問到不同網站的頁面資源。而且,每個網站都有 一個獨立的 IP 地址,對搜尋引擎優化也大有裨益。因此以這種方式提供虛擬網站主機功能不 僅最常見,也受到了網站站長的歡迎(尤其是草根站長)。 劉遄老師在第 4 章和第 9 章分別講解了用於配置網路的兩種方法,大家在實驗中和工作 中可隨意選擇。就當前的實驗來講,需要配置的 IP 地址如圖 10-13 所示。在配置完畢並重啟 網絡卡服務之後,記得檢查網路的連通性,確保三個 IP 地址均可正常訪問,如圖 10-14 所示(這 很重要,一定要測試好,然後再進行下一步!)。

圖 10-13 使用 nmtui 命令配置網路引數

第1步:分別在/home/wwwroot 中建立用於儲存不同網站資料的 3 個目錄,並向其中分 別寫入網站的首頁檔案。每個首頁檔案中應有明確區分不同網站內容的資訊,方便我們稍後 能更直觀地檢查效果。

[[email protected] ~]# mkdir -p /home/wwwroot/3
[[email protected] ~]# mkdir -p /home/wwwroot/5
[[email protected] ~]# mkdir -p /home/wwwroot/6
[[email protected] ~]# echo "IP:192.168.1.3" > /home/wwwroot/3/index.html
[[email protected] ~]# echo "IP:192.168.1.5" > /home/wwwroot/5/index.html
[[email protected] ~]# echo "IP:192.168.1.6" > /home/wwwroot/6/index.html
[[email protected] ~]# 

第2步:在 httpd 服務的配置檔案中大約 113 行處開始,分別追加寫入三個基於 IP 地址的虛 擬主機網站引數,然後儲存並退出。記得需要重啟 httpd 服務,這些配置才生效。

# <VirtualHost 192.168.1.3> DocumentRoot /home/wwwroot/3 ServerName www.jingpan.site <Directory /home/wwwroot/3 > AllowOverride None Require all granted </Directory> </VirtualHost>

<VirtualHost 192.168.1.5> DocumentRoot /home/wwwroot/5 ServerName www.jingpan.site <Directory /home/wwwroot/5 > AllowOverride None Require all granted </Directory> </VirtualHost>

<VirtualHost 192.168.1.6> DocumentRoot /home/wwwroot/6 ServerName www.jingpan.site <Directory /home/wwwroot/6 > AllowOverride None Require all granted </Directory> </VirtualHost> # # DocumentRoot: The directory out of which you will serve your # documents. By default, all requests are taken from this directory, but "/etc/httpd/conf/httpd.conf" 379L, 12312C written [[email protected] ~]# httpd -t AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using ::1. Set the 'ServerName' directive globally to suppress this message Syntax OK [[email protected] ~]# systemctl restart httpd

 圖 10-15 基於不同的 IP 地址訪問虛擬主機網站

10.5.2 基於主機域名

當伺服器無法為每個網站都分配一個獨立 IP 地址的時候,可以嘗試讓 Apache 自動識別 使用者請求的域名,從而根據不同的域名請求來傳輸不同的內容。在這種情況下的配置更加簡 單,只需要保證位於生產環境中的伺服器上有一個可用的 IP 地址(這裡以 192.168.10.10 為 例)就可以了。由於當前還沒有介紹如何配置 DNS 解析服務,因此需要手工定義 IP 地址與 域名之間的對應關係。/etc/hosts 是 Linux 系統中用於強制把某個主機域名解析到指定 IP 地址 的配置檔案。簡單來說,只要這個檔案配置正確,即使網絡卡引數中沒有 DNS 資訊也依然能夠 將域名解析為某個 IP 地址。

第1 步:手工定義 IP 地址與域名之間對應關係的配置檔案,儲存並退出後會立即生效。 可以通過分別 ping 這些域名來驗證域名是否已經成功解析為 IP 地址。

[[email protected] ~]# vi /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.3 www.jingpan.site bbs.jingpan.site tech.jingpan.site

"/etc/hosts" 3L, 222C written
[[email protected] ~]# ping -c 4 www.jingpan.site
PING www.jingpan.site (192.168.1.3) 56(84) bytes of data.
64 bytes from www.jingpan.site (192.168.1.3): icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from www.jingpan.site (192.168.1.3): icmp_seq=2 ttl=64 time=0.021 ms
64 bytes from www.jingpan.site (192.168.1.3): icmp_seq=3 ttl=64 time=0.017 ms
64 bytes from www.jingpan.site (192.168.1.3): icmp_seq=4 ttl=64 time=0.031 ms

--- www.jingpan.site ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.017/0.026/0.037/0.009 ms

第2步:分別在/home/wwwroot 中建立用於儲存不同網站資料的三個目錄,並向其中分 別寫入網站的首頁檔案。每個首頁檔案中應有明確區分不同網站內容的資訊,方便我們稍後 能更直觀地檢查效果。

[[email protected] ~]# mkdir -p /home/wwwroot/www
[[email protected] ~]# mkdir -p /home/wwwroot/bbs
[[email protected] ~]# mkdir -p /home/wwwroot/tech
[[email protected] ~]# echo "WWW.jingpan.stie" > /home/wwwroot/www/index.html
[[email protected] ~]# echo "bbs.jingpan.stie" > /home/wwwroot/bbs/index.html
[[email protected] ~]# echo "tech.jingpan.stie" > /home/wwwroot/tech/index.html

第3步:在 httpd 服務的配置檔案中大約 113 行處開始,分別追加寫入三個基於主機名的 虛擬主機網站引數,然後儲存並退出。記得需要重啟 httpd 服務,這些配置才生效。

<VirtualHost 192.168.1.3>
DocumentRoot /home/wwwroot/www
ServerName www.jingpan.site
<Directory /home/wwwroot/www >
AllowOverride None
Require all granted
</Directory>
</VirtualHost>

<VirtualHost 192.168.1.3>
DocumentRoot /home/wwwroot/bbs
ServerName bbs.jingpan.site
<Directory /home/wwwroot/bbs >
AllowOverride None
Require all granted
</Directory>
</VirtualHost>

<VirtualHost 192.168.1.3>
DocumentRoot /home/wwwroot/tech
ServerName tech.jingpan.site
<Directory /home/wwwroot/tech >
AllowOverride None
Require all granted
</Directory>
</VirtualHost>

圖 10-16 基於主機域名訪問虛擬主機網站

10.5.3 基於埠號

基於埠號的虛擬主機功能可以讓使用者通過指定的埠號來訪問伺服器上的網站資源。 在使用 Apache 配置虛擬網站主機功能時,基於埠號的配置方式是最複雜的。因此我們不僅 要考慮 httpd 服務程式的配置因素,還需要考慮到 SELinux 服務對新開設埠的監控。一般來 說,使用 80、443、8080 等埠號來提供網站訪問服務是比較合理的,如果使用其他埠號 則會受到 SELinux 服務的限制。 在接下來的實驗中,我們不但要考慮到目錄上應用的 SELinux 安全上下文的限制,還需 要考慮 SELinux 域對 httpd 服務程式的管控。

第1 步:分別在/home/wwwroot 中建立用於儲存不同網站資料的兩個目錄,並向其中分 別寫入網站的首頁檔案。每個首頁檔案中應有明確區分不同網站內容的資訊,方便我們稍後 能更直觀地檢查效果。

[[email protected] ~]# mkdir -p /home/wwwroot/6111
[[email protected] ~]# mkdir -p /home/wwwroot/6222
[[email protected] ~]# echo "port:6111" > /home/wwwroot/6111/index.html
[[email protected] ~]# echo "port:6222" > /home/wwwroot/6222/index.html

第2步:在 httpd 服務配置檔案的第 43 行和第 44 行分別新增用於監聽 6111 和 6222 埠的引數。

[[email protected] ~]# vim /etc/httpd/conf/httpd.conf
………………省略部分輸出資訊………………
33 #
34 # Listen: Allows you to bind Apache to specific IP addresses and/or
35 # ports, instead of the default. See also the <VirtualHost>
36 # directive.
37 #
38 # Change this to Listen on specific IP addresses as shown below to
39 # prevent Apache from glomming onto all bound IP addresses.
40 #
41 #Listen 12.34.56.78:80
42 Listen 80
43 Listen 6111
44 Listen 6222
………………省略部分輸出資訊………………

第3步:在 httpd 服務的配置檔案中大約 113 行處開始,分別追加寫入兩個基於埠號的 虛擬主機網站引數,然後儲存並退出。記得需要重啟 httpd 服務,這些配置才生效。 [[email protected] ~]# systemctl restart httpd Job for httpd.service failed because the control process exited with error code. See "systemctl status httpd.service" and "journalctl -xe" for details. [[email protected] ~]# systemctl status httpd.service ● httpd.service - The Apache HTTP Server    Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)    Active: failed (Result: exit-code) since 二 2018-10-16 13:36:54 CST; 2s ago      Docs: man:httpd(8)            man:apachectl(8)   Process: 4201 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=1/FAILURE)   Process: 2090 ExecReload=/usr/sbin/httpd $OPTIONS -k graceful (code=exited, status=0/SUCCESS)   Process: 4199 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)  Main PID: 4199 (code=exited, status=1/FAILURE)

10月 16 13:36:54 localhost httpd[4199]: (13)Permission denied: AH00072: make_sock: could not bind to address [::]:6111 10月 16 13:36:54 localhost httpd[4199]: (13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:6111 10月 16 13:36:54 localhost httpd[4199]: no listening sockets available, shutting down 10月 16 13:36:54 localhost httpd[4199]: AH00015: Unable to open logs 10月 16 13:36:54 localhost systemd[1]: httpd.service: main process exited, code=exited, status=1/FAILURE 10月 16 13:36:54 localhost kill[4201]: kill: cannot find process "" 10月 16 13:36:54 localhost systemd[1]: httpd.service: control process exited, code=exited status=1 10月 16 13:36:54 localhost systemd[1]: Failed to start The Apache HTTP Server. 10月 16 13:36:54 localhost systemd[1]: Unit httpd.service entered failed state. 10月 16 13:36:54 localhost systemd[1]: httpd.service failed. Hint: Some lines were ellipsized, use -l to show in full.

[[email protected] ~]# semanage port -l | grep http
http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989

第4步:SELinux 允許的與 HTTP 協議相關的埠號中預設沒有包含 6111 和 6222,因此需要將這兩個埠號手動新增進去。該操作會立即生效,而且在系統重啟過後依然有效。設定 好後再重啟 httpd 服務程式,然後就可以看到網頁內容了,結果如圖 10-17 所示。

[[email protected] ~]# semanage port -a -t http_port_t -p tcp 6111
[[email protected] ~]# semanage port -a -t http_port_t -p tcp 6222
[[email protected] ~]# semanage port -l| grep http
http_cache_port_t tcp 8080, 8118, 8123, 10001-10010
http_cache_port_t udp 3130
http_port_t tcp 6222, 6111, 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989
[[email protected] ~]# systemctl restart httpd

圖 10-17 基於埠號訪問虛擬主機網站

10.6 Apache 的訪問控制

Apache 可以基於源主機名、源 IP 地址或源主機上的瀏覽器特徵等資訊對網站上的資源 進行訪問控制。它通過 Allow 指令允許某個主機訪問伺服器上的網站資源,通過 Deny 指令實 現禁止訪問。在允許或禁止訪問網站資源時,還會用到 Order 指令,這個指令用來定義 Allow 或 Deny 指令起作用的順序,其匹配原則是按照順序進行匹配,若匹配成功則執行後面的預設 指令。比如“Order Allow, Deny”表示先將源主機與允許規則進行匹配,若匹配成功則允許訪 問請求,反之則拒絕訪問請求。

第1 步:先在伺服器上的網站資料目錄中新建一個子目錄,並在這個子目錄中建立一個 包含 Successful 單詞的首頁檔案。

[[email protected] ~]# mkdir /var/www/html/server
[[email protected] ~]# echo "Successful" > /var/www/html/server/index.html

第2步:開啟 httpd 服務的配置檔案,在第 129 行後面新增下述規則來限制源主機的訪 問。這段規則的含義是允許使用 Firefox 瀏覽器的主機訪問伺服器上的首頁檔案,除此之外的 所有請求都將被拒絕。使用 Firefox 瀏覽器的訪問效果如圖 10-18 所示。

<Directory "/var/www/html/server">
SetEnvIf User-Agent "Firefox" ff=1
Order allow,deny
Allow from env=ff
</Directory>

圖 10-18 火狐瀏覽器成功訪問

除了匹配源主機的瀏覽器特徵之外,還可以通過匹配源主機的 IP 地址進行訪問控制。例 如,我們只允許 IP 地址為 192.168.1..64 的主機訪問網站資源,那麼就可以在 httpd 服務配置 檔案的第 129 行後面新增下述規則。這樣在重啟 httpd 服務程式後再用本機(即伺服器,其 IP 地址為 192.168.1.3)來訪問網站的首頁面時就會提示訪問被拒絕了,如圖 10-19 所示。

圖 10-19 因 IP 地址符合要求訪問成功。