Я пытаюсь создать сертификат со следующим subjectAltName:
hostname
*.hostname
hostname.mydomain.local
*.hostname.mydomain.local
Я генерирую CSR через OpenSSL, а затем получаю сертификат из служб сертификации Microsoft Active Directory. Сертификат работает нормально для следующих альтернативных имен:
hostname
hostname.mydomain.local
*.hostname.mydomain.local
Но, *.hostname
просто не работает. Тестируя Curl, я получаю следующий результат:
% curl https://m.example/
curl: (51) SSL: certificate subject name '*.example' does not match target host name 'm.example'
Если, с другой стороны, я добавлю m.example как subjectAltName, тогда это работает. Итак, подстановочный знак с сокращенным именем хоста просто отказывается работать.
Некоторое время назад у меня была аналогичная проблема.
Я настроил локальный DNS для серверов Windows и Linux с .staging в качестве TLD. Чтобы сэкономить на создании и подписании сертификатов для каждого виртуального хоста и избежать необходимости настраивать новые IP-адреса (веб-серверы, отличные от SNI), я создал ключ и сертификат для *.staging
но все клиенты, которых я пробовал (включая curl), сообщали только имя субъекта сертификата *.staging
не соответствует имени целевого хоста, когда я пытался загрузить виртуальные хосты на наш промежуточный сервер с помощью TLS.
Я потратил много времени, пытаясь выяснить, почему сертификат с подстановкой, который я создал для *.staging
не сработает. Я прочитал все соответствующие RFC, но ни один из них специально не указывал, что такой шаблонный сертификат недействителен или незаконен.
Я в конце концов просветился после прочтения этот отличный ответ Security Stack Exchange.
Важно то, что SSL-клиенты будет принимать как «действительный сертификат», т.е. сертификат, включающий имя, которое «совпадает» с предполагаемым именем сервера (тем, которое включено в URL-адрес). Это номинально указано в RFC 2818, раздел 3.1, и он позволяет использовать множество видов подстановочных имен, в том числе такие, как "
www.*.*c*
", совпадающее (теоретически) с любым именем сервера, содержащим три компонента, первый из которых"www
"а третий содержит хотя бы один"c
".
...
Поэтому производители браузеров вводили свои схемы и ограничения. Намного позже новый RFC (6125, с марта 2011 г.), с раздел 6.4.3 посвящен обработке подстановочных имен в сертификатах. То, что описывает RFC 6125, больше соответствует действительности, и является «предлагаемый стандарт», так что на каком-то уровне есть хоть какая-то воля, чтобы это произошло. Однако ничто в RFC 6125 не требует отказа от
*.com
; еще браузеры делать отклонить это.
В принятый ответ к Можно ли выдать подстановочный SSL-сертификат для домена второго уровня? также заслуживает голосования.
Я подумал, что помимо пересказа личного разочарования, мой ответ на самом деле ничего не добавляет, кроме ссылки на RFC и соответствующие ответы на Security Stack Exchange; Я подумал, что приложу больше усилий и найду актуальный исходный код, используемый Chromium и Firefox.
Обратите внимание, что комментарии в исходном коде Chromium явно упоминают, что неизвестные домены верхнего уровня (например, *.intranet
) запрещены.
Также: нет ссылки на настраиваемый пользователем параметр, который может переопределить это поведение.
Из Mercurial Repository в mozilla-central
Как и в случае с NSS, после метки с подстановочным знаком требуется как минимум две метки.
if (isWildcard) {
// If the DNS ID ends with a dot, the last dot signifies an absolute ID.
size_t labelCount = (labelLength == 0) ? dotCount : (dotCount + 1);
// Like NSS, require at least two labels to follow the wildcard label.
//
// TODO(bug XXXXXXX): Allow the TrustDomain to control this on a
// per-eTLD+1 basis, similar to Chromium. Even then, it might be better to
// still enforce that there are at least two labels after the wildcard.
if (labelCount < 3) {
return false;
}
// XXX: RFC6125 says that we shouldn't accept wildcards within an IDN
// A-Label. The consequence of this is that we effectively discriminate
// against users of languages that cannot be encoded with ASCII.
if (StartsWithIDNALabel(hostname)) {
return false;
}
// TODO(bug XXXXXXX): Wildcards are not allowed for EV certificates.
// Provide an option to indicate whether wildcards should be matched, for
// the purpose of helping the application enforce this.
}
Запрещать использование подстановочных знаков для общедоступных доменов / доменов, контролируемых реестром ICANN, то есть предотвращать использование * .com или * .co.uk в качестве допустимых представленных имен.
Кроме того, неявно предотвращаются также неизвестные домены верхнего уровня (например, домены «интрасети» или новые TLD / gTLD, еще не добавленные в набор данных домена, контролируемого реестром).
if (!reference_domain.empty()) {
DCHECK(reference_domain.starts_with("."));
// Do not allow wildcards for public/ICANN registry controlled domains -
// that is, prevent *.com or *.co.uk as valid presented names, but do not
// prevent *.appspot.com (a private registry controlled domain).
// In addition, unknown top-level domains (such as 'intranet' domains or
// new TLDs/gTLDs not yet added to the registry controlled domain dataset)
// are also implicitly prevented.
// Because |reference_domain| must contain at least one name component that
// is not registry controlled, this ensures that all reference domains
// contain at least three domain components when using wildcards.
size_t registry_length =
registry_controlled_domains::GetRegistryLength(
reference_name,
registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
// Because |reference_name| was already canonicalized, the following
// should never happen.
CHECK_NE(std::string::npos, registry_length);
// Account for the leading dot in |reference_domain|.
bool is_registry_controlled =
registry_length != 0 &&
registry_length == (reference_domain.size() - 1);
// Additionally, do not attempt wildcard matching for purely numeric
// hostnames.
allow_wildcards =
!is_registry_controlled &&
reference_name.find_first_not_of("0123456789.") != std::string::npos;
}
Комментарии в registry_controlled_domain.h также актуальны:
RegistryControlledDomainService проверяет имя хоста переданного ему GURL и определяет самую длинную часть, которая контролируется регистратором. Хотя технически домен верхнего уровня (TLD) для имени хоста является последней частью имени с точкой (например, .com или .org), многие домены (например, co.uk) функционируют, как если бы они были TLD, выделяя любые ряд более конкретных, по существу не связанных имен под ними. Например, .uk - это TLD, но никому не разрешено регистрировать домен непосредственно под .uk; «эффективными» TLD являются ac.uk, co.uk и т. д. Мы бы не хотели, чтобы какой-либо сайт в * .co.uk устанавливал cookie для всего домена co.uk, поэтому важно иметь возможность определять, какие домены более высокого уровня функционируют как эффективные TLD, а какие могут быть зарегистрированы.
И проекты Chromium, и Mozilla основывают свое определение эффективный TLD на Список общедоступных суффиксов как опубликовано Mozilla.
Клиенты HTTPS должны отказаться от сопоставления подстановочных знаков TLD, например *.com
или *.net
(или даже *
) по соображениям безопасности: ни один сертификат не должен претендовать на полномочия в отношении всего TLD.
Теперь, как клиент должен узнать, является ли .example TLD (соответствие *.example
запрещено) или краткая форма (соответствие разрешено)? Особенно с учетом того, что новые TLD появляются через день, и любой статический список TLD скоро устареет.
Таким образом, клиенты просто отказываются соответствовать любому подстановочному знаку *.XYZ
и ожидайте увидеть как минимум две точки в подстановочном знаке.
Обратите внимание, что они по-прежнему должны поддерживать черные списки с подстановочными знаками, например *.co.uk *.co.jp
и т.п.