Apache (2.0) 網頁伺服器

author:Yung-Yu Chen (yungyuc) http://blog.seety.org/everydaywork/ <yyc@seety.org>
copyright:© 2006, all rights reserved

目錄

1   全球資訊網

全球資訊網 (World Wide Web,WWW) 可說是目前網際網路上最重要的應用,像 http://www.google.com/、http://www.yahoo.com/ 等,都是我們常瀏覽的 WWW 網站。基本上當我們談到「網站」這個詞的時候,多半指的都是 WWW 網站 (web site)。

WWW 的特性是站站相連,所以能建構起相當龐大的網際資源。網站們透過所謂的超連結 (hyperlink) 彼此關聯在一起;每一個站點 (site) 都會超連結到許多其它的站點去,互相交織成一張綿密而複雜的大網。

Apache 是目前最受歡迎也最穩定而功能強大的網頁伺服軟體,本章將說明如何安裝與組態這套系統。不過,在進入主題之前,我們需要建立一些基本的概念。

1.1   HTML 與 HTTP

從技術的角度來解釋 WWW 的話,可以說它是一個以 HTTP 協定在網際網路提供以 HTML 檔案為主體的資訊系統。

HTTP (Hyper Text Transportation Protocol) 是一種無狀態 (stateless) 的 TCP 協定,可以用來傳送各種不同的文件。它最主要的用途是用來傳遞超文件 (hyper text)。而超文件呢,就是由「超文件標記語言」(Hyper Text Markup Language) 所描述的文件,可以與文字、聲音、影像等等多樣化的內容進行連結。

HTML 是一種標記語言,利用各種標籤 (tag) 來定義 (標記) 資訊內容。HTML 基本上會以純文件檔案的形式存在,其中有許多不同的標籤,把各種資訊分門別類地定義清楚。使用者可以用 WWW 瀏覽器 (browser) 來閱讀 HTML 文件;瀏覽器會把 HTML 文件與相關的檔案從伺服器上用 HTTP 傳回客戶端,然後以 HTML 文件內設計好的格式來顯示 (render) 給使用者。

HTML 經過長久的演進,目前最新的標準是 XHTML (eXtensible Hyper Text Markup Language)cite{bib:XHTML1.0},把 HTML 修改為與 XML (eXtensible Markup Language) 相容。不過,許多網站都還沒有直援 XHTML,而是使用 HTML 4 (4.01),請參考 W3C 所提供的規格以及相關書籍。

1.2   Apache 與 Apache2 簡介

Apache 是目前全世界使用得最多的網頁伺服器,你可以在 Apache Fundation 的網站 http://www.apache.org/ 找到相關的資訊。

原本 Apache 只是一個開放原始碼的網頁伺服器計畫,但隨著開放原始碼的蓬勃發展,它從只支援網頁伺服器軟體的組織,變成了支援了許多與全球資訊網應用相關的大計畫,並且改名為 Apache Fundation。目前除了 Apache 網頁伺服器之外,比較知名的如 Jakarta、Tomcat 等 Java Container,以及 Java 程式建立工具 Ant,都是 Apache Fundation 名下的開放原始碼計畫。

單純的網頁伺服器還是叫作 Apache,不過現在有兩個版本:1.3 和 2.0;另外還有一個正在開發中的 2.1 版。Apache2 (2.0) 不是 Apache (1.3) 的單純昇級版,事實上新版經過了完全的改寫,內部構造與舊版的 Apache (1.3) 已經不一樣了。

Apache 除了穩定與高效率之外,還有一個特點,就是它有許多外加的模組 (module);Apache 提供了良好的架構,允許其他人為其撰寫模組,擴充或強化它原本的功能。許多動態網頁技術是利用模組來提高執行的效率的,例如 PHP、Perl 與 Python 都有 Apache 模組,並且相較於舊式的 CGI (Common Gateway Interface),可以達到數十倍到數百倍以上的效能提昇。不過因為 Apache2 與 Apache (1.3) 的內部結構差異十分大,兩者的模組通常不能混用。

