Apache 2.4でキャッチオール(デフォルト)HTTPS仮想ホストを構成することは可能ですか?現在4つのドメインがあり、HTTPがすべてをキャッチしますが、何らかの構成を追加しようとするとすぐに、他の仮想ホストが壊れます。私の設定は次のようになります:
<VirtualHost _default_:80>
# Default catch-all virtual Host.
Redirect permanent / https://example-prod.com
</VirtualHost>
<VirtualHost _default_:80>
ServerName example-prod.com
ServerName www.example-prod.com
Include conf/sites/example-prod.com.conf
</VirtualHost>
<VirtualHost _default_:80>
ServerName example-dev.com
Include conf/sites/example-dev.com.conf
</VirtualHost>
#
# This is the virtual Host I'm missing and that I cannot get to work.
#
#<VirtualHost _default_:443>
# # Default catch-all virtual Host.
# ServerAlias *
# SSLEngine on
# SSLCertificateFile "C:/prod/hosts.crt.pem"
# SSLCertificateKeyFile "C:/prod/hosts.key.pem"
# SSLCertificateChainFile "C:/prod/intermediate.crt.pem"
# Redirect permanent / https://example-prod.com
#</VirtualHost>
<VirtualHost _default_:443>
ServerName example-prod.com
ServerName www.example-prod.com
SSLEngine on
SSLCertificateFile "C:/prod/hosts.crt.pem"
SSLCertificateKeyFile "C:/prod/hosts.key.pem"
SSLCertificateChainFile "C:/prod/intermediate.crt.pem"
Include conf/sites/example-prod.com.conf
</VirtualHost>
<VirtualHost _default_:443>
ServerName example-dev.com
SSLEngine on
SSLCertificateFile "C:/dev/hosts.crt.pem"
SSLCertificateKeyFile "C:/dev/hosts.key.pem"
SSLCertificateChainFile "C:/dev/intermediate.crt.pem"
Include conf/sites/example-dev.com.conf
</VirtualHost>
私のhttpd.confにはもうDocumentRoot
がありません-すべてがvhostにあり、含まれています。これも専用サーバーとIPです。
どうすればこれを解決できますか?
問題は解決されましたが、いくつかの誤解がありました。HTTPSが一致する証明書を必要とするという要件がありますが、これによって引き起こされる問題は、接続が信頼されないことですホスト名が証明書と一致しない一般名または にリストされているサブジェクト代替名 :
同じ不一致は、他の回答で提供されているRewriteRule
ソリューションを使用しても維持されます。
「キャッチオール」ホスト名がすべて_example.com
_のサブドメインであり、_*.example.com
_のワイルドカード証明書がある場合、それは一致します。
一方、ほとんどの場合、_something.example.com
_にアクセスしようとすると、_http://
_または_https://
_プレフィックスを付けずにブラウザのアドレスバーに入力すると、ブラウザのデフォルトはHTTPになります。したがって、証明書が一致しない場合でも、HTTPSで「キャッチオール」リダイレクトを行っても、通常、実際の問題は発生しません。_SSL_ERROR_BAD_CERT_DOMAIN
_エラーが表示されるのはごくわずかです。
Virtual Host Matching は、TLSの有無にかかわらず同じように機能します。
[〜#〜] sni [〜#〜] :がない場合
特定の_
IP:port
_ペアの構成ファイルの最初の名前ベースの仮想ホストは、その_IP:port
_ペアの他の仮想ホストに一致するものがない、そのアドレスとポートで受信されたすべての要求に使用されるため、重要ですServerName
またはServerAlias
。サーバーが Server Name Indication をサポートしていない場合は、すべてのSSL接続にも使用されます。
SNIなし 最初のVirtualHost
からの証明書がハンドシェイクに使用されます:
実際には、Apacheでは名前ベースのSSL仮想ホストを構成できますが、常に最初にリストされた仮想ホスト(選択したIPアドレスとポート上)からの構成を使用して暗号化レイヤーを設定します。
最初の試みでの主な問題は、_ServerAlias *
_があり、ServerName
がないことでした。 「キャッチオール」ホストの場合、他のServerName
sからの他のVirtualHost
s以外の以外のもので動作します。他に一致するものがない場合、ApacheはデフォルトのVirtualHost
セクションにフォールバックします。最初のセクション(名前ベースのルックアップが失敗したときにIPベースのルックアップと一致するセクション)のいずれか。
_
<virtualhost>
_ sの最も一致するセットの名前ベースの仮想ホストは、構成に表示される順序で処理されます。最初に一致するServerName
またはServerAlias
が使用され、ワイルドカードの優先順位は異なります(ServerName
とServerAlias
)。
SOME ServerName
が必要です:
ServerName
ディレクティブは、サーバーの定義内のどこにでも使用できます。ただし、各外観は、そのサーバー内の以前の外観をオーバーライドします。
ServerName
が指定されていない場合、サーバーは、最初にオペレーティングシステムにシステムホスト名を要求することにより、クライアントに表示されるホスト名を推測し、失敗した場合は、システムに存在するIPアドレスで逆引きを実行します。
これにより、次のような構成になります。
_<VirtualHost *:443>
# Default catch-all (everything that won't match the following VirtualHosts)
ServerName catch-all.example.com
ServerAlias www.example.com
SSLEngine on
SSLCertificateFile "C:/prod/hosts.crt.pem"
SSLCertificateKeyFile "C:/prod/hosts.key.pem"
SSLCertificateChainFile "C:/prod/intermediate.crt.pem"
Redirect permanent / https://example.com
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile "C:/prod/hosts.crt.pem"
SSLCertificateKeyFile "C:/prod/hosts.key.pem"
SSLCertificateChainFile "C:/prod/intermediate.crt.pem"
Include conf/sites/example.com.conf
</VirtualHost>
<VirtualHost *:443>
ServerName dev.example.com
SSLEngine on
SSLCertificateFile "C:/prod/hosts.crt.pem"
SSLCertificateKeyFile "C:/prod/hosts.key.pem"
SSLCertificateChainFile "C:/prod/intermediate.crt.pem"
Include conf/sites/dev.example.com.conf
</VirtualHost>
_
私が変更した他の点に注意してください:
dev.example.com
_は、SNIがなくても同じ証明書を使用します。_<VirtualHost *:443>
_ には特別な目的があるため、__default_:443
_ではなく__default_
_を使用します。
マジック_
_default_
_ワイルドカードを含む仮想ホストには、メインサーバーと同じServerNameが与えられます。
(これは、「キャッチオール」で__default_:443
_を使用できることを意味します。他のものでは使用できません。試すことができます!)
ドメインは Reserved Example Domain Names に置き換えられます。
サイトの正規アドレスを1つだけ にするために、「キャッチオール」の一部として(エイリアスではなく)_www.example.com
_を使用することをお勧めします。したがって、私はそこに移動しました。
[〜#〜] sni [〜#〜]があった場合、処理は同じ動作を模倣します詳細は少し異なります:
SSLハンドシェイクさえある前に、ApacheはIPアドレスとTCPポートが接続が確立されているポート(IPベースの仮想ホスティング))に最も一致するものを見つけます
この最も一致する
NameVirtualHost
と同じリテラル引数を持つVirtualHost
ディレクティブがある場合、Apacheは代わりに、一致するVirtualHostと同じ引数を持つすべてのVirtualHost
エントリを考慮します。そうでない場合、SNI処理には実行する選択がありません。クライアントがTLSハンドシェイク要求とともにホスト名を送信する場合、ApacheはこのTLSホスト名を、前の手順で決定された候補
ServerName
セットのServerAlias
/VirtualHost
と比較します。上記に基づいて選択されたVirtualHostは、SSL構成を使用してハンドシェイクを続行します。特に、証明書の内容はどの比較にも使用されません。
SNIを使用すると、_dev.example.com
_の追加の証明書を取得できます。
SNIのすべての前提条件が満たされている場合、SNIは自動的に機能し、_error.log
_は[warn] Init: Name-based SSL virtual hosts only work for clients with TLS server name indication support (RFC 4366)
を表示します。
すべての不明なHTTPSトラフィックを特定の仮想ホストにリダイレクトすることは可能ですが、Apacheでは簡単にできませんでした。
ServerName
が必要ですが、これはキャッチオールホストには必要ありません。証明書は通常ホスト(ServerName
またはServerAlias
)に関連付けられているため、これはHTTPSの要件です。ServerName
ステートメントがありました)。ここで詳細をもう少し理解したいと思いますが、それは質問の焦点ではありません。これに基づいて2つのソリューションがあります。おそらくよりスケーラブルで(例外を更新する必要がない)かつパフォーマンスが高い(追加のモジュールを使用する必要がない)ため、私は最初の方法を好みます。
偽のServerNameを使用したキャッチオール(Esaの推奨)
#
# Catch-all virtual hosts.
#
<VirtualHost _default_:80>
# Default catch-all virtual Host.
Redirect permanent / https://example-prod.com
</VirtualHost>
<VirtualHost _default_:443>
ServerName catch-all
SSLEngine on
SSLCertificateFile "C:/dev/hosts.crt.pem"
SSLCertificateKeyFile "C:/dev/hosts.key.pem"
SSLCertificateChainFile "C:/dev/intermediate.crt.pem"
Redirect permanent / https://example-prod.com
</VirtualHost>
#
# Real virtual hosts.
#
<VirtualHost _default_:80>
ServerName example-prod.com
ServerAlias www.example-prod.com
Include conf/sites/example-prod.com.conf
</VirtualHost>
<VirtualHost _default_:80>
ServerName example-dev.com
Include conf/sites/example-dev.com.conf
</VirtualHost>
<VirtualHost _default_:443>
ServerName example-prod.com
ServerAlias www.example-prod.com
SSLEngine on
SSLCertificateFile "C:/prod/hosts.crt.pem"
SSLCertificateKeyFile "C:/prod/hosts.key.pem"
SSLCertificateChainFile "C:/prod/intermediate.crt.pem"
Include conf/sites/example-prod.com.conf
</VirtualHost>
<VirtualHost _default_:443>
ServerName example-dev.com
SSLEngine on
SSLCertificateFile "C:/dev/hosts.crt.pem"
SSLCertificateKeyFile "C:/dev/hosts.key.pem"
SSLCertificateChainFile "C:/dev/intermediate.crt.pem"
Include conf/sites/example-dev.com.conf
</VirtualHost>
mod_rewrite(Alexisが推奨)
<VirtualHost _default_:80>
# Default catch-all virtual Host.
Redirect permanent / https://example-prod.com
</VirtualHost>
<VirtualHost _default_:80>
ServerName example-prod.com
ServerName www.example-prod.com
Include conf/sites/example-prod.com.conf
</VirtualHost>
<VirtualHost _default_:80>
ServerName example-dev.com
Include conf/sites/example-dev.com.conf
</VirtualHost>
<VirtualHost _default_:443>
ServerName example-prod.com
ServerName www.example-prod.com
SSLEngine on
SSLCertificateFile "C:/prod/hosts.crt.pem"
SSLCertificateKeyFile "C:/prod/hosts.key.pem"
SSLCertificateChainFile "C:/prod/intermediate.crt.pem"
Include conf/sites/example-prod.com.conf
# Default catch-all HTTPS virtual Host.
# Make sure to add all valid SSL domains on this Host to avoid conflicts.
RewriteEngine on
RewriteCond %{HTTP_Host} !^example-prod\.com$ [NC]
RewriteCond %{HTTP_Host} !^www\.example-prod\.com$ [NC]
RewriteCond %{HTTP_Host} !^example-dev\.com$ [NC]
RewriteRule .* https://example-prod [R=permanent,L]
</VirtualHost>
<VirtualHost _default_:443>
ServerName example-dev.com
SSLEngine on
SSLCertificateFile "C:/dev/hosts.crt.pem"
SSLCertificateKeyFile "C:/dev/hosts.key.pem"
SSLCertificateChainFile "C:/dev/intermediate.crt.pem"
Include conf/sites/example-dev.com.conf
</VirtualHost>
では、なぜ単純なものはそれほど複雑なのでしょうか。 Apacheは年齢の兆候を見せていますか?少なくともこの状況を解決する方法はいくつかあります。
HTTPSには証明書と一致するドメイン名が必要であるため、対応するServerName
がない*:443
は意味がありません。
ただし、RewriteRule
を使用して、他の<VirtualHost>
エントリでリダイレクトを使用できます。
RewriteEngine on
RewriteCond %{HTTP_Host} ^(something-else.example-prod.com|whatever.example-prod.com|...others...)$
RewriteRule ^/(.*) https://www.example-prod.com/$1 [R=permanent,L]
特定のドメインのみが期待どおりにリダイレクトされることを確認する条件(RewriteCond
)が必要です。考えられるすべての名前を知っておく必要がありますが、新しいドメイン名を動的に追加する場合は、これらの動的サブドメインのすべてに一致する正規表現を使用できると便利です。