использовать VirtualHost *: 443 по умолчанию для всех несовпадающих ServerAlias ​​[дубликат]

Можно ли настроить универсальный (по умолчанию) HTTPS Vhost на Apache 2.4? В настоящее время у меня есть 4 домена, и HTTP перехватывает все, но как только я пытаюсь добавить какую-либо конфигурацию, мои другие vhosts ломаются. Вот как выглядит моя конфигурация:

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

Как я могу решить эту проблему?

8
задан 9 April 2017 в 05:15
3 ответа

Проблема была решена, но возникли недоразумения. Действительно существует требование, чтобы HTTPS нуждался в соответствующем сертификате, но проблема, вызванная этим, заключается в том, что соединение не будет доверенным, если имя хоста не соответствует сертификату Общее имя или указано в Альтернативное имя субъекта :

  • Такое же несоответствие сохраняется даже с решением RewriteRule , указанным в другом ответе.

  • Если «универсальные» имена хостов являются субдоменами example.com и у вас есть подстановочный сертификат для *. Example.com , он будет соответствовать.

  • С другой стороны, большинство людей при попытке доступа к something.example.com , вводит его в адресную строку браузера без префикса http: // или https: // , а браузеры по умолчанию используют HTTP. Таким образом, «всеобъемлющее» перенаправление на HTTPS даже с несовпадающим сертификатом обычно не вызывает реальных проблем: лишь немногие люди когда-либо видят ошибку SSL_ERROR_BAD_CERT_DOMAIN .

Сопоставление виртуальных хостов работает одинаково с TLS или без него.

Если у вас нет SNI :

Первый виртуальный хост на основе имени в файле конфигурации для данного Пара IP: порт важна, потому что она используется для всех запросов. получен на тот адрес и порт, для которых нет другого vhost для этого IP: пара портов имеет совпадающие ServerName или ServerAlias ​​. Он также используется для всех SSL-соединений, если сервер не поддерживает Индикация имени сервера .

Без SNI сертификат из первого VirtualHost используется для рукопожатия:

На самом деле Apache позволяет настраивать на основе имени SSL виртуальный хостов, но он всегда будет использовать конфигурацию из первых в списке виртуальный хост (на выбранном IP-адресе и порту) для настройки уровень шифрования.

Основная проблема с вашей первоначальной попыткой заключалась в наличии ServerAlias ​​* и отсутствии ServerName . Для универсального хоста он работал бы с чем угодно, кроме других ServerName из других VirtualHost s. Если другого совпадения нет, Apache возвращается к разделу по умолчанию VirtualHost ; в зависимости от того, какой из разделов является первым (который соответствует поиску на основе IP-адреса, когда поиск на основе имени не выполняется).

Виртуальные хосты на основе имени для наилучшего -соответствующий набор из s обрабатываются в том порядке, в котором они появляются в конфигурации. Первый используется сопоставление ServerName или ServerAlias ​​ , без отличий приоритет для подстановочных знаков (ни для ServerName по сравнению с ServerAlias ​​).

Должно быть НЕКОТОРЫЕ 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. Используйте вместо _default_: 443 как _default_ имеет особое назначение:

    Любой виртуальный хост, включает волшебный подстановочный знак _default_ . ServerName в качестве основного сервера.

    (Это также означает, что вы можете использовать _default_: 443 в вашем «общем случае», а не в других. Вы можете попробовать!)

  3. Домен заменяется на Зарезервированные примеры доменных имен .

  4. Я бы предпочел, чтобы 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 соблюдены, он должен работать автоматически и error.log покажет [warn] Init: виртуальные хосты SSL на основе имени работают только для клиентов с поддержкой указания имени сервера TLS (RFC 4366) .

5
ответ дан 4 January 2021 в 10:02

Хотя можно перенаправить весь неизвестный трафик HTTPS на конкретный виртуальный хост, Apache не упростил эту задачу:

  1. Каждому виртуальному хосту HTTPS требуется ServerName , которое у нас нет универсального хозяина. Это требование HTTPS, поскольку сертификаты обычно связаны с хостами ( ServerName или ServerAlias ​​).
  2. Apache будет использовать первый виртуальный хост по умолчанию один, когда все остальное терпит неудачу. Убедитесь, что у вас нет другой конфигурации с таким же настроенным IP-адресом порта, в противном случае у вас будет ошибка.
  3. У меня были опечатки в исходной конфигурации, которые, вероятно, вызвали перенаправленные петли (у меня было 2 ServerName операторов в некоторых VirtualHost). Мне бы хотелось подробнее разобраться в деталях, но вопрос не в этом.

На основании этого есть два решения. Я предпочитаю первый, поскольку он, вероятно, более масштабируемый (нет необходимости обновлять исключения), а также производительность (нет необходимости использовать дополнительные модули).

Всеобщее использование поддельного 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 (предложено Алексисом)

    <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
ответ дан 4 January 2021 в 10:02

HTTPS требует доменного имени, которое соответствует сертификату, поэтому *: 443 без соответствующего ServerName не имеет смысла.

Однако , вы можете использовать перенаправление в других своих записях с RewriteRule .

    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
ответ дан 4 January 2021 в 10:02

Теги

Похожие вопросы