舊版 Apache (1.3) 的程式碼雖然還有在維護,但已經停止增加新功能了;Apache2 經過了幾年的陣痛期,現在已經相當地穩定,也支援了大部分常用的模組。基於以上的理由,以下將只針對 Apache2 進行說明footnote{Apache (1.3) 組態檔裡大部分的關鍵字和 Apache2 是一模一樣的,但 Debian 的開發人員對針對這兩組套件不同的特性作了一些調整,看起來的差別會比較大。}。

2   讓 Apache2 動起來

Apache2 支援許多新架構與功能,所以在 Debian 中包了幾個不同的套件,以提供經過不同版本的多行程模組 (Multi-Processing Module,MPM)。

如果我們用 apt-get install apache2 來安裝的話,預設是使用比較有效率的 apache2-mpm-worker 套件,它利用執行緒 (thread) 來提昇速度,也比較節省記憶體。相對於 worker,apache2-mpm-prefork 則比較穩定,但沒有使用執行緒,處理連線要求的模式比較類似 Apache 1.3。

如果伺服的環境要求比較高的效能,請用 worker 套件。本章考慮的是一般的情況,所以採用 prefork,在穩定性與相關模組的支援性上都比較好,可以用以下的 apt 指令來安裝:

apt-get install apache2 apache2-mpm-prefork

安裝完畢之後,如果你是在本機上進行安裝的話,打開你的瀏覽器,輸入:

http://localhost/

就會出現 Debian 預設的網頁內容。如果我們操作的是遠端主機,請把以上網址中的 localhost 代換成該主機的網路位址,你一樣會看到 Debian 預設的網頁內容。

你可以用

$ /etc/init.d/apache2 stop

來關閉伺服器,再用

$ /etc/init.d/apache2 start

來啟動伺服器。

3   Debian 的 Apache2 組態檔結構

Debian 把與 Apache2 相關的組態檔案都放在 /etc/apache2 之下1。這個目錄應該會有以下的內容:

[1]如果你也有安裝 Apache (1.3) 的話,它的組態檔則是放在 /etc/apache 之下。兩者分開,避免干擾。
$ ls
apache2.conf  httpd.conf       mods-enabled/  sites-available/
conf.d/       magic            ports.conf     sites-enabled/
envvars       mods-available/  README         ssl/

目前 Debian (Sarge) 的 Apache2 預設是用虛擬主機 (name based) 進行組態的;過去並不是這個樣子,但現在這種模式可以讓管理員更便利地組態伺服器。為了善用 Debian 的規畫,我們必須要先了解 /etc/apache2 裡各個檔案與目錄的用途:

另外還有幾個比較不重要的檔案:

無論是修改了哪一個組態檔的內容,要讓它生效,就必須重新啟動 Apache2:

$ /etc/init.d/apache2 restart

4   基本組態

以前我們會把 Apache 的設定寫到

/etc/init.d/apache/apache.conf

/etc/init.d/apache2/apache2.conf

裡面,但在了解了 Debian 為我們設計好的組態結構之後,你知道其實只需要修改 site-availible 裡的虛擬主機設定檔。

site-availible 裡面一定會有一個預設的虛擬主機 default,而在 site-enabled 裡面用 000-default 連過去,所以 default 會被第一個載入。如果我們要建立簡單的網站,可以把設定直接寫到 default 裡面;不過還有另一種更乾淨的作法:建立個別的虛擬主機檔進行設定,如果可能的話,最好都這樣作。

4.1   主機資訊

首先要設定的應該是主機本身的資訊,有以下的項目:

  • ServerAdmin:指定管理員的電子郵件地址。使用者在連線到伺服器的時候,如果發生問題,就會在伺服器產生的錯誤訊息中看到這個郵件地址。
  • ServerName:用來指定主機的名稱,通常要設為 FQDN。這項資訊也會用於 name-based 虛擬主機的設定,用來指定各虛擬主機。另外在某些情況下,譬如伺服器向使用者回覆錯誤訊息的時候,使用者會看到這裡設定的伺服器名稱。
  • ServerAlias:主機的別名;如果主機只有一個名稱的話,就完全不需要這項設定,但若會有超過一個名稱,則可以用它來指定。

4.2   文件位置與主要選項

以下是幾個重要的相關指令:

  • DocumentRoot:指定主機根目錄在檔案系統內的位置。舉 default 為例,它把 DocumentRoot 預設為 /var/www,也就是說所有針對該主機的存取動作,都會先到檔案系統內的該處來尋找檔案。除非另有設定,否則 /var/www 內會存放所有由主機所提供的檔案。

  • DirectoryIndex:它指定在「瀏覽目錄」時要找尋的檔案名稱。預設為 (在 apache2.conf 檔案裡):

    DirectoryIndex index.html index.cgi index.pl index.php index.xhtml
    

    也就是說,當使用者在瀏覽本主機的某目錄時,伺服器會依照 index.html, index.cgi, index.pl, index.php, index.xhtml 的順序來尋找這些檔案,找到的話就以其內容回應給使用者。

    • <Directory path>...</Directory>:這一組標籤可以用來指定一組目錄下的設定。仍舉 default 為例:
    <Directory />
            Options FollowSymLinks
            AllowOverride None
    </Directory>
    

    為檔案系統根目錄及以下的所有目錄指定兩項設定。

  • Alias:為檔案系統內容建立主機上的別名,譬如

    Alias /mydoc /var/local/lib/mydata
    

    會把 /var/local/lib/mydata 對應到網站上的 /mydoc 去;這特別會用來設定 DocumentRoot 以外的檔案路徑。

  • ScriptAlias:這個指令的作用和 Alias 很類似,不過會指定目標路徑的內容為 CGI 指令稿。

  • Options:設定許多伺服器的行為選項,可以放在主設定檔、<Directory> 區塊、虛擬主機 (<VirtualHost>) 區塊或 .htaccess 裡面。茲列出較常用也較為重要的選項:

    • FollowSymLinks:允許使用符號連結來移動到其它位置。
    • SymLinksIfOwnerMatch:作用和 FollowSymLinks 一樣,但只有在符號連結本身和目的位置的擁有者相同的時候才作用。
    • Includes:開啟 Server Side Include 的功能。
    • ExecCGI:允許執行 CGI 指令稿程式。
    • Indexes:如果接到的 http 要求位置是一個目錄,而該目錄內又沒有 DirectoryIndex 所指定的檔案,打開這個選項則會對客戶端回應一個自動產生的目錄索引。

    另外,All 則會開啟除了 MultiViews 之外的所有選項 (而 MultiViews 則是與 HTTP 1.1 content negotiation 有關的功能,在此略過不談)。

  • AllowOverride:這個指令只能用在 <Directory> 區塊裡,用以指定可以在 .htaccess 檔footnote{.htaccess 是 Apache 的 per-directory 設定檔;你可以在任何一個伺服器存取得到的目錄內建立一個 .htaccess 檔,在其中撰寫只會套用在該目錄之下的 Apache 指令。}內覆寫的組態項目。``AllowOverride`` 後接的選項通常有:

    • AuthConfig:與使用者認證有關的設定。
    • FileInfo:管理文件型態的設定。
    • Indexes:目錄索引方面的設定。
    • Limit:存取控制設定。
    • Options:伺服器選項設定。

    除了可以指定以上的群組之外,還有許多細節可以設定。詳細的說明請參考說明手冊。

在架設網頁伺服器時,另一個常作的檔案位置設定是使用者網頁。所謂的使用者網頁,就是使用者可以在自己的家目錄下放置屬於自己、自行管理的網頁空間。目前的 Apache2 把關於使用者網頁的設定移出了主要組態檔,而改放進 mod_userdir 的組態檔裡面。你可以看一下 mod-availible 下面 userdir.conf 的內容:

<IfModule mod_userdir.c>
  UserDir public_html
  UserDir disabled root

  <Directory /home/*/public_html>
    AllowOverride FileInfo AuthConfig Limit
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
  </Directory>
</IfModule>

這樣的預設設定會把使用者家目錄下的 public_html 指定為使用者網頁的根目錄,而其對應的 URL 則為 http://hostname/~username/。如果我們想修改相關的設定,可以把這些指令複製一份到虛擬主機設定檔內,然後再進行修改;直接修改 userdir.conf 當然也可以達到目的,但會影響到未來 Apache2 的昇級footnote{userdir.conf 檔案是 Apache2 相關套件的一部分,Debian apache2 的維護人員未來有可能改動其內容,所以直接修改它很可能會破壞這些組態檔的相容性。虛擬主機設定檔則完全是我們自訂的內容,不會造成問題。}。

4.3   存取控制

Order, Deny, Allow 這一組指令可以用來控制連線來源。再舉 default 為例:

Order deny,allow
Deny from all
Allow from 127.0.0.0/255.0.0.0 ::1/128

Deny from 指令是用來指定textbf{不可以}連線的網路來源位址;而 Allow from 則用來指定可以連線的網路來源位址。欲允許或禁止連線的位址要列在指令的後面,其間以空白分隔;來源位址可以使用 IP, IP/netmask, 網域名稱等等方式指定,並且在同一行指令裡可以混用不同的方式。``Order`` 會設定 DenyAllow 作用的順序;如果用 Order deny,allow,表示允許連線的設定會蓋過禁止連線的設定,即預設為可以連線;若用 Order allow,deny 則會讓禁止連線的設定蓋過允許連線的設定,即預設為不可以連線。

以上所舉出 default 內的設定會禁止除了來自 localhost 之外的所有連線 (Allow 指令的第一個參數是 IPv4 的 localhost;第二個參數是 IPv6 的 localhost)。

如果我們想要更進一步地限制使用者對伺服器的存取,可以使用 <Limit> 指令區塊。``<Limit>`` 可以針對個別的 HTTP 存取方法作限制,能夠限制的有:GET, POST, PUT, DELETE, CONNECT, OPTIONS, PATCH, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK 和 UNLOCK。一般並不常會用到這個指令,所以詳細的說明請參考 Apache 使用手冊。

4.4   使用者認證

Apache 具備 HTTP Auth 的能力,並且內建了 htpasswd 這個工具來幫助我們管理帳號密碼。

假設我們希望存取某組頁面的人需要用一組帳號密碼登入,那麼我們可以這樣設定:

AuthType Basic
AuthName "Restricted Files"
AuthUserFile /usr/local/apache/passwd/passwords
Require user mordor

AuthType Basic 指定使用 "Basic" 的認證模式;另外也可以設定為 "Digest",不過 "Basic" 是較為常用的設定。``AuthName`` 設定認證的「領域 (Realm)」,你可以把它當作是一個識別項,可以隨意設定。``AuthUserFile`` 指定儲存帳號與密碼的檔案。``Require`` 指令最為重要,它用來「要求」所必須通過的認證內容,在此例中是只允許被認證為 "mordor" 的使用者存取。

以上關於認證的設定可以放在 <Directory> 區塊及 .htaccess 裡面。

在組態檔裡設定完畢之後,接下來要建立密碼檔

$ htpasswd -c /usr/local/apache/passwd/password mordor
New password:
Re-type new password:
Adding password for user mordor

你可以看一下這個檔案的內容:

mordor:CA7nCNQe/rcE6

它的格式非常簡單,就是「帳號:加密過的密碼」。設定完畢之後,使用者就可以用這組帳號密碼登入存取我們所設定限制的頁面了。

Apache 的 Basic 認證也支援群組功能,請參考 AuthGroupFile 指令的說明文件。

4.5   其它常用設定

在此列出一些常用的設定指令及其作用,詳細的說明請見 Apache2 的手冊:

  • <Location>:指定一個網站上的「位置」,這個位置不必有對應的檔案系統目錄,譬如在 apache2.conf 有以下被註解掉的指令:

    <Location /server-status>
        SetHandler server-status
        Order deny,allow
        Deny from all
        Allow from .your_domain.com
    </Location>
    

    只要你所在的位置是 .your_domain.com,就可以存取網站的 /server-status 目錄,而顯示目前伺服器的狀態。

  • AddDefaultCharset:這是 Apache 1.3 時惡名昭彰的指令;會把所有伺服器送出的資料重新用 DefaultCharset 進行編碼。Apache2 的組態檔終於預設關了它,但如果你的伺服器送出的中文資料變成亂碼,問題又不在客戶端身上的話,記得檢查一下這個設定。

5   以 SSL 進行加密通訊

Debian 的 Apache2 套件改變了 Apache (1.3) 處理 SSL 設定的方式。舊的 Debian Apache (1.3) 套件裡並沒有包含 SSL,如果想要使用 SSL 加密功能,要另外安裝專用的套件footnote{apache-ssl};Apache2 則將之二合為一。

如果要在 Apache2 裡面使用 SSL,直接打開 mod_ssl 模組即可:

$ a2enmod ssl
$ /etc/init.d/apache2 force-reload

然後你可以用瀏覽器看一下你的 http://localhost/doc/,如果最下面出現了類似

... mod_ssl/2.0.53 OpenSSL/0.9.7e ...

的字樣,表示設定成功了。

不過,僅僅開啟 mod_ssl,只是讓伺服器具備以 SSL 溝通的能力而已,我們還需要指定讓伺服器處理 SSL 連線,以及建立與管理最重要的 SSL 私鑰 (private key) 和憑證 (certificate)。

在前面的部分有提到 ports.conf 這個設定檔,現在我們就要在裡面加上一行

Listen 443

然後再 /etc/init.d/apache2 restart,讓 Apache2 重新啟動之後會監聽標準的 HTTPS (HTTP over SSL) 443 號通訊埠。

SSL 私鑰與憑證的管理是一件複雜的工作,但卻又至為重要:SSL 的安全性完全建立在私鑰的安全上面。我們要用 OpenSSL 工具來處理這些資訊,並且作一個簡單的示範 (不過不會說明 SSL 與對稱式加密的原理,這超出了本書的範疇)。

5.1   建立 SSL 私鑰與 X.509 憑證

在產生給 Apache2 使用的私鑰與憑證之前,我們先建立 root CA (Certificate Authority)。產生 root CA 的私鑰 (2048 位元的 RSA 密鑰):

$ openssl genrsa -out /etc/ssl/private/myrootca.key 2048
$ chmod og-rwx /etc/ssl/private/myrootca.key

最好為 root CA 的私鑰設定一個存取密碼:

$ openssl rsa -in myrootca.key -out myrootca.passwd.key -des3

接著,為這個私鑰產生憑證申請書 (request):

$ openssl req -new -key /etc/ssl/private/myrootca.key -out /tmp/myrootca.req

執行了以上的指令後,OpenSSL 會問一些設定上的問題;能夠儘量照實回答是最好的,但因為無論答的適不適當,都不影響後續的設定 (只會影響這個 CA 的可靠程度),所以我們下一段再討論這些設定問題 (那時就會影響使用了)。最後我們用 root CA 所產生的私鑰來簽發 (sign) 憑證 (也就是說,自己簽發自己的憑證,self-sign):

$ openssl x509 -req -days 7305 -sha1 \
 -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
 -signkey /etc/ssl/private/myrootca.key \
 -in /tmp/myrootca.req -out /etc/ssl/certs/myrootca.crt

root CA 的憑證最好不要過期,所以給定 7305 天,也就是 20 年。

有了 root CA 之後,我們再來產生給 Apache2 伺服器作 SSL 加解密用的私鑰與憑證。一樣產生私鑰:

$ openssl genrsa -out /etc/ssl/private/myhost.key 2048
$ chmod og-rwx /etc/ssl/private/myhost.key

這回不要設定密碼了,免得啟動伺服器的時候還要被問一次密碼。接著,為這個私鑰產生憑證申請書:

$ openssl req -new -key /etc/ssl/private/myhost.key -out /tmp/myhost.req

在執行以上的指令時,OpenSSL 會問你一串問題:

  1. Country Name (2 letter code) [AU]: -- 這裡要輸入國別代碼,人在台灣的話請輸入 TW
  2. State or Province Name (full name) [Some-State]: -- 州/省的名稱,並非動作必要的欄位。
  3. Locality Name (eg, city) []: -- 你所在的位置,並非動作必要的欄位。
  4. Organization Name (eg, company) [Internet Widgits Pty Ltd]: -- 所屬組織,並非動作必要的欄位。
  5. Organizational Unit Name (eg, section) []: -- 在所屬組織內的單位名稱,並非動作必要的欄位。
  6. Common Name (eg, YOUR name) []: -- 這個欄位很重要,要填入這個憑證所用於主機的網域名稱,若不一致的話,將來使用者在瀏覽時永遠會有警告訊息跳出來,抱怨憑證內的網域名稱與所存取的網域名稱不符合。
  7. Email Address []: -- 電子郵件位址,並非動作必要的欄位。

正確填答了之後,就會產生憑證申請書;因為我們要用自己的 CA 來簽發憑證,所以上面所列出「並非動作必要的欄位」不去詳填也沒有關係。但如果你要向其它正式的 CA 要求憑證,則最好詳細填寫這些資料。接著,以 root CA 的名義簽發憑證:

$ openssl x509 -req -days 3650 -sha1 \
 -extfile /etc/ssl/openssl.cnf -extensions v3_req \
 -CA /etc/ssl/certs/myrootca.crt -CAkey /etc/ssl/private/myrootca.key \
 -CAserial /etc/ssl/myrootca.srl -CAcreateserial \
 -in /tmp/myhost.req -out /etc/ssl/certs/myhost.crt

最後產生的私鑰與憑證,分別會被放在 /etc/ssl 目錄下的 private/myhost.keycerts/myhost.crt 檔案內。

5.2   為網站加上 SSL 支援

私鑰和憑證作好了之後,就要在你的組態檔裡寫入適當的指令,讓伺服器知道你的 SSL 設定:

SSLEngine On
SSLCertificateFile /etc/ssl/certs/myhost.crt
SSLCertificateKeyFile /etc/ssl/private/myhost.key

以上的指令可以寫在 default 裡。或者,更常見的作法是另外建立一個專門用作 SSL 網站的虛擬主機設定檔,這是因為 SSL 限制一個 IP 只能有一個 certificate,所以我們不能用 name-based 虛擬主機來在同一個 IP 上設定多個 SSL 站台。

因為我們是用自己建 root CA 來簽發 Apache2 用的憑證,一般瀏覽器根本是不認得的,而會發出警告訊息給使用者。如果想避免這個問題,一是花錢改向正式的 CA 買憑證,二是讓使用者安裝我們自己 CA 的憑證。第二個方法很簡單,把 CA 憑證公開出去讓使用者自行安裝即可;如果是在有統一管理的環境下,也可以預先在使用者的電腦裡安裝憑證。

一旦我們的 CA 被使用者的電腦當作可信任的來源,則將來所有由此 CA 簽發的憑證,也會自動被信任。這就是我們要分兩段來產生 Apache2 SSL 私鑰與 X.509 憑證的理由:提高管理上的彈性。

5.3   OpenSSL 常用指令

OpenSSL 工具箱裡的指令既多而雜,不常使用很容易就忘記了。本小節的用意是作一個整理,把常用的 OpenSSL 指令列出來,方便查詢使用:

  • 產生有 pass phrase 的 1024 bits 3DES 私鑰

    $ openssl genrsa -des3 -out mykey.pem [-rand randfiles] 1024
    
  • 產生使用者的憑證申請書,效期為 365 天 (1 年)

    $ openssl req -new -days 365 -key mykey.pem -out myreq.pem \
     -extensions user_ext
    
  • 產生未加密的伺服器憑證申請書

    $ openssl req -extensions server_ext -nodes -keyout myserver.key \
     -out myserver.req 1024
    
  • 更改私鑰的 pass phrase

    $ openssl rsa -in key.pem.old -out key.pem
    
  • 把私鑰的內容印到標準輸出

    $ openssl rsa -noout -text -in key.pem
    
  • 核驗憑證申請書

    $ openssl req -noout -text -verify -in userreq.pem
    
  • 將 PEM 私鑰轉為 DER 格式

    $ openssl rsa -in userkey.pem -out userkey.der -outform DER
    
  • 核對憑證鏈

    $ openssl verify [-CApath directory] cert.pem
    
  • 顯示憑證的內容

    $ openssl x509 -noout -text -in cert.pem
    
  • 顯示憑證的 MD5 指紋

    $ openssl x509 -noout -fingerprint -in cert.pem
    
  • 顯示憑證的 SHA1 指紋

    $ openssl x509 -noout -sha1 -fingerprint -in cert.pem
    
  • 把 PEM 憑證轉換成 DER 格式

    $ openssl x509 -in cert.pem -out cert.der -outform DER
    

6   虛擬主機 (name-based)

Debian 的 Apache2 套件預設就使用 name-based 虛擬主機來管理,所以我們一定要多加了解這部分的組態。所謂的 name-based 虛擬主機,是指使用者如果透過不同的主機名稱 (即一個 URL 中 http://hostname/pathhostname 這個部分) 來存取網站,就會得到不同的回應,「好像是textbf{不同的主機}」。這是一種方便的設定模式,可以讓伺服器的管理更有彈性,也可以讓組態檔更穩定2;一旦我們要轉移網頁伺服器時,只需把虛擬主機這部分的設定改放到新伺服器即可,能夠避免很多設定混雜的問題 (當然前提是虛擬主機的設定檔要寫得夠好)。

[2]我的意思是,組態檔彼此之間更不容易混亂。

Apache 所支援的虛擬主機有兩種:name-based 與 address-based。一般我們講到虛擬主機都是指 name-based,它可以讓許多虛擬主機共仔在同一個 IP 位址上,而 address-based 則否。

6.1   最簡設定

Name-based 虛擬主機要在 <VirtualHost> 區塊裡面進行設定,以下的指令會建立一個最基本的虛擬主機:

<VirtualHost *>
  ServerAdmin webmaster@hostname
  ServerName hostname
  ServerAlias hostnamealternative

  DocumentRoot /var/www/somedir
  <Directory />
    Options FollowSymLinks
    AllowOverride None
  </Directory>
  <Directory /var/www/somedir/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
  </Directory>
</VirtualHost>

name-based 虛擬主機的 <VirtualHost> 區塊一定要寫成 <VirtualHost *>;或者在是伺服器不止監聽一個通訊埠的情況下,在 * 後面指定埠號,如 <VirtualHost *:443> (通常會用於啟動了 SSL 的伺服器)。如果把 * 改成 IP 位址,那就變成了 address-based 虛擬主機設定;要注意,address-based 與 name-based 虛擬主機設定是不能共存的,我們只能擇一使用3

[3]我們不能建立一個又使用 address-based 虛擬主機,又使用 name-based 虛擬主機的伺服器;雖然只有 address-based 虛擬主機才能處理多個 SSL 站台,但為了 name-based 虛擬主機,我們只好放棄這項能力。

name-based 虛擬主機以 <VirtualHost> 區塊內的 ServerName 來辨識各虛擬主機。``ServerAlias`` 可以用來指定這個虛擬主機的別名,如此一來用 ServerNameServerAlias 所指定的名稱進行存取時,就會連到這個虛擬主機來了。

6.2   從 default 修改

設定虛擬主機最快的方式就是從範例修改;我們有現成的範例:

$ cd /etc/apache2/sites-availible
$ cp defaults samplehost

你應該有注意到,預設的 default 內容雖然有用 <VirtualHost> 包起來,但卻缺乏 ServerName 名稱設定。這是故意的,目的是讓它成為真正的「預設」組態;我們在設定自己的虛擬主機時應該要加回去。

另外一個要注意的地方是複製出來的 samplehost 檔裡第一行的

NameVirtualHost *

也應該要拿掉。這是 default 用來開啟 name-based 虛擬主機的指令,在其它的虛擬主機設定檔裡不應該重複出現。

6.3   設定符號連結

一旦我們設定好了我們的虛擬主機組態檔,就要在 sites-enabled 裡建立一個符號連結。``sites-enabled`` 預設只有 default 的符號連結:

$ ls -al sites-enabled/
total 0
lrwxrwxrwx  1 root root 36 2005-04-14 15:38 000-default ->
  /etc/apache2/sites-available/default

我們依樣畫葫蘆另外建一個:

$ cd /etc/apache2/sites-enabled
$ ln -s /etc/apache2/sites-availible/samplehost 100-samplehost

如果我們的組態檔沒有設錯,重新啟動 Apache2 之後,``http://samplehost/`` 的根目錄就會是你所指定位置的內容,而非原本的 /var/www 了。

6.4   名稱設定

通常虛擬主機的 ServerName 都會使用設在 DNS 上的名稱,而且會是 FQDN4。不過有時候我們為了測試虛擬主機,也可以直接使用在 /etc/hosts 檔裡設定的名稱。

[4]Full Qualified Domain Name,即是以 hostname.domain.name 寫成的名稱,可以拆成主機 (前) 與網域 (後) 兩個部分。

如果 ServerName 不是 FQDN,Apache2 在啟動時可能會印出警告訊息,請注意這一點。

7   常用的動態網頁模組

3P -- PHP, Perl, Python 是目前最為流行的開放原始碼網頁程式工具,Debian 都有為相關的工具模組進行包裝。本節簡單列出在 Debian 下,這些語言工具與 Apache2 相關綁定 (binding) 模組的安裝指令:

關於這些程式工具的實際使用,請參考相關的說明文件。

8   紀錄與稽核

8.1   紀錄檔的預設值與調整

對於實際在進行服務的網頁伺服器,一定要時常檢查它的紀錄檔內容。一方面方便我們統計伺服器的使用率與效益,而更重要的是找出不正常的存取或惡意入侵行為。

Apache2 的紀錄檔存放在 /var/log/apache2 目錄內,access.log 紀錄了網頁的存取動作,而 error.log 則紀錄存取失敗或伺服器錯誤的訊息。Debian 會使用 logrotate 工具定時封存系統中所有的紀錄檔,所以如果你的 Debian 安裝有一段時間以上,可能會在 Apache2 的紀錄檔目錄裡看到以下的內容:

$ ls
access.log    access.log.2.gz  error.log    error.log.2.gz
access.log.1  access.log.3.gz  error.log.1  error.log.3.gz

*.log.1 是最新一次的封存;``logrotate`` 每封存一次紀錄檔,就會把它的檔尾數字加 1,而預設會用 gzip 壓縮編號 2 以上的封存檔。

如果我們回頭去看一下 default 虛擬主機組態檔的內容,會發現其中有兩行關於紀錄檔的設定:

ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined

它們指定了這個虛擬主機的紀錄檔所要存放的位置;正是我們在 /var/log/apache2 下看到的兩個檔案。``CustomLog`` 在紀錄檔名之後所接的參數是該檔案的格式,而這個格式可以使用 LogFormat 自訂;``combined`` 是預先設定在 apache2.conf 組態檔裡的一種格式,而預設的格式還有 common, refereragentfootnote{ErrorLog 就不能自訂格式。}。

另外你也應該要注意到 LogLevel 這個指令,它設定了錯誤紀錄檔 (ErrorLog) 所要紀錄訊息的層級 (並不影響存取紀錄檔)。預設的 LogLevelwarn,而以下列出所有可設定的紀錄層級;愈後面的愈詳細,而愈前面的愈嚴重:

  • emerg:嚴重到系統無法運作的事件訊息。
  • alert:必須立刻處理的問題。
  • crit:關鍵的例外狀況。
  • error:有出現錯誤的狀況。
  • warn:警告訊息。
  • notice:正常但值得注意的狀況。
  • info:言之有物的資訊。
  • debug:用來除錯的訊息。

8.2   紀錄分析工具

能夠分析 Apache2 紀錄檔的工具很多,我們在這裡先介紹一個簡單的稽核工具:logwatch,方便每天監看伺服器的狀況。

$ apt-get install logwatch

完裝好程式之後,``logwatch`` 就會用 cron 每天定時產生一次紀錄檔的報表。``logwatch`` 不是只會分析 Apache/Apache2 而已,事實上它是一個用 Perl 寫成的模組化紀錄檔分析軟體,一般安裝好之後,它會每天進行一次 crond, httpd, maild, sshd 等許多紀錄檔的分析,然後把報表用 email 寄給管理員。

logwatch 的使用非常簡單,採用預設值的話幾乎完全不需要再作額外的設定。對 Apache2 來說,它會統計前一天的資料總傳輸量,並且列出已知的惡意攻擊及該攻擊行動的來源、偵測本伺服器的主機,以及所有未分類 (Other) 的存取動作。每天看一次 logwatch 對昨天所作的分析整理,你會很容易了解伺服器的狀況。

對於有超過一台伺服器要管理的人,可以使用 .forward 檔來把各台主機屬於管理員的信件都集中到一個 email 位址,瀏覽起來會更方便。

另外,Debian 裡面還有 awstatswebalizer 這兩個專門用來分析 Apache2 紀錄檔的工具。它們不只會產生文字報表,還可以建立圖表,並且允許管理員從網頁上來存取這些資料。