web-dev-qa-db-ja.com

Apache 2.4のキャッチオールHTTPS仮想ホスト

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です。

どうすればこれを解決できますか?

7

問題は解決されましたが、いくつかの誤解がありました。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がないことでした。 「キャッチオール」ホストの場合、他のServerNamesからの他のVirtualHosts以外の以外のもので動作します。他に一致するものがない場合、ApacheはデフォルトのVirtualHostセクションにフォールバックします。最初のセクション(名前ベースのルックアップが失敗したときにIPベースのルックアップと一致するセクション)のいずれか。

_<virtualhost>_ sの最も一致するセットの名前ベースの仮想ホストは、構成に表示される順序で処理されます。最初に一致するServerNameまたは ServerAlias が使用され、ワイルドカードの優先順位は異なります(ServerNameServerAlias)。

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>
_

私が変更した他の点に注意してください:

  1. _dev.example.com_は、SNIがなくても同じ証明書を使用します。
  2. _<VirtualHost *:443>_ には特別な目的があるため、__default_:443_ではなく__default__を使用します。

    マジック__default__ワイルドカードを含む仮想ホストには、メインサーバーと同じServerNameが与えられます。

    (これは、「キャッチオール」で__default_:443_を使用できることを意味します。他のものでは使用できません。試すことができます!)

  3. ドメインは Reserved Example Domain Names に置き換えられます。

  4. サイトの正規アドレスを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)を表示します。

5
Esa Jokinen

すべての不明なHTTPSトラフィックを特定の仮想ホストにリダイレクトすることは可能ですが、Apacheでは簡単にできませんでした。

  1. 各HTTPS VirtualHostにはServerNameが必要ですが、これはキャッチオールホストには必要ありません。証明書は通常ホスト(ServerNameまたはServerAlias)に関連付けられているため、これはHTTPSの要件です。
  2. Apacheはデフォルトとして最初の仮想ホスト 1を他のすべてが失敗したときに使用します。同じポートIPが構成されている他の構成がないことを確認してください。構成されていない場合、キャッチオールは失敗します。
  3. 元の構成にタイプミスがあり、リダイレクトされたループの一部が発生した可能性があります(VirtualHostに2つの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は年齢の兆候を見せていますか?少なくともこの状況を解決する方法はいくつかあります。

4

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)が必要です。考えられるすべての名前を知っておく必要がありますが、新しいドメイン名を動的に追加する場合は、これらの動的サブドメインのすべてに一致する正規表現を使用できると便利です。

3
Alexis Wilke