Amazon-Ec2

亞馬遜 ec2 實例上的多個虛擬主機:無法訪問除預設以外的任何其他虛擬主機

  • October 12, 2016

我有一個執行 Ubuntu 14.04 和 Apache 2.4 的 Amazon EC2 實例。我已經為 Apache 配置了 3 個虛擬主機,全部僅用於 HTTPS。

問題是,當我嘗試從 Internet 訪問 Web 伺服器時,主機名會以某種方式失去,並且 apache 會嘗試從預設主機提供頁面,無論我使用哪個主機名訪問它。

/etc/apache2/sites-enabled/default-ssl.conf:

<VirtualHost *:80>
   ServerName monitor.mydomain.net
   Redirect / https://monitor.mydomain.net
</VirtualHost>

<VirtualHost *:443>
   ServerAdmin webmaster@localhost
   ServerName monitor.mydomain.net
   DocumentRoot /usr/share/nagios3/htdocs
   <Directory />
           Options FollowSymLinks
           AllowOverride None
           allow from all
   </Directory>
   <Directory /usr/share/nagios3/htdocs>
           Options Indexes FollowSymLinks MultiViews
           Options +ExecCGI
           AllowOverride None
           Order allow,deny
           allow from all
   </Directory>
   ScriptAlias /cgi-bin/nagios3 /usr/lib/cgi-bin/nagios3
   ScriptAlias /nagios3/cgi-bin /usr/lib/cgi-bin/nagios3
   Alias /stylesheets /etc/nagios3/stylesheets
   <DirectoryMatch (/usr/share/nagios3/htdocs|/usr/lib/cgi-bin/nagios3|/etc/nagios3/stylesheets)>
           Options FollowSymLinks
           DirectoryIndex index.php index.html
           AllowOverride AuthConfig
               <IfVersion < 2.3>
                   Order Allow,Deny
                   Allow From All
               </IfVersion>
               <IfVersion >= 2.3>
                   Require all denied
               </IfVersion>
               AuthName "Nagios Access"
           AuthType Basic
           AuthUserFile /etc/nagios3/htpasswd.users
           <RequireAny>
                   Require valid-user
           </RequireAny>
   </DirectoryMatch>
   ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
   <Directory "/usr/lib/cgi-bin">
           AllowOverride None
           Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
           Order allow,deny
           Allow from all
   </Directory>

   ErrorLog ${APACHE_LOG_DIR}/nagios_error.log
   LogLevel warn
   CustomLog ${APACHE_LOG_DIR}/nagios_access.log combined
   SSLEngine on

   SSLCertificateKeyFile /etc/ssl/private/a-wildcard.key
   SSLCertificateFile /etc/ssl/certs/a-wildcard+dhparam.pem
   SSLCertificateChainFile /etc/ssl/certs/gd_bundle-g2-g1.crt

   <FilesMatch "\.(cgi|shtml|phtml|php)$">
           SSLOptions +StdEnvVars
   </FilesMatch>
   <Directory /usr/lib/cgi-bin>
           SSLOptions +StdEnvVars
   </Directory>
   BrowserMatch "MSIE [2-6]" \
           nokeepalive ssl-unclean-shutdown \
           downgrade-1.0 force-response-1.0
   BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>

/etc/apache2/sites-enabled/timetracker.conf:

<VirtualHost timetracker.mydomain.net:80>
   ServerName timetracker.mydomain.net
   Redirect / https://timetracker.mydomain.net
</VirtualHost>
<VirtualHost timetracker.mydomain.net:443>

   ServerAdmin webmaster@mydomain.net
   ServerName timetracker.mydomain.net

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

   ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
   <Directory "/usr/lib/cgi-bin">
           AllowOverride None
           Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
           Order allow,deny
           Allow from all
   </Directory>

   ErrorLog ${APACHE_LOG_DIR}/timetracker_error.log

   LogLevel warn

   CustomLog ${APACHE_LOG_DIR}/timetracker_access.log combined

   SSLEngine on

   SSLCertificateKeyFile /etc/ssl/private/a-wildcard.key
   SSLCertificateFile /etc/ssl/certs/a-wildcard+dhparam.pem
   SSLCertificateChainFile /etc/ssl/certs/gd_bundle-g2-g1.crt

   <FilesMatch "\.(cgi|shtml|phtml|php)$">
           SSLOptions +StdEnvVars
   </FilesMatch>
   <Directory /usr/lib/cgi-bin>
           SSLOptions +StdEnvVars
   </Directory>

   # MSIE 7 and newer should be able to use keepalive
   BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

