分享

Apache 伺服器管理

 农夫子oice 2007-04-28

Apache 伺服器管理

作者:李忠憲 shane@mail.spps.

2004/08/02 修訂

HTTP 1.1 通訊協定

當歐洲高等物理實驗室開發出網頁伺服器時,當時是使用 HTTP 1.0 版通訊協定,市場上支援得最好的瀏覽器大概就是 Netscape Navigator及Communicator,Netscape 公司在產品成熟後緊接著推出 Gold 版開始收費販賣,在 Gold 版中他們提出了線上編輯網頁的概念(編好後要用 FTP 上傳就是了),為了實現這個概念必須要發展新的 HTTP 通訊協定,當然沒多久 Netscape 從市場消失,大家開始改用微軟公司的 IE 以及 FrontPage,微軟公司基於簡單易用的考量, 積極參與新版本 HTTP 通訊協定的制定,這就是後來我們看到的 HTTP 1.1

HTTP 1.1 版通訊協定的改版幅度相當大,例如:增加檔案 zip 壓縮功能,增加 MD5 編密傳送功能......等等,其中對微軟公司最重要的就是,他們提案的 PUT DELETE 指令被接受了,PUT 指令用來新增網頁、修改網頁內容或變更檔名,DELETE 指令則用來刪除網頁或目錄,透過這個機制就可以很容易用 HTTP 80 埠來直接更新網站內容,這就是微軟產品 FrontPage Server Extension 的目標,目前除了 FrontPage 支援 PUTDELETE 指令外,還有 W3C 開發的 Winie 也可以用來上傳網頁(支援 Linux 平台,Server 端則由 Apache mod_put 負責)。底下簡要的說明 HTTP 1.1 版各個指令的用途:

指令 用途
OPTIONS 查詢或設定 URI 旗號,透過這個機制伺服器得以和瀏覽器協商傳輸資料時要不要壓縮、要不要 Cache ......等等
GET 取得網頁資料。必須使用絕對網址來要求資料,如果使用相對路徑,則必須以 Host: 標頭標示目的網址,這跟 1.0 版有很大的不同
HEAD GET 很像,但只會取得網頁標頭,不包含網頁內文(除錯用)
POST 取得網頁資料前,先上傳前一個網頁的表單資料,POST GET 的差別在於上傳資料的方式不同,使用 GET 可以在網址後方添加資訊(user=xxps&test=on......),但資訊的量無法超過一行的限制,使用 POST 上傳沒有上限。POST 除了用來上傳表單資料(上傳檔案)外,還可以:
  1. Server 上的資料來源建立註解
  2. 提供資料給表單中的動態資料連結項目(DataField
  3. 新增資料到資料庫(通常是另一個網頁或純文字資料庫)

FrontPage 上可以製作這種進階表單,在此不作詳細說明

PUT PUT 指定的網頁不存在時,會自動新增網頁,否則就是要取代舊網頁或變更名稱
DELETE 刪除指定的網頁或空目錄
TRACE 用來做應用層的 loopback 追蹤,可以配合 OPTIONS 指定 Max-Forwards 來決定追蹤的深度,使用此指令將追蹤出所經過的 Proxy(除錯用)
CONNECT 是給 Proxy 伺服器用來建立 SSL 通道的,當瀏覽器透過 Proxy 使用 HTTPS 連上網頁時,需要在 Proxy 上建立 SSL 通道才能提供服務給 Client

了解 HTTP 回應狀態碼的涵義(RFC 2068),對於理解 Apache 伺服器的行為和運作機制有很大的幫助,同時當網頁出現狀況無法正常顯示時,瀏覽器也會秀出這些錯誤訊息,了解這些錯誤訊息您就可以判斷出問題的成因,因此在附錄 特地收錄了一般常見的各種狀態碼的表列,當作補充教材請學員細心閱讀。

新版 Apache 的特色

RedHat 8.0 版隨附的 Apache 伺服器是 2.0 版,相較於過去推出的 1.3 版有非常大幅度的改變,2.0 版的 Apache 不但支援多重處理器系統、支援 ipv6,也重新改寫了函式庫。新版 Apache 內的模組全部使用新的函式庫來編譯,使得所有模組都能支援 DSO 動態載入。(DSO 不算是新東西,過去一直不是 Apache 預設的做法,在前版 Apache 上想要使用 DSO 必須自己重新編譯 Apache)。除此之外,新版 Apache 也支援一種稱為過濾器(Filter)的全新模組,過去使用的舊模組則被稱為掌舵者(Handler)模組。

說到 filter 我想經常使用 Linux 指令的人一定不陌生,當一次使用多個 shell 指令時,我們會使用管道符號來串接指令,而在 Linux 上管道符號就被稱為 filter 符號,這意味著,這些模組可以像 shell 指令一樣串接在一起,例如:ls | grep a | less,透過多個程式接力運作最後可以得出比較複雜有彈性的結果。過去使用的 Handler 模組,在處理完程式網頁的內容後,會直接將處理結果推送回瀏覽器端;而 Filter 模組則在處理完後,將處理結果送回給 Apache core module,以便交給其它 Filter 模組進行後續處理。事實上這個新的轉變在 Microsoft IIS 上已經行之多年,它能帶來最大的好處,就是網頁伺服器將有能力去處理混用多種 script 語言所設計出來的複雜網頁,這在過去被認為用途不大,但隨著 Web Computing 的風行,這已經成為不得不然的趨勢事實上 Apache 這樣的轉變,將有助於吸納原來 IIS JAVA 伺服器的使用者,因為使用 ASP JSP 的網頁在 Apache 上剖析執行已經不再只是夢想。

除了這些重大的改變以外,2.0 版在組態設定上有一些改變,這個改變是好是壞就見仁見智了,筆者認為預設的組態對於中文世界的使用者特別是中小學來說是相當不友善的,必須要經過蠻多修改才能使用,與過去 1.3 版相比改變還真大!底下就來說明組態檔中新舊版本不同的地方:

conf.d

新版的 Apache 將各種模組會用到的組態檔集中擺放在 /etc/httpd/conf.d 資料中,例如:mod_perlmod_sslmod_php......等,因此在組態檔中有這一行:

Include  conf.d/*.conf

如果您的 Apache 是從舊版升級上來的,記得把這一行加到原來的組態檔中。

IP 與埠號繫結

舊版 Apache 是使用 BindAddress Port 來指定伺服器提供服務的位置,新版的 Apache 則是使用 Listen 來宣告要傾聽的埠號,使用 ServerName 指定埠號的方式來宣告是由哪個 DN 來提供該服務,好處是一台 Web 將可以同時服務多個 Port,甚至可以利用埠號的不同來設計虛擬站台(過去有所謂 IP basename base 虛擬站台,現在又多了 Port base,有關虛擬站台在後面章節說明),例如:

1.3 2.0
BindAddress 192.168. 1.2
Port 12000
ServerName wam.spps.
Listen 12000
ServerName wam.spps.:12000

Multi-Processing ModulesMPMs

MPMs 是一群特殊的模組,和其它模組不同它們是無法動態載入的(DSO), 它們必須在安裝 Apache 時就決定要用哪一個,目前 MPMs 有三種 ,分別是:preforkworker perchild。像過去 1.3 版那樣在 Apache 啟動時,即預先將要提供服務的 StartServers 一併 fork 好,這種做法就稱為 prefork,其它兩種作業模式 RedHat 8.0 尚未提供,必須等新的 rpm 出來後才能安裝使用。

三個模組分別採用不同的記憶體管理方式,其中 perchild 使用執行緒來提供服務,prefork 使用子程序來提供服務,而 worker 則兼用兩種方法,它們的差異在於:執行緒可共用記憶體,並使用記憶體與其它執行緒溝通;子程序則獨立使用記憶體,且利用檔案與其它子程序溝通。前者效能較高,後者比較安全穩定。

三個模組被設計用來應付不同的效能需求,小型實驗網站使用 perchild,它會同時啟動 5 Server,每個 Server 最多執行 10 個執行緒,因此可同時應付 50 條連線,假設有開啟 KeepAlive 功能,則最多可同時服務  5000 個要求,相當於 IIS 中的 1000 人以下存取量(在 IIS 中也可以進行效能調整,兩者相互對照比較容易理解 MPMs 機制),預設的 prefork 是提供給中量級網站使用,最多可同時接受 3000 條連線,服務 30000 個要求,重量級網站則使用 worker,最多可同時接受 22500 條連線,約可服務 20 萬個要求。

直接受此改變影響的包含:StartServersMinSpraeServersMaxSpareServersMaxClientsMaxRequestsPerChildNumServersStartThreadsMinSpareThreadsMaxSpareThreadsMaxThreadsPerChild....等 ,預設值如下:

##
## Server-Pool Size Regulation (MPM specific)
##

# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves
# NumServers: constant number of server processes
# StartThreads: initial number of worker threads in each server process
# ThreadsPerChild: constant number of worker threads in each server process
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# MaxThreadsPerChild: maximum number of worker threads in each server process
<IfModule prefork.c>
StartServers 8
MinSpareServers 5
MaxSpareServers 20
MaxClients 150
MaxRequestsPerChild 1000
</IfModule>

# worker MPM
<IfModule worker.c>
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
</IfModule>

# perchild MPM
<IfModule perchild.c>
NumServers 5
StartThreads 5
MinSpareThreads 5
MaxSpareThreads 10
MaxThreadsPerChild 20
MaxRequestsPerChild 0
</IfModule>

Dynamic Shared ObjectDSO

新版 Apache 已經全面採用 DSO,過去 DSO 是編譯 Apache 的選項之一,由於一直未被各版本 Linux 支援,因此如果想要使用必須自行下載原始檔編譯,Apache 模組全面改寫應該與全面採用 DSO 有很密切的關連。如前所述,由於 Apache 模組改以過濾器的方式運作,因此有許多模組被合併、分割、移除或改名,模組之間串接的順序也變得更為重要,因此 Apache 允許模組可以指定自己的順序,過去於組態檔中提供的 AddModule ClearModuleList 已經被取消不再使用,LoadModule 指令的順序也被忽略。安裝 mod_perlmod_sslmod_php...... RPM,也不用再去新增 LoadModule 設定,因為它們會自動被載入。另外,過去用來偵測哪些模組被載入的 HAVE_XXX 巨集命令,也不再使用了,因為現在的模組是動態載入的。

個人網頁目錄

中小學架設 Apache 主要是為了提供師生個人網頁空間,可惜新版 Apache 預設將此功能關閉,必須手動自行修改才能啟用:

UserDir  disable

改為

UserDir  public_html(或其它想使用的名稱)

預設語言與字元集

新版 Apache 裝好後預設會使用荷蘭語系和西歐字元集,這樣就造成網頁看到亂碼,過去舊版本使用哪種語系是由瀏覽器來決定,新版改為由 Apache 和瀏覽器來協商,因此就算設計網頁時有指定 Big-5 字元集,但瀏覽器卻接受 Apache 的指派,而不再理會網頁內容本身的設定,這對我們會造成很大的困擾,因此安裝完 Apache,一定要記得改底下這些選項:

DefaultLanguage tw
............................(中間省略)........................
LanguagePriority tw en da nl et fr de el it ja kr no pl pt pt-br ltz ca es sv
............................(中間省略)........................
AddDefaultCharset Big5

如果這些都改好後仍然出現亂碼,請檢查 IE 網際網路選項中的進階設定,是否有開啟 UTF-8 功能,目前發現某些情形下使用該功能會導致網頁亂碼,將它移除後就正常了。

常用組態設定

分類 組態名稱 預設值 使用說明
基本設定 ServerRoot /etc/httpd Apache 主程式所在目錄,這是不需要修改的。
Timeout 300 用來設定連線等待時間,包含:連線完成後,瀏覽器應於多少時間內送出 GET 指令、瀏覽器送出 POST PUT 指令後,應於多少時間內送出網頁或表單資料、伺服器回應網頁資料後,瀏覽器應於多少時間內回覆收到。這個設定是以秒作為單位。
KeepAlive off 是否允許同一連線送出多個要求,通常一個要求會起始一條連線,這樣雖會耗用較多的系統資源,但是回應比較迅速,當連線數太多系統資源不足時,可以考慮使用此功能。
MaxKeepAliveRequests 100 設定每條連線最多可接受多少要求,設得越高重啟連線的機率就越低,對改善 KeepAlive 的效能很有幫助。
KeepAliveTimeout 15 當一條連線服務完一個要求後,會等待一段時間以便接受下一個要求,如果逾時就關閉連線,這個設定值與前面介紹的 Timeout 意義完全不同,可千萬別搞混了。
Listen 80 和舊版的 Port 不同,它允許一個伺服器可以同時傾聽多個通訊埠,當埠號被設定少於 1024 的情形下,可以允許一般使用者將 Apache 安裝在個人家目錄下,成為個人專屬伺服器,像這種站台地下化的情形,系管人員應該要留意追查。
User apache 預設啟動帳號,事實上 Apache 啟動時還是以 root 身分進行準備工作,直到接受服務時才改用此帳號。為了安全考量,公開的 WEB 服務不應使用 root 身分來提供服務。
Group apache 預設啟動群組。
ServerAdmin 請務必修改為該伺服器的實際負責人信箱。
ServerName 用來提供服務的網址及埠號,當省略不設定時,預設會使用 hostname 80 port
HostnameLookups off 要不要對連線的客戶端進行 DNS 查詢驗證,這是為了避免駭客用假 IP 攻擊主機,但進行 DNS 查詢會降低伺服器效能,特別是當網站非常受歡迎的情況下,問題將會很嚴重
DefaultLanguage nl 預設語系
LanguagePriority 協商語系時的優先順序
AddDefaultCharset iso-8859 預設字元集
AddType 用來新增 MIME 格式,當 Apache 將檔案傳輸給 Client 時,必須告知 Client 該檔案屬於何種格式,這樣瀏覽器才能正確顯示或播放該檔案,常用的格式都已預先設好,因此除非要作特殊應用否則不需設定(有些站台故意隱藏正確的附加檔名,來限制某些檔案的下載)
AddHandler 定義 Apache Handler 模組所對應的附加檔名,當附加檔名吻合時,會交由該模組處理。目前支援的 Handler 模組,主要有 cgi-scriptperl)、imap-fileimagemap)、type-map(多語系)......等,這些設定都不需修改。(有些書教大家在 AddHandler cgi-script .cgi 的後面加上 .pl,這是多餘的,因為按照 perl 的慣例 .pl 檔案會被引入到 .cgi 中,本身並不會單獨執行,因此這樣設是多餘的)
AddOutputFilter 屬於新版 Apache 支援的 Filter 模組,應該使用 AddOutputFilter 而非 AddHandler,例如過去屬於 Handler 模組的 SSI,現在已經變成 Filter 模組,因此設定由
AddHandler server-parsed .shtml
改成
AddOutputFilter INCLUDES .shtml
AddPathInfo on 這個選項用來讓 Filter core 模組在傳送剖析過的網頁資料時,能使用 PATH_INFO 環境變數來傳遞 basedir,以免相對路徑無法對應正確
特異功能 Action 這個功能的設計相信是絕大多數網站經營者的福音,它允許為某種 MIME 類型或某個 Handler 設定前導執行程式,透過這個功能將可以為站台中的每個檔案進行權限檢查和過濾,以防堵不肖業者砍站的行徑,以前使用者從後門偷檔的情形也將受到遏止,設定方式如下:
Action media/type /cgi-script/location
Action handler-name /cgi-script/location
網頁目錄設定 DocumentRoot /var/www/html 根網站的主目錄
UserDir public_html 個人網頁的主目錄,建議改成 www 比較容易被學生接受
DirectoryIndex index.html 設定首頁的名稱,為了配合 FrontPage 教學,請修改成 index.html index.htm default.htm default.html
AccessFileName .htaccess .htaccess 是用來做目錄存取控制的,如果您修改了它的檔名,不要忘記一併修改底下的設定:
<Files ~ "^\.ht">
Order allow,deny
allow from all
</Files>
Alias 用來設定虛擬目錄,可以將某個目錄虛擬成根網站內的子目錄
ScriptAlias 功能與 Alias 相同,但為了讓程式能正常執行,該資料夾內的檔案權限應設為 755
Redirect 原本是用來幫助使用者連上網頁的新網址,但大多應用來對應位於不同主機的虛擬目錄
目錄權限設定 <Directory ......>
</Directory>
用來規範網頁目錄的權限,可以設定 OptionsAllowOverrideOrderAllowDeny 等各種權限,除此之外還能內含 <Files .....><Limit .....> 等標籤進行進一步設定。特別要注意的是,目錄本身可以使用 * 通配字元,例如:
<Directory /home/*/public_html>
是表示
/home 目錄下所有命名為 public_html 的子目錄,都要套用此權限設定
Options Indexes
Includes
FollowSymLinks
可以選用的功能如下:
Indexes
表示當找不到首頁時,要顯示目錄清單
Includes
啟用 SSIServer Side Include<!--#exec= --><!--#include= --> 功能
IncludesNoExec 啟用 SSI 中的 include 但忽略 exec
FollowSymLinks 允許用 Link 檔案連結網頁目錄外的實體檔案
SymLinksifOwnerMatch 當實體檔案與
Link 檔案屬於同一個人擁有時,才允許連結
ExecCGI 允許執行
CGI 程式
Multiviews 啟用多語言網頁功能(網頁應以語系作為附加檔名
, 例如 index.html.zh_tw
None 關閉所有功能
All 除了 Multiviews 以外的全部功能
AllowOverride None 是否允許 .htaccess 中的設定值取代 Options 的設定,可以選用的功能如下:
Options 啟用
.htaccess 中的 Options 設定
FileInfo 啟用
.htaccess 中的 Files 設定,請參考 <Files ....> 標籤
AuthConfig
啟用 .htaccess 中的 Auth 相關設定
Limit
啟用 .htaccess 中的 Limit 設定,請參考 <Limit ....> 標籤
None 不允許使用 .htaccess
All 允許忽略 Options 設定,改由 .htaccess 來進行存取控制
Order Allow,Deny 進行連線來源的網址或 IP 過濾時,是採用白名單(預設值)還是黑名單
Allow from all 誰可以存取這個資料夾,all 表示任何人都可以,這個欄位可以使用網址、網域名稱、IP、省略尾碼的 IP、網路號碼/遮罩 等等方式來作過濾
Deny from all 哪些人不允許存取這個資料夾,設定方式同上
<Files ......>
</Files>
這個標籤可以內嵌在 <Directory ......> 中,也可以獨立存在,兩者的作用範圍不同。它和 <Directory ......> 相同也可以使用 Order、AllowDeny 作存取控制,不同的地方是可以使用正規表達式來匹配檔案,而且可以用 ~ 作反向匹配,例如:
<Files ~ "^\.ht">
Order allow,deny
allow from all
</Files>
<Limit ......>
</Limit>
這個標籤必須內嵌在 <Directory ......> 中,主要是用來限制某些 HTTP 1.1 指令,例如:HEADPUTDELETETRACECONNECT 等,範例如下:
<Limit GET POST OPTIONS>
Order allow,deny
Allow from all
</Limit>
<LimitExcept GET POST OPTIONS>
Order deny,allow
Deny from all
</LimitExcept>
<Location ......>
</Location>
這個標籤允許針對 Client 身分進行權限管理,可以使用的關鍵字有:AuthTypeAuthNameAuthUserFileAuthGroupFilerequire......等等,以上設定的詳細用法在後面說明。
除此之外在
Location 內也能使用 OrderAllowDeny 來進行存取控制,並且允許使用部分網域名稱來進行比對,例如:
Allow  from  .spps.
目錄清單設定 IndexOptions FancyIndexing 當一個目錄找不到首頁時,可以選擇要不要由 Apache 幫忙製作目錄清單,這個選項用來控制該目錄清單的功能,預設值 FancyIndexing 會啟用目錄清單各欄位的排序功能,其它可設定的功能包括:IconHeightIconWidthIconsAreLinksVersionSortNameWidth......等等。
IconHeightIconWidth 用來指定圖示大小
IconsAreLinks 讓小圖示也變成超連結
VersionSort 當檔案名稱後面附有版本號碼時,根據版本號碼排序
NameWidth 指定檔名顯示幾個英文字
AddIconByEncoding AddIcon 用來設定檔案格式與小圖示的對應關係,ByEncoding 意思是要比對 MIME 中的 Encoding 欄位,MIME 格式如下:
 
檔名(Filename) 類型(Type) 編碼(Encoding)
*.z application/octet-stream x-compress
*.gz application/octet-stream x-gzip
AddIconByType 根據檔案的 MIME Type 來決定使用哪一個小圖示
AddIcon 根據檔案的副檔名來決定使用哪一個小圖示
DefaultIcon /icons/unknown.gif 當以檔案格式比對不到符合條件的小圖示時,預設使用這個圖示
ReadmeName README.html 產生出來的目錄清單,結尾會加上這個檔案的內容
HeaderName HEADER.html 同樣也是用來附加資訊,但是會加在目錄清單的上方
IndexIgnore 用來定義哪些檔案不要顯示在目錄清單上,包含: . 開頭、~ # 結尾...
虛擬站台 NameVirtualHost 用來設定 name base 虛擬站台,所謂 name base 是指該虛擬站台與預設站台使用同一個 IP 但不同網址,這時就可以透過網址來區分 Client 所要求的哪一個站台的資料,使用 name base 必須先在 DNS 做好 A 紀錄,NameVirtualHost 用法與 ServerName 完全相同
<VirtualHost ......>
</VirtualHost>
用來設定虛擬站台的各項參數,例如:
<VirtualHost
192.57.1.10:12000>
ServerAdmin w
am@test.
DocumentRoot /usr/libexec/wam
ServerName
wam.spps.
ErrorLog logs/
wam-error_log
CustomLog logs/
wam-access_log common
DirectoryIndex wam.cgi
 <Directory />
  
Options ExecCGI
  AllowOverride None
  
Order allow,deny
  
Allow from 192.57
  Deny from all
 
</Directory>
</VirtualHost>
快取伺服器設定 CacheNegotiateDocs Off Apache 預設會要求 Proxy 不要快取網頁,如果您的網頁沒有提供互動功能,那麼開啟這項功能將有助於改善網路環境
ProxyRequests On 通常這一行會被 remark 起來,這是用來開啟 Apache 內附的 Proxy Server
ProxyVia On 用來定義 Via 標頭是否要使用,Via 用來提供 Apache Proxy 資訊給 Client 端,On 提供 hostnameFull 提供 hostname versionOff 不作任何處理,Block 則會將 Via: 標頭去除
<Proxy *>
</Proxy>
定義 Proxy 功能的權限控制,可以使用 OrderAllowDeny 作細部設定
CacheRoot /etc/httpd/proxy 快取網頁擺放的資料夾
CacheSize 5 快取網頁所能使用的磁碟空間,預設是 5KB
CacheGcInterval 4 設定快取檢查的頻率,當檢查到快取空間已經超過 CacheSize 的設定時,則刪除比較舊的檔案
CacheMaxExpire 24 正常的快取網頁保留 24 小時
CacheLastModifiedFactor 0.1 當快取的網頁未設定過期期限時,則以 (今天 - 網頁最後更新時間)*0.1 作為過期期限
CacheDefaultExpire 1 當取得檔案的通訊協定無法支援過期設定時(FTP),該檔案視為 1 小時後過期
NoCache 設定不要快取的網站或網域

mod_proxy  模組

這個模組是用來實作 Proxy 功能,Apache 所提供的 Proxy 功能完全符合 HTTP 1.1 的標準,算是 Proxy Server 的原型,但實際上卻很少人去利用,畢竟那樣的 Proxy 實在是太陽春了,有關 Proxy 功能的各種設定已經在上表詳細說明,不在贅述。

mod_ssl  模組

這個模組是用來實作 SSL 安全伺服器,因此必須先在系統上安裝 open_ssl 套件,open_ssl open_ssh 一樣都是用來建立加密的傳輸層(TCP/IP 四層架構的第三層),也都是採用對稱式金鑰演算法來進行編密傳輸,但他們的應用範圍卻不同,open_ssh 支援 r servertelnetftp,而 open_ssl 則支援 mail web,有關 open_ssh 的詳細說明請閱讀 Linux 基礎班講義。在此要先提醒學員,SSL 2.0 已經被發現有安全漏洞,因此應該要升級為 3.0 才對(需自行從 RedHat 站台取得新的 RPM)。

open_ssl 安裝好後會自動在 /etc/httpd/conf 目錄下建立底下五個目錄:

資料夾 用途
ssl.crl 用來擺放被撤銷的憑證
ssl.crt 用來擺放伺服器的憑證
ssl.csr 用來擺放申請憑證用的申請表
ssl.key 用來擺放伺服器的金鑰
ssl.prm 用來擺放參觀者的個人憑證

open_ssl 會順便幫我們建立測試憑證和金鑰,這組憑證和私鑰僅供測試使用,如果要公開對外服務最好是使用合法憑證,底下就來說明取得合法憑證的方法:

  1. 首先刪除測試用憑證和金鑰,否則 open_ssl 會拒絕產生新的金鑰

    rm  /etc/httpd/conf/ssl.key/server.key
    rm  /etc/httpd/conf/ssl.crt/server.crt
     
  2. 重新產生金鑰,產生金鑰時會詢問 PEM 密碼,如果輸入密碼,將來在伺服器重新啟動時每次都會詢問,萬一是從停電狀態重開機,由於沒有人去輸入密碼,Apache 就會停止運作,因此建議直接按 Enter 不要設密碼,記得將私鑰的檔案權限設為 700

    cd  /etc/httpd/conf
    make  genkey
     
  3. 金鑰產生完畢後,才能產生憑證申請表,事實上金鑰中的公鑰會隨著該申請表傳送給 CA 認證機構,如果順序顛倒了,將來公鑰和私鑰會匹配不起來,這樣麻煩可大了

    make certreq
     
  4. 產生好的申請表必須傳送給 CA 組織來核發憑證,向 CA 組織申請核發憑證雖然不需要付費,但申請手續麻煩並且必須以機關名義提出申請(蓋學校關防),在這裡就不介紹了。其實 open_ssl 也允許核發憑證給自己,有點像 windows 2000 中的 CA Server 自己核發憑證給自己,但這個憑證將不會被瀏覽器信任,導致 Client HTTPS 連上網站時,會詢問參觀者要不要信任該網站,這會讓參觀者卻步。要自己發憑證給自己請輸入:

    make testcert
     
  5. windows 2000 CA Server 取得憑證,請先安裝 CA 伺服器


     
  6. CA 伺服器會被安裝在 IIS 預設網站的 certsrv 虛擬目錄內,請打開 IE 連上伺服器,點選要求憑證


     
  7. 如果點選使用者憑證要求,則可以線上提出個人憑證的申請,伺服器請點選進階要求


     
  8. 憑證申請表已經做好,因此點選第二個選項使用檔案來提出要求


     
  9. 點「瀏覽」,這時會詢問是否要執行 ActiveX,按確定,從表單上按「瀏覽」按鈕,出現開啟檔案對話框後,請找出在 Linux 上預先作好的 server.csr 檔案,最後按「讀取」即可


     
  10. 憑證要求被讀取出來後,就直接提交,等候伺服器核准



     
  11. 請在伺服器上開啟憑證管理員,核發剛剛提出的申請


     
  12. 底下介紹安裝授權憑證的方法,打開 IE 後連上 CA Server,並點選第三項


     
  13. 按下一步後可以看到已被核准的憑證,點選該憑證


     
  14. 下載憑證後,請將憑證改名為 server.crt 並拷貝到 Linux

mod_ssl 模組的相關組態設定可以在 /etc/httpd/conf.d 目錄中找到,檔名為 ssl.conf ,預設值如下:

LoadModule ssl_module modules/mod_ssl.so

Listen 443 //此埠號可以自行修改,但如果不是使用預設值,則在使用瀏覽器時需自行輸入埠號(例如: https://wam.spps.:12000),否則會找不到站台

AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl

SSLPassPhraseDialog builtin //當讀取憑證需要密碼時,讓 Apache 自動引用 Deamon 啟動時輸入的密碼
SSLSessionCache dbm:/var/cache/mod_ssl/scache //定義 SSL 連線時的 cache 路徑,尚未以私鑰解密的網頁會暫時放在這裡
SSLSessionCacheTimeout 300 //定義 SSL 連線逾時限制為 300
SSLMutex file:logs/ssl_mutex //定義 SSL 連線日誌檔的路徑
SSLRandomSeed startup builtin //定義產生一次性密碼時,亂數種子由系統自動提供
SSLRandomSeed connect builtin //定義產生一次性密碼時,亂數種子由系統自動提供

<VirtualHost _default_:443> //這裡設定為 _default_ 代表使用預設網站的 IP 和網址

DocumentRoot "/var/www/html" //由於主目錄與預設網站相同,如果不想再提供預設網站的 HTTP 想改用 HTTPS,請在 httpd.conf 中加入這一行
Redirect  http://wam.spps./  https://wam.spps./

ServerName wam.spps.:443
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
CustomLog logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
SSLEngine on //啟用 SSL 引擎
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL //設定加密機制與金鑰類型,這一行和上一行是同一行,因為太長自動折行了
SSLCertificateFile /etc/httpd/conf/ssl.crt/server.crt //定義伺服器憑證的路徑
SSLCertificateKeyFile /etc/httpd/conf/ssl.key/server.key //定義伺服器私鑰的路徑
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
  SSLOptions +StdEnvVars
</Files> //以檔名來判斷該網頁是否是程式,並讓它們可以引用環境變數
<Directory "/var/www/cgi-bin">
  SSLOptions +StdEnvVars
</Directory> // /var/www/cgi-bin 資料夾裡的程式可以引用環境變數
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0 //設定向下相容舊版 IE 瀏覽器,和上一行是同一行,因為太長自動折行了

</VirtualHost>

.htaccess mod_auth 系列模組)

mod_auth 模組用來實作 .htaccess 機制,當某個資料夾底下的內容需要進行權限認證,以避免資料被公眾讀取時,這個工作就可以交給 .htaccess 來負責,在該資料夾下建立 .htaccess 檔案,舉例如下:

AuthType Basic //驗證傳送方式,Basic 會使用 uuencode 加密來傳送密碼
AuthName "private"  //驗證領域,用來區分是否已通過認證,當不同資料夾使用同一個領域名稱時,已經通過該驗證的使用者不須再輸入一次帳號密碼,直接可以瀏覽網頁
AuthUserFile /home/shane/.htuser //擺放使用者 資訊的檔案
AuthGroupFile /home/shane/.htgroup //擺放 群組資訊的檔案
Require valid-user //表示所有 .htpasswd 的使用者都可以登入,也可以直接寫要給權限的帳號,中間以空白隔開,例如:Require  user george  mary,如果使用者眾多也可以使用群組,例如:Require  Group iwantcash
以上功能可不可以使用,視 <Directory ......> AllowOverride 是否有設定 AuthConfig 來決定
Satisfy any //當該資料夾被多個驗證領域所管理時,只要登入其中一個就行了,如果把 any 改為 all,則必須逐一登入成功才行
Options +ExecCGI
SetHandler cgi-script //設定 CGI 程式的執行權限
以上功能可不可以使用,視
<Directory ......> AllowOverride 是否有設定 Options 來決定

<Limit PUT DELETE TRACE>
 Order deny,allow
 
Allow from 192.57
 Deny from all
</Limit>
以上功能可不可以使用,視 <Directory ......> AllowOverride 是否有設定 Limit 來決定
<Files "^\.ht">
Order deny,allow
Deny from all
</Files>
以上功能可不可以使用,視 <Directory ......> AllowOverride 是否有設定 FileInfo 來決定

.htaccess 的使用者 及群組資訊檔是以純文字檔形式來存放,但為了避免使用者密碼外洩,因此在存放時會先將使用者密碼加密,這個工作由 htpasswd 來負責。能採用的加密格式如下:

加密格式 語法 用途
MD5加密 htpasswd -m windows 平台上使用時,此為預設值
呼叫 crypt 函式 htpasswd -d Linux 平台上使用時,此為預設值(通常不是 MD5 就是 DES
SHA加密 htpasswd -s 支援 Netscsape LDAP 伺服器
不加密 htpasswd -p 最不安全的方法

由於 Apache 預設會對 .ht 開頭的檔案加以保護,因此不要忘記把紀錄使用者和群組的資訊檔以 .ht 開頭來命名,以免這些檔案被參觀者盜取或瀏覽,建立使用者資訊檔的方法如下:

htpasswd -c /home/shane/.htuser george

檔案建立後請加入使用者,如下:

htpasswd /home/shane/.htuser mary

如果要刪除使用者,請以文書編輯器直接開啟使用者資訊檔,找到要刪除的使用者,直接將該行刪除後儲存即可。如果需要以群組來進行管理,請先建立群組資訊檔:

touch /home/shane/.htgroup

檔案內容如下:

iwantcash: george mary

由於 .htaccess 是在提供服務時,才載入記憶體,因此任何修改都是立即生效,不需要重新啟動 Apache

採用 Basic 驗證傳送方式,當使用者從瀏覽器輸入帳號密碼時是以 uuencode 編密後再傳送,這種加密方式只是把 8 bit 字元改用 7 bit 字元來表示,本身並沒有任何秘密可言,只要監聽網路封包很容易就可以竊取密碼。針對這個問題 Apache mod_auth_digest 模組提供 MD5 編密傳送來解決,想採用這種方法,請將 .htaccess 中的 AuthType 設定修改如下:

AuthType Digest

建立使用者資訊檔時請不要再使用 htpasswd,而是改用 htdigest

htdigest -c /home/shane/.htuser private george // private 是驗證領域名稱,請參考上面 .htaccess AuthName 設定

檔案建立後請加入使用者,如下:

htdigest /home/shane/.htuser private mary

如果要刪除使用者,請以文書編輯器直接開啟使用者資訊檔,找到要刪除的使用者,直接將該行刪除後儲存即可。至於群組設定檔的使用方式,則與上面介紹過的  mod_auth 模組相同。關於使用 DIGEST 驗證傳送還有一件事要注意,目前有支援這種驗證方式的瀏覽器,包括:Opera 4.0IE 5.0Mozilla 1.0.1Netscape 7 及以上的版本,請在登入前告知你的參觀者,以免參觀者無法登入時不知所措。

由於在純文字檔內搜尋使用者資訊速度非常慢,因此有必要改用資料庫索引的方式來儲存,然而關聯式資料庫系統雖然好用,但程式龐大且耗用大量系統資源,想要開發 WEB 介面程式來管理使用者,門檻也很高。在各種資料庫系統中,就以 DB DBM 最為簡單,mod_auth_dbm 模組便是採用 DB DBM 格式作為解決之道。DB 是柏克萊大學研發的一種純文字資料庫,它可以支援 btreehash ......等索引方式,由於程式輕薄短小幾乎不耗用系統資源,因此在 Unix Linux 上被廣為採用,例如先前介紹的 sendmail 有許多組態就採用 DB 格式。DBM DB 的改良品,當資料量較大時使用 DBM 效能比較高,也有許多系統採用 DBM 來儲存帳號資訊,例如成功大學開發的 Openwebmail等,由於著手改良 DB 的程式設計師眾多,因此所謂 DBM 也存在許多不同版本,常見的 DBM 包括:DB2NDBMGDBMSDBM mod_auth_dbm 模組僅支援 DBGDBMSDBM

底下的範例說明使用 mod_auth_dbm .htacces 的設定方式:

AuthType Basic
AuthName "private"
AuthDBType default //指定資料庫版本,預設為 default
AuthDBMUserFile /home/shane/.htuser
AuthDBMGroupFile /home/shane/.htgroup
Require valid-user

使用 htdbm 指令來建立使用者資料庫檔案,請輸入:

htdbm -c /home/shane/.htuser george //建立資料庫時會自動建立兩個檔案,其中 .htuser.pag 是資料檔,而 .htuser.dir 是索引檔

檔案建立後請加入使用者,如下:

htdbm /home/shane/.htuser mary

如果要刪除使用者,請輸入:

htdbm -x /home/shane/.htuser george

列出資料庫中的使用者,請輸入:

htdbm -l /home/shane/.htuser

檢查使用者是否已經建立,請輸入:

htdbm -v /home/shane/.htuser mary

建立群組資料庫方法與建立使用者資料庫相同,但是使用者名稱欄位變成群組名稱,而密碼欄位變成使用者列表,每個使用者以空格隔開,例如:

htdbm -cbp /home/shane/.htgroup iwantcash george,mary //參數中 b 代表批次模式,這樣就可以同時輸入使用者名稱(對群組檔來說是群組名稱)和密碼(對群組檔來說是使用者列表)兩個欄位,p 表示密碼欄位不加密

移除群組請輸入:

htdbm -x /home/shane/.htgroup iwantcash

使用 Perl 程式來管理使用者,範例如下:

use DB_File;
tie %database, ‘DB_File‘, "passwords.dat"  || die "Can‘t initialize database: $!\n";

$username = ‘rbowen‘;
$password = ‘mypassword‘;
@chars=(0..9,‘a‘..‘z‘);
$salt = $chars[int rand @chars] . $chars[int rand @chars];

$crypt = crypt($password, $salt);
$database{$username} = $crypt;

untie %database;

上面程式片段用來讓使用者從網頁直接變更密碼,由於牽涉程式設計,不在這個課程範圍內,往後如果有開程式設計班再講解!

mod_auth_mysql 模組

這個模組和其它 mod_auth 系列模組一樣是用來進行使用者認證,但它用 MySQL 伺服器作為儲存使用者資訊的後端資料庫,同時這個模組僅能在 httpd.conf 裡設定,請不要在 .htaccess 中使用它。由於本課程裡並不打算詳細介紹關聯式資料庫,因此不作詳細解說。

在設定 httpd.conf 之前,請以下列步驟進行資料庫部分的準備 工作:

mysql -u root -p mysql
mysql> GRANT ALL PRIVILEGES ON *.* TO web@localhost;
mysql> GRANT ALL PRIVILEGES ON *.* TO web@"%";
mysql> CREATE DATABASE http_users;
mysql> USE http_users;
mysql> CREATE TABLE user_info (
user_name CHAR(30) NOT NULL,
user_passwd CHAR(20) NOT NULL,
user_group CHAR(10),
PRIMARY KEY (user_name)
); // SQL 語法建立 users 資料表,資料表中包含三個欄位,user_name 為帳號欄位最多 30 個英數字元,user_passwd 為密碼欄位最多 20 個英數字元,user_group 為群組欄位最多 0 個英數字元,此資料表以帳號作為主索引,一個使用者僅允許加入一個群組
mysql> INSERT INTO user_info VALUES (‘testuser‘,PASSWORD(‘mypasswd‘),‘users‘);
mysql> INSERT INTO user_info VALUES (‘testadmin‘,PASSWORD(‘mypasswd‘),‘admins‘);
//以上兩行,會建立一般使用者測試帳號及管理員測試帳號

請修改 httpd.conf,加入以下設定值:

LoadModule mysql_auth_module modules/mod_auth_mysql.so
AddModule mod_auth_mysql.c

<Location /var/www/html/private/> //要使用 mysql 驗證保護的資料夾
 AuthName "MySQL authenticated zone"
 AuthType Basic

 AuthMySQLHost locahost //定義提供 MySQL 服務的主機,如果是別台電腦請輸入 IP
 AuthMySQLCryptedPasswords On //定義使用者 密碼要不要以 MySQL MD5 編密
 AuthMySQLUser web //定義 以何身分連線到 MySQL 伺服器,web MySQL 提供給 Apache 使用的預設帳號
 AuthMySQLDB http_users //定義 所使用的資料庫
 AuthMySQLUserTable user_info //定義 使用者資料表的名稱

 require valid-user //通過驗證的使用者才能瀏覽此資料夾
</Directory>

筆者撰寫了底下的 PHP 程式碼來示範如何進行使用者管理,該程式片段用來變更使用者密碼,其它應用不在這裡討論:

<?php

$username = "web";
$password = "";
$hostname = "localhost";
$databasename = "http_users";
$tablename = "user_info";

if (!($link = mysql_connect($hostname, $username, $password) ) ) {
  printError( sprintf("以使用者 %s 連結主機 %s 時,發生錯誤", $username, $hostname) );
  exit();
}
if (!mysql_select_db($databasename, $link) ) {
  printError( sprintf("開啟 %s 資料庫時,發生錯誤 %d %s", $databasename,
  mysql_errno($link), mysql_error($link) ) );
  exit();
}
$sql = "Update $tablename Set user_passwd = PASSWORD(‘$passwd‘) Where user_name = ‘$user‘";
if (!(result = mysql_query($sql, $link) ) {
  printError( sprintf("無法修改使用者 %s 的密碼,錯誤 %d %s", $user,
  mysql_errno($link), mysql_error($link) ) );
  exit();
}

?>

mod_auth_pgsql 模組

這個模組和其它 mod_auth 系列模組一樣是用來進行使用者認證,但它用 Postgre SQL 伺服器作為儲存使用者資訊的後端資料庫,同時這個模組僅能在 httpd.conf 裡設定,請不要在 .htaccess 中使用它。由於本課程裡並不打算詳細介紹關聯式資料庫,因此不作詳細解說。

在設定 httpd.conf 之前,請先登入 PostgreSQL 伺服器,進行下列準備動作:

CREATE DATABASE auth; // SQL 語法建立資料庫,資料庫名稱為 auth

\c auth //開啟資料庫,以下 SQL 指令將在此資料庫中執行

CREATE TABLE users (
user_name CHAR(30) NOT NULL,
user_passwd CHAR(32) NOT NULL,
PRIMARY KEY (user_name)
); // SQL 語法建立 users 資料表,資料表中包含兩個欄位,user_name 為帳號欄位最多 30 個英數字元,user_passwd 為密碼欄位最多 32 個英數字元,此資料表以帳號作為主索引,一個使用者僅允許出現在一筆紀錄中

CREATE TABLE groups (
user_name CHAR(30) NOT NULL,
user_group CHAR(20) NOT NULL,
PRIMARY KEY (user_name, user_group)
); // SQL 語法建立 groups 資料表,資料表中包含兩個欄位,user_name 為帳號欄位最多 30 個英數字元,user_group 為群組欄位最多 20 個英數字元,此資料表以帳號+群組作為主索引,因此允許同一個使用者加入多個群組

CREATE USER apache; //建立 Postgre 使用者帳號,帳號名稱乾脆就叫 apache,比較不會忘記
GRANT SELECT ON users TO apache; // users 資料表授權給 apache
GRANT SELECT ON groups TO apache; // groups 資料表也授權給 apache

INSERT INTO users VALUES (‘testuser‘, ‘179ad45c6ce2cb97cf1029e212046e81‘); //建立測試帳號 testuser,密碼為 MD5 編密,你可以使用 echo -n ‘mypasswd‘ | md5sum 指令將 mypasswd 編成 MD5 字串,這樣就能使用此 SQL 語法來建立帳號
INSERT INTO groups VALUES (‘testuser‘, ‘user‘); // testuser 加入 user 群組
INSERT INTO users VALUES (‘testadmin‘, ‘179ad45c6ce2cb97cf1029e212046e81‘);
INSERT INTO groups VALUES (‘testadmin‘, ‘admin‘);
INSERT INTO groups VALUES (‘testadmin‘, ‘user‘);

請修改 httpd.conf,加入以下設定值:

LoadModule auth_pgsql_module modules/mod_auth_pgsql.so

<Directory /var/www/html/private> //要使用 pqsql 驗證保護的資料夾
 AuthName "PostgreSQL group authenticated zone"
 AuthType Basic

 Auth_PG_database auth //定義所使用的資料庫名稱
 Auth_PG_pwd_table users //定義使用者資料表的名稱
 Auth_PG_uid_field user_name  //定義使用者欄位的名稱
 Auth_PG_pwd_field user_passwd //定義密碼欄位的名稱
 Auth_PG_grp_table groups //定義群組資料表的名稱
 Auth_PG_gid_field user_group //定義群組欄位的名稱
 Auth_PG_hash_type MD5 //定義編密方式為 MD5

 require group user //user 群組的使用者才能瀏覽此資料夾
</Directory>

mod_perl 模組

Apache 上使用 perl 這件事可以說歷史悠久,但使用傳統 CGI 方式來發展互動式網站有很大的缺點,包括:

  1. 由於一支 CGI 程式會同時被多人存取,而每次的存取都是獨立的行程,因此會耗用 N 倍的記憶體,N 就等於連線人數
  2. CGI 程式需讀取檔案時,由於多人同時存取,因此 I/O 衝突難以避免
  3. 每次連線都得反覆載入、剖析語法、編譯執行,浪費太多時間,尤其是程式很大時

以上這些缺點使得許多互動式站台不得不改用微軟公司的 IIS,因為 IIS 支援的 ASP 具有以下優點:

  1. ASP IIS 行程內執行,因此不會造成系統資源的浪費
  2. 使用同一行程來存取同一檔案,不會造成 I/O 衝突
  3. 執行過的 ASP 會常駐在記憶體,不用反覆載入、反覆剖析語法、反覆編譯

mod_perl 就是以讓 perl CGI 執行起來像 ASP 一樣為目標來開發,因此這個模組的標準化,讓人對 Apache 又有了信心,使用 perl 模組進行程式設計,即使對經常從事程式創作的人來說,門檻也是不低,在本課程裡並不適合詳細解說,底下僅舉 WAM 2.0 的部分設定值來說明如何進行設定:

PerlModule WAM::menu //用來向 Apache 註冊 menu.pm 程式檔,Apache 在有需要時會動態載入該程式
<Location /wam> //將該程式對應到 wam 虛擬目錄,當以 http://站台名稱/wam 連上站台時,就會觸動 Apache 載入該程式
AuthName "WAM"
AuthType Basic
PerlAuthenHandler WAM::AuthenPasswd //使用此 pm 來檢查使用者是否通過驗證,若否則跳出登入視窗要求登入
require valid-user
SetHandler perl-script //設定 mod_perl 程式的執行權限
PerlHandler WAM::menu //設定要執行的 pm 程式檔
PerlSendHeader On //允許 Perl 自行產生 HTTP 檔頭,而非由 Apache 核心模組產生檔頭,這樣做程式的彈性比較大
</Location>

PHP  模組

PHP 也是大家之所以要使用 Apache 的動機之一,底下設定在 Apache 安裝時就一併設定好了,不需修改,這個設定與舊版差蠻多的,主要是因為 PHP mod_include 一樣已經變成 Filter 了!

LoadModule php4_module modules/libphp4.so

<Files *.php>
SetOutputFilter PHP
SetInputFilter PHP
LimitRequestBody 524288
</Files>

DirectoryIndex index.php

虛擬站台設定

虛擬站台功能算是 Apache 遙遙領先 IIS 的地方,因為 IIS 僅提供 IP-base 的虛擬站台,而 Apache 多提供 Name-base Port-base 兩種虛擬站台,三者之間的不同如下:

Port-base 每個虛擬站台僅擁有獨立的埠號(不能重複),但共用同一個 IP 和網址。
Name-base 每個虛擬站台擁有獨立的網址和埠號(不能重複),但共用同一個 IP。只要在 DNS 上為該 IP 設定多筆 A 紀錄或增加 CNAME 紀錄就能支援。
IP-base 每個虛擬站台擁有獨立的 IP、網址和埠號(可以重複)。該 Linux 主機必須在一片網卡上設定多個不同 IP,並且完成 DNS 設定,才能實作此種虛擬站台。

Port-base 虛擬站台最容易實作,只要定義好 Apache 傾聽的埠號,接著以 <VirtualHost ...> 標籤來定義組態就可以了,範例如下:

Listen 12000
<VirtualHost _default_:12000> //default 意思就是與預設站台使用同一個 IP 和網址
ServerAdmin w
am@test.
DocumentRoot /usr/libexec/wam
ServerName
wam.spps.
ErrorLog logs/
wam-error_log
CustomLog logs/
wam-access_log common
DirectoryIndex wam.cgi
 <Directory />
  
Options ExecCGI
  AllowOverride None
  
Order allow,deny
  
Allow from 192.57
  Deny from all
 
</Directory>
</VirtualHost>

使用這個機制雖然很容易可以利用不同埠號,提供不同的網站資訊,但參觀者必須知道埠號才能連上該虛擬站台,使用上不太方便,另外還有一個小缺點,就是無法和預設站台一起提供 SSL 安全連線,這是因為一個 IP 僅被允許執行一份 SSL。預設站台是使用 443 埠來提供 HTTPS 安全連線,如果想讓 Port-base 使用 HTTPS 安全連線,就必須先將 443 埠關閉,同時移除 <VirtualHost _default_:443> 標籤的內容,如果在 httpd.conf 中找不到上述內容,可能是放在 /etc/httpd/conf.d/ssl.conf 中,接著修改上面的範例,加入粗體字部分的內容:

Listen 12000
<VirtualHost _default_:12000>
ServerAdmin w
am@test.
DocumentRoot /usr/libexec/wam
ServerName
wam.spps.
ErrorLog logs/
wam-error_log
CustomLog logs/
wam-access_log common
DirectoryIndex wam.cgi
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /etc/httpd/conf/ssl.crt/server.crt
SSLCertificateKeyFile /etc/httpd/conf/ssl.key/server.key
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
  SSLOptions +StdEnvVars
</Files>
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0

 <Directory />
  
Options ExecCGI
  AllowOverride None
  
Order allow,deny
  
Allow from 192.57
  Deny from all
 
</Directory>
</VirtualHost>

Name-base 虛擬站台是透過 Apache 解析 HTTP 通訊協定中的 Host: 標頭來判斷要存取的網站資訊,因此它能允許不同站台使用同一個 IP,有關 Host: 標頭將在下一小節介紹。設定 Name-base 站台除了埠號的設定與 Port-base 相同外,尚須以 NameVirtualHost 來宣告網址別名,該別名必須事先定義在 DNS 伺服器上,設定範例如下:

Listen 12000 //如果想和預設站台一樣以 80 埠提供服務,請刪除此行
NameVirtualHost *
<VirtualHost *
:12000> //如果想和預設站台一樣以 80 埠提供服務,請刪除 :12000
ServerName wam.spps.

ServerAdmin w
am@test.
DocumentRoot /usr/libexec/wam
............................................................ //設定與前例相同,因此省略
</VirtualHost>

由於 Name-base Port-base 一樣是使用預設的 IP,因此在 SSL 連線的應用場合裡會與預設的 443 埠發生衝突,請參考 Port-base 的說明和範例來設定虛擬站台的 HTTPS 安全連線。

IP-base 虛擬站台是三種虛擬站台中功能最齊全也最常使用的,但在設定上卻是最麻煩的。首先必須在同一片網卡上虛擬出多個 IP,方法如下:

# ifconfig eth0:0 192.168.1.10 //設定第一個假 IP
# ifconfig eth0:1 192.168.1.20 //設定第二個假 IP
# ifconfig //查看 IP 是否已經設好
eth0      Link encap:Ethernet HWaddr 00:50:8D:47:AA:FF
            inet addr:192.168.1.2 Bcast:192.168.1.255 Mask:255.255.255.0
            UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
            RX packets:18347596 errors:0 dropped:0 overruns:0 frame:0
            TX packets:17827505 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:100
            RX bytes:1387340808 (1323.0 Mb) TX bytes:3378133984 (3221.6 Mb)
            Interrupt:11 Base address:0x3000
eth0:0   Link encap:Ethernet HWaddr 00:50:8D:47:AA:FF
            inet addr:192.168.1.10 Bcast:192.168.1.255 Mask:255.255.255.0
            UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
            RX packets:18347596 errors:0 dropped:0 overruns:0 frame:0
            TX packets:17827505 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:100
            RX bytes:1387340808 (1323.0 Mb) TX bytes:3378133984 (3221.6 Mb)
            Interrupt:11 Base address:0x3000
eth0:1   Link encap:Ethernet HWaddr 00:50:8D:47:AA:FF
            inet addr:192.168.1.20 Bcast:192.168.1.255 Mask:255.255.255.0
            UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
            RX packets:18347596 errors:0 dropped:0 overruns:0 frame:0
            TX packets:17827505 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:100
            RX bytes:1387340808 (1323.0 Mb) TX bytes:3378133984 (3221.6 Mb)
            Interrupt:11 Base address:0x3000
# service network restart //讓網卡重新啟動,以便啟用所有設定好的 IP

接著必須在 DNS 上新增 A 紀錄,這和 Name-base 虛擬站台使用 CNAME 紀錄是不同的(Name-base 當然也可以使用 A 紀錄,不過通常是使用 CNAME 紀錄為主)。上述準備工作做好後,接下來必須修改 httpd.conf 設定,這部分反而比較簡單:

Listen 12000 //如果想使用 80 埠提供服務,請刪除此行
<VirtualHost 192.168.1.10:12000> //注意:這個地方是使用 IP 來區分而非使用網址,如果想使用 80 埠提供服務,請刪除 :12000
ServerName
wam.spps.
ServerAdmin wam@test.
DocumentRoot /usr/libexec/wam
............................................................ //設定與前例相同,因此省略
</VirtualHost>

手動測試 HTTP

$ telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
GET / HTTP/1.1
//輸入要連結的相對網址
Host: mail.spps.
// Host: 標頭告知 base URL,要結束標頭必須連按兩次 Enter

HTTP/1.1
200 Ok
Date: Sat, 15 Mar 2003 07:34:11 GMT
Server: Apache/2.0.40 (Red Hat Linux)
Accept-Ranges: bytes
Content-Length: 2898
Content-Type: text/html; charset=Big5
Content-Language: zh-tw

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE>Test Page for the Apache Web Server on Red Hat Linux</TITLE>
 </HEAD>
<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
<BODY BGCOLOR="#FFFFFF">
....................................................(中間內容省略)...........................................................
 </BODY>
</HTML>
Connection closed by foreign host.

 

$ telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
GET
http://mail.spps./ HTTP/1.1 //輸入絕對網址時,不需要使用 Host: 標頭

HTTP/1.1
200 Ok
....................................................(其餘內容省略)...........................................................

 

$ telnet 127.0.0.1 80
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
HEAD http://mail.spps./ HTTP/1.1
//HEAD 指令用來取得 HTTP 標頭,不會傳輸本文

HTTP/1.1
200 Ok
Date: Sat, 15 Mar 2003 07:40:10 GMT
Server: Apache/2.0.40 (Red Hat Linux)
Connection: close
Content-Type: text/html; charset=iso-8859-
1
Connection closed by foreign host.

 

$ telnet 127.0.0.1 12000 //連線到 WAM 伺服器
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
GET /wam.cgi?step=menu&user=shane&password=
mypasswd HTTP/1.1 // URL 傳值進行登入
Host: mail.spps.

HTTP/1.1 200 OK
Date: Sat, 15 Mar 2003 07:45:13 GMT
Server: Apache/1.3.19 (Unix)
Set-Cookie: uid=868
//登入成功,伺服器要求我們紀錄 Cookie
Set-Cookie: pid=%241%2458760616%24fZoQL
9RRFOC3VOWA1B6KY2
Transfer-Encoding: chunked
Content-Type: text/html

<head><meta http-equiv=‘Content-Type‘ content=‘text/html; charset=big5‘>
<META HTTP-EQUIV="Pargma" CONTENT="no-cache">
<title>主選單</title><link rel=‘stylesheet‘ type=‘text/css‘ href=‘test.css‘>
<script>
....................................................(其餘內容省略)...........................................................

 

$ telnet 127.0.0.1 12000 //再次連上 WAM 伺服器
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
GET /wam.cgi?step=m
ail HTTP/1.1
Host: mail.spps.
Cookie: uid=868; //傳送剛才的 Cookie 給伺服器
Cookie: pid=%241%2458760616%24fZoQL9RRFOC3VOWA1B6KY2;

HTTP/1.1 200 OK
Date: Sat, 15 Mar 2003 07:45:13 GMT
Server: Apache/1.3.19 (Unix)
Transfer-Encoding: chunked
Content-Type: text/html

<head><meta http-equiv=‘Content-Type‘ content=‘text/html; charset=big5‘>
<META HTTP-EQUIV="Pargma" CONTENT="no-cache">
<title>網路郵局</title><link rel=‘stylesheet‘ type=‘text/css‘ href=‘test.css‘>
<script>
....................................................(其餘內容省略)...........................................................

管理 apache log

Apache 執行一段時間之後,log 檔會膨脹得很厲害,動不動就是幾百MB,這會造成很大的困擾,尤其是為了分析存取狀況,大家都會安裝 webalizer 套件,因此 log 必須一個月才能清除一次,這時我們可以利用 rotatelogs 指令來進行轉檔工作,將超過一個月的資料轉出來,如果不需保留也可以逕行刪除,以免浪費硬碟空間,進行轉檔的指令如下:

# rotatelogs /var/log/httpd/access_log 259200 //30 天轉檔一次

用這個方法將日誌轉出後然後刪除,不需要停掉 Apache 服務。自己手動轉檔也是蠻累的,我們可以修改 httpd.conf 中的 CustomLog 來替我們作這動作:

CustomLog "|bin/rotatelogs /var/logs/access_log 259200" combined

這樣轉出來的檔案,仍然必須手動刪除,透過 cron job 將刪除動作自動化,也是個不錯的點子。底下再來介紹一個更好的方法,我們可以透過 syslog 輕鬆地管理 Apache 的日誌,syslog 是一個系統套件,其中 logrotate 機制不但能自動幫我們轉出日誌檔,也會自動幫我們清除過期的日誌,可以說是超級簡單好用的工具,請找到 /etc/logrotate.d/httpd 檔案,修改如下:

/var/log/httpd/*log {
monthly //自己加上這一行,這表示一個月要轉檔一次
rotate 1 //自己加上這一行,這表示只保留一份舊日誌檔在硬碟,超過的就刪掉
compress //如果希望將轉出的日誌檔壓縮起來的話,自己加上這一行
missingok
notifempty
sharedscripts
postrotate
  /bin/kill -HUP `cat /var/run/httpd.pid 2>/dev/null` 2> /dev/null || true
endscript
}

附錄:

底下是 HTTP 回應狀態碼的涵義與說明(RFC 2068),注意:下文所說的 Client 有可能是 Proxy Server(精確的講是一個 user agent 或瀏覽器,Server 則有可能是 Web Server Proxy Server,由於 Proxy 介於瀏覽器與網頁伺服器之間因此同時扮演兩種角色

分類 狀態碼 說明
資訊 100 Continue 催促 Client 送出後續要求,當 Client 提出的請求不完整時會產生此訊息(當 Client 上傳大檔案時,會將檔案切細再傳,Server 回應此訊息告訴 Client:前面部分已收到,請繼續送出後續資料)
101 Switching Protocols Server 接受 Client 變更應用層通訊協定的請求,用來回應 Client 端送來的 OPTIONS 請求
完成 200 OK Client 的請求已被接受並處理,僅用來回應 GETHEADPOSTTRACE 請求
201 Created 新網頁已經建立,僅用來回應 PUT 請求
202 Accepted Server 已接收請求,但處理需要時間完成,Client 可以斷線不用等待
203 Non-Authoritative Information Client 端送出的請求未包含 Web-Authoritative 標頭,送出此回應後瀏覽器會要求使用者登入
204 No Content 處理 Client 端的請求僅需回覆標頭時,Server 會回覆此訊息
205 Reset Content Client 端要求重設表單資料,Server 已接受並清除上次上傳的資料
206 Partial Content 因為頻寬限制,Server 將較大的網頁或檔案分次傳送,由於僅能傳輸部分內容,因此以此訊息通知 Client 資料尚未傳完
轉向 300 Multiple Choices 要求的網頁提供多重選擇,Client 可以根據參觀者的需要選取適合的網頁(多語系支援)
301 Moved Permanently 要求的網頁已經永久改變網址了,Server 會以 Location: 標頭告知新網址
302 Found 要求的網頁暫時改變網址,Client 下次連線時應優先嘗試原網址。由於 RFC 1945 2068 禁止 Client 在網頁重導向時變更指令(POST 變成 GET),因此是否須變更指令必須由 Server 告知,為了釐清此需求,多增加了兩個回應訊息 303 307 (前者要變,後者不變)
303 See Other 通知 Client 連到另一個網址去查看上傳表單的結果(POST 變成 GET),當使用程式作網頁轉向時,會回應此訊息
304 Not Modified 網頁 Expired 標頭顯示已過期,因此 Client 要求 reload 該網頁,但其內容並沒有變更,回應附加標頭的 GET 請求
305 Use Proxy 要求的網頁必須透過 Server 指定的 proxy 才能觀看
306 (Unused) 1.0 版使用,現在已經取消不用
307 Temporary Redirect 要求的網頁暫時改變網址,Client 下次連線時應優先嘗試原網址(設計用來取代 302,但因為有些 Client 僅支援 1.0 版,因此 302 還是保留)


端錯誤
400 Bad Request Server 看不懂 Client 的請求,通常是語法錯誤、打錯字或打成小寫
401 Unauthorized 該網頁必須通過使用者驗證才能取得(另外,當 Client 上傳的檔案太大時,Server 可以回應此訊息拒收)
402 Payment Required 預計給新版本用的
403 Forbidden 權限不足因此 Client 的請求被拒絕
404 Not Found Client 嘗試連結的網頁不存在
405 Method Not Allowed 該目錄禁止使用 Client 送來的指令
406 Not Acceptable 該網頁含有 Client 無法支援的語系、字元集、編碼方式或多媒體串流格式時,Server 以此訊息回應
407 Proxy Authentication Required 類似於 401,但這是給 Proxy 使用的,當 Client 透過 Proxy 觀看某些特定網頁時,Proxy 會要求先通過認證(配合 305 來使用,可以讓眾多站台統一透過同一台 Proxy 進行會員管理)
408 Request Timeout Server 苦等不到 Client 送來的請求
409 Conflict 當版本管理被啟用,而 Client 要求 PUT 的網頁正被修改中(Locked)或網頁版本比現有的還舊,Server 將回應此訊息,請參考 FrontPage Server Extension 中的版本管理功能
410 Gone 該網頁已遷移,但不知道移去哪裡
411 Length Required Client 上傳的表單資料(或檔案)沒有計算大小,Server 拒絕接受
412 Precondition Failed Client 提出的請求中某些標頭所設定的值,經測試後無法正確執行
413 Request Entity Too Large Client 一次送出的請求太多,Server 無法處理逕行斷線
414 Request-URI Too Long Client 上傳資料的標頭,包含太多資訊,Server 無法處理
415 Unsupported Media Type Server 不支援 Client 要求的檔案類型(譬如:某些 third-party 開發的 Server 不支援 JAVA
416 Requested Range Not Satisfiable Client 對某個多媒體串流提出下載某範圍內容的要求,但 Server 無法提供時必須回應此訊息(該串流必須從頭觀看)
417 Expectation Failed 某些先進的 Server 支援獨家的標頭(例如:Netscape Enterprise),當 Client 要求這類的延伸標頭而伺服器不支援時,應該回覆此訊息


端錯誤
500 Internal Server Error 無法預期錯誤(通常是 CGI 程式語法錯誤造成)
501 Not Implemented Client 所要求的指令在 Server 上沒有被實作出來
502 Bad Gateway Proxy 從上游伺服器得到的回應無法辨識時,回應此訊息給 Client
503 Service Unavailable 伺服器因為系統維護或負載太重,無法提供服務
504 Gateway Timeout Proxy 無法從上游伺服器取得 Client 要求的網頁時,回覆此訊息給 Client
505 HTTP Version Not Supported Server 不能支援或不想支援 Client 提出的指令版本
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多