Apache HTTP Server 版本 2.4
Virtual_host
和 mod_proxy 搭配使用_default_
虛擬主機ServerPath
指令你的伺服器有多個解析到單一位址之主機名稱,且你希望對 www.example.com
和 www.example.org
做出不同的回應方式。
在 Apache 伺服器上建立虛擬主機設定並不會神奇地為這些主機名稱建立 DNS 條目。你必須在 DNS 中有這些名稱解析到你的 IP 位址,否則沒有人能看到你的網站。你可以將條目放在你的 hosts
檔案中以進行本機測試,但這只有擁有那些 hosts
條目的機器才能執行。
# Ensure that Apache listens on port 80 Listen 80 <VirtualHost *:80> DocumentRoot "/www/example1" ServerName www.example.com # Other directives here </VirtualHost> <VirtualHost *:80> DocumentRoot "/www/example2" ServerName www.example.org # Other directives here </VirtualHost>
星號比對所有位址,因此主伺服器不會處理任何要求。由於載有 ServerName www.example.com
的虛擬主機在設定檔中的順序最優先,因此可視為預設或主伺服器。這代表如果接獲的請求未比對任一個指定的 ServerName
指令,就會由這個第一個 <VirtualHost>
處理。
上述設定是您在幾乎所有基於名稱的虛擬主機狀況下會想要使用的設定。事實上,這個設定唯一無法處理的狀況,就是根據不同的 IP 位址或埠提供不同內容時。
您可以在系統上用特定的 IP 位址取代 *
。此虛擬主機將只用於與指定的 IP 位址建立連線時接收到的 HTTP 請求。
但是,如果系統上的 IP 位址無法預測(例如向 ISP 取得動態 IP 位址且正在使用某種動態 DNS 解決方案時),使用 *
也額外有用。由於 *
比對任何 IP 位址,因此這個設定在您的 IP 位址變更時不需更動就能運作。
在此討論的任何技術都可以延伸到任何數量的 IP 位址。
伺服器有兩個 IP 位址。我們將在其中一個(172.20.30.40
)提供「主」伺服器,server.example.com
,且將在另一個(172.20.30.50
)提供兩個或更多個虛擬主機。
Listen 80 # This is the "main" server running on 172.20.30.40 ServerName server.example.com DocumentRoot "/www/mainserver" <VirtualHost 172.20.30.50> DocumentRoot "/www/example1" ServerName www.example.com # Other directives here ... </VirtualHost> <VirtualHost 172.20.30.50> DocumentRoot "/www/example2" ServerName www.example.org # Other directives here ... </VirtualHost>
所有寄往非 172.20.30.50
位址的請求都將由主伺服器提供。寄往 172.20.30.50
有未知主機名稱,或沒有 Host:
標頭的請求,將由 www.example.com
提供。
伺服器機器有兩個 IP 位址(192.168.1.1
和 172.20.30.40
)。這部機器位於內部(區域網路)網路和外部(網際網路)網路之間。在網路外部,server.example.com
這個名稱解析為外部位址(172.20.30.40
),但在網路內部,這個相同的名稱解析為內部位址(192.168.1.1
)。
只要用一個 <VirtualHost>
區段,伺服器就能用相同的內容回應內部和外部請求。
<VirtualHost 192.168.1.1 172.20.30.40> DocumentRoot "/www/server1" ServerName server.example.com ServerAlias server </VirtualHost>
現在,來自兩個網路的請求都將由同一個 <VirtualHost>
提供。
在內部網路中,人們只要使用名稱 server
就可以,不用使用完全限定主機名稱 server.example.com
。
另請注意,在上述範例中,你可以將 IP 位址清單替換成 *
,這將使得伺服器對所有位址回應相同內容。
您有多個網域會轉到相同的 IP,同時您也想要提供多個埠。下列範例說明,在確定最相符的 IP 位址和埠配對後,就會進行名稱配對。
Listen 80 Listen 8080 <VirtualHost 172.20.30.40:80> ServerName www.example.com DocumentRoot "/www/domain-80" </VirtualHost> <VirtualHost 172.20.30.40:8080> ServerName www.example.com DocumentRoot "/www/domain-8080" </VirtualHost> <VirtualHost 172.20.30.40:80> ServerName www.example.org DocumentRoot "/www/otherdomain-80" </VirtualHost> <VirtualHost 172.20.30.40:8080> ServerName www.example.org DocumentRoot "/www/otherdomain-8080" </VirtualHost>
該伺服器具有兩個 IP 位址(172.20.30.40
及 172.20.30.50
),它們分別解析為 www.example.com
和 www.example.org
網址。
Listen 80 <VirtualHost 172.20.30.40> DocumentRoot "/www/example1" ServerName www.example.com </VirtualHost> <VirtualHost 172.20.30.50> DocumentRoot "/www/example2" ServerName www.example.org </VirtualHost>
對於在任一 <VirtualHost>
指令中未指定之任何位址(例如 localhost
)的要求,都會轉到主要伺服器(如果有的話)。
該伺服器機器具有兩個 IP 位址(172.20.30.40
及 172.20.30.50
),它們分別解析為 www.example.com
和 www.example.org
網址。在每種情況中,我們都希望在埠 80 和 8080 上執行主機。
Listen 172.20.30.40:80 Listen 172.20.30.40:8080 Listen 172.20.30.50:80 Listen 172.20.30.50:8080 <VirtualHost 172.20.30.40:80> DocumentRoot "/www/example1-80" ServerName www.example.com </VirtualHost> <VirtualHost 172.20.30.40:8080> DocumentRoot "/www/example1-8080" ServerName www.example.com </VirtualHost> <VirtualHost 172.20.30.50:80> DocumentRoot "/www/example2-80" ServerName www.example.org </VirtualHost> <VirtualHost 172.20.30.50:8080> DocumentRoot "/www/example2-8080" ServerName www.example.org </VirtualHost>
在 virtualhost 引數中指定之任何未出現在另一個 virtual host 中的位址,都是一個嚴格的 IP-based 虛擬主機。
Listen 80 <VirtualHost 172.20.30.40> DocumentRoot "/www/example1" ServerName www.example.com </VirtualHost> <VirtualHost 172.20.30.40> DocumentRoot "/www/example2" ServerName www.example.org </VirtualHost> <VirtualHost 172.20.30.40> DocumentRoot "/www/example3" ServerName www.example.net </VirtualHost> # IP-based <VirtualHost 172.20.30.50> DocumentRoot "/www/example4" ServerName www.example.edu </VirtualHost> <VirtualHost 172.20.30.60> DocumentRoot "/www/example5" ServerName www.example.gov </VirtualHost>
Virtual_host
和 mod_proxy下列範例讓前端機器透過執行於另一台機器上的伺服器來代理虛擬主機。在該範例中,於 192.168.111.2
的機器上設定了名稱相同的虛擬主機。使用 ProxyPreserveHost On
指令,以便轉送所需的主機名稱,以防我們將多個主機名稱代理至單一機器。
<VirtualHost *:*> ProxyPreserveHost On ProxyPass "/" "http://192.168.111.2/" ProxyPassReverse "/" "http://192.168.111.2/" ServerName hostname.example.com </VirtualHost>
_default_
vhost_default_
vhost接收任何未指定的 IP 位址和埠的所有要求,也就是未用於任何其他虛擬主機的位址/埠配對。
<VirtualHost _default_:*> DocumentRoot "/www/default" </VirtualHost>
使用具有萬用字元埠的此類預設 vhost,可有效禁止任何要求轉送至主要伺服器。
預設 vhost 絕不會提供已傳送至用於名稱為基礎 vhost 之位址/埠的要求。如果要求包含未知或不存在的 Host:
標頭,將會始終從主要名稱為基礎 vhost 提供服務(設定檔中最早出現對應於該位址/埠的 vhost)。
您可以使用 AliasMatch
或 RewriteRule
將任一要求改寫至單一資訊頁面(或指令碼)。
_default_
vhost與設定 1 相同,但伺服器聆聽多個埠,並且我們想要使用第二個 _default_
vhost 針對埠 80。
<VirtualHost _default_:80> DocumentRoot "/www/default80" # ... </VirtualHost> <VirtualHost _default_:*> DocumentRoot "/www/default" # ... </VirtualHost>
埠 80 的預設 vhost(必須出現在任何具有萬用字元埠的預設 vhost 之前)會擷取所有已傳送到未指定 IP 位址的要求。主伺服器絕不用於提供要求。
_default_
vhost我們想要為埠 80 有一個預設 vhost,但沒有其他預設 vhost。
<VirtualHost _default_:80> DocumentRoot "/www/default" ... </VirtualHost>
埠 80 沒有指定地址的要求會由預設 vhost 提供。任何其他沒有指定地址與埠的要求會由主伺服器提供。
虛擬主機宣告中任何使用*
都會具有高於 _default_
的優先權。
具有主機名稱 www.example.org
的基於名稱的 vhost(取自於我們的 基於名稱的範例,設定 2)應取得其自己的 IP 位址。為了避免名稱伺服器或代理程式快取基於名稱的 vhost 的舊 IP 位址的問題,我們想要在移轉期間提供兩個變體。
解決方案很簡單,因為我們可以只將新 IP 位址(172.20.30.50
)新增到 VirtualHost
指令。
Listen 80 ServerName www.example.com DocumentRoot "/www/example1" <VirtualHost 172.20.30.40 172.20.30.50> DocumentRoot "/www/example2" ServerName www.example.org # ... </VirtualHost> <VirtualHost 172.20.30.40> DocumentRoot "/www/example3" ServerName www.example.net ServerAlias *.example.net # ... </VirtualHost>
現在可以透過新地址(作為基於 IP 的 vhost)和舊地址(作為基於名稱的 vhost)存取 vhost。
ServerPath
指令我們有一個具有兩個基於名稱的 vhost 的伺服器。為了符合正確的虛擬主機,客戶端必須傳送正確的Host:
標頭。舊的 HTTP/1.0 客戶端不會傳送這樣的標頭,而 Apache 也無法了解客戶端嘗試要接觸哪個 vhost(然後從主要 vhost 提供要求)。為了提供最大的向後相容性,我們創造了一個主要 vhost,它會傳回包含連結的單一頁面,其中連結包含到基於名稱的虛擬主機的 URL 字首。
<VirtualHost 172.20.30.40> # primary vhost DocumentRoot "/www/subdomain" RewriteEngine On RewriteRule "." "/www/subdomain/index.html" # ... </VirtualHost> <VirtualHost 172.20.30.40> DocumentRoot "/www/subdomain/sub1" ServerName www.sub1.domain.tld ServerPath "/sub1/" RewriteEngine On RewriteRule "^(/sub1/.*)" "/www/subdomain$1" # ... </VirtualHost> <VirtualHost 172.20.30.40> DocumentRoot "/www/subdomain/sub2" ServerName www.sub2.domain.tld ServerPath "/sub2/" RewriteEngine On RewriteRule "^(/sub2/.*)" "/www/subdomain$1" # ... </VirtualHost>
由於有 ServerPath
指令,對 URL http://www.sub1.domain.tld/sub1/
的要求會永遠由 sub1-vhost 提供。
對 URL http://www.sub1.domain.tld/
的要求只有在客戶端傳送正確的Host:
標頭時才會由 sub1-vhost 提供。如果沒有傳送Host:
標頭,客戶端會從主要主機取得資訊頁面。
請注意有一個奇怪的地方:如果客戶端沒有傳送Host:
標頭,對 http://www.sub2.domain.tld/sub1/
的要求也會由 sub1-vhost 提供。
RewriteRule
指令用來確保傳送正確的Host:
標頭的客戶端可以使用兩個 URL 變體,也即是,有或沒有 URL 字首。