</VirtualHost>

當然,該域已匿名。

在瀏覽器中測試 URL 給了我:

monitor.mydomain.net-> 來自 monitor.mydomain.net 的 Nagios 頁面timetracker.mydomain.net-> ALSO 來自 monitor.mydomain.net 的 Nagios 頁面,而它應該提供來自 timetracker.mydomain.net 的 Kimai 頁面。

這是我通過monitor.mydomain.net訪問頁面後的日誌文件nagios_acces.log:

188.194.164.71 - nagiosadmin [10/Oct/2016:19:08:35 +0000] "GET / HTTP/1.1" 200 6389 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.0"
188.194.164.71 - nagiosadmin [10/Oct/2016:19:08:36 +0000] "GET /side.php HTTP/1.1" 200 1429 "https://monitor.mydomain.net/" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.0"
188.194.164.71 - nagiosadmin [10/Oct/2016:19:08:36 +0000] "GET /main.php HTTP/1.1" 200 1917 "https://monitor.mydomain.net/" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.0"

當我通過 timetracker.mydomain.com 訪問該站點時,我在同一個日誌文件中獲得了這些行:

188.194.164.71 - nagiosadmin [10/Oct/2016:19:12:19 +0000] "GET / HTTP/1.1" 200 1018 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.0"
188.194.164.71 - nagiosadmin [10/Oct/2016:19:12:20 +0000] "GET /side.php HTTP/1.1" 200 1429 "https://timetracker.mydomain.net/" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.0"
188.194.164.71 - nagiosadmin [10/Oct/2016:19:12:20 +0000] "GET /main.php HTTP/1.1" 200 1917 "https://timetracker.mydomain.net/" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.0"
188.194.164.71 - nagiosadmin [10/Oct/2016:19:12:20 +0000] "GET /images/favicon.ico HTTP/1.1" 200 1178 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.2.0"

請注意,這些行也出現在 monitor 的日誌文件中timetracker的實際日誌文件保持為空。

有人向我建議,Amazon EC2 實例可能位於反向代理之後,該代理會以某種方式丟棄發出原始 HTTP 請求的主機名。

這是真的嗎?如果是這樣,我該如何解決?

提前非常感謝!

編輯:整個配置已從另一台伺服器遷移,該伺服器在該伺服器上按預期完美執行。兩台伺服器上的 /etc/apache2 目錄完全一樣,當然除了二級域名。唯一的其他區別是原始伺服器是 Debian Jessie,而新伺服器是 Ubuntu 14.04。

這是因為AWS的網路環境。您的 EC2 實例看起來分配了 2 個 IP(私有一個和公共一個),但實際上 EC2 僅分配了私有 ip。公共 IP 指向位於 VPC 前面的一些巨大的 NAT 設備,該設備知道如何將公共 IP 映射到您的 EC2 實例。這是 AWS 的怪異之處之一。

這是您的問題的根本原因。如您所見,您的預設虛擬主機被聲明為<VirtualHost *:80><VirtualHost *:443>對於 apache 意味著“掃描 apache 正在偵聽的每個介面上的請求並查找 Host 標頭等於 monitor.mydomain.net 的請求(如 ServerName 指令中設置) ”。沒關係,您的請求是通過您的私有 IP(由於 NAT 設備)發出的,並且一切正常。

但是在您的第二個虛擬主機中,您已聲明為<VirtualHost timetracker.mydomain.net:80>resp。as <VirtualHost timetracker.mydomain.net:443>,這意味著在 apache 語言中“掃描通過 IP timetracker.mydomain.net 介面的所有請求並查找主機標頭 timetracker.mydomain.net”。問題是您的 EC2**與 timetracker.mydomain.net 的 IP 沒有介面,**因為該 IP 指向 AWS NAT 設備,而不是您的 EC2 實例,因此從不使用此規則。

您必須重新配置所有 VirtualHosts 以偵聽 *:80 和 *:443 並使用ServerName指令定義您的站點。不幸的是,您無法將公共 IP 直接放在 EC2 上。AWS 之所以這樣做,是因為他們希望動態更改 IP 和 EC2 實例的映射。

引用自:https://serverfault.com/questions/808224