我正在尝试使用以下内容生成证书主题替代名称:
hostname
*.hostname
hostname.mydomain.local
*.hostname.mydomain.local
我通过 OpenSSL 生成 CSR,然后从 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”作为主题替代名称,那么它就可以正常工作。因此,带有缩短主机名的通配符无法正常工作。
答案1
个人经验
不久前我遇到了类似的问题。
我已经为 Windows 和 Linux 服务器设置了本地 DNS,并将 .staging 作为 TLD。为了节省为每个虚拟主机创建和签署证书的时间,并避免必须配置新的 IP 地址(非 SNI Web 服务器),我创建了一个密钥和证书,*.staging
但每当我尝试使用 TLS 在我们的 Staging 服务器上加载虚拟主机时,我尝试的所有客户端(包括 curl)都只报告证书主体名称与*.staging
目标主机名不匹配。
相关 RFC
我花了很长时间才弄清楚为什么我生成的通配符证书不起作用*.staging
。我读过所有相关的 RFC,但没有一个明确指出这种通配符证书无效或非法。
- 将 TLS 与 IMAP、POP3 和 ACAP 结合使用
- 基于 TLS 的 HTTP
- 在传输层安全性 (TLS) 环境中使用 X.509 (PKIX) 证书在互联网公钥基础设施中表示和验证基于域的应用服务身份
安全 Stack Exchange 答案
读完后我终于开悟了这个出色的 Security Stack Exchange 答案。
重要的是SSL 客户端将接受为“有效证书”,即包含与目标服务器名称(URL 中包含的名称)“匹配”的名称的证书。这在名义上指定为RFC 2818,第 3.1 节,并且它允许使用多种通配符名称,包括诸如“
www.*.*c*
”之类的名称,理论上可以匹配任何包含三个部分(第一个部分为“www
”,第三个部分至少包含一个“ ”c
)的服务器名称。
...
因此浏览器厂商制定了自己的方案和限制。很久以后, 新的 RFC(6125,自 2011 年 3 月起)已出版,第 6.4.3 节 专门用于处理证书中的通配符名称。RFC 6125 描述的更符合现实,是“拟议标准”,因此至少在某种程度上,有意愿实现它。然而,RFC 6125 中没有任何内容要求拒绝
*.com
;然而浏览器做拒绝它。
这接受的答案到可以为二级域名颁发通配符 SSL 证书吗?也值得一票。
编辑
我认为除了叙述个人的挫败感之外,我的回答除了链接到 RFC 和 Security Stack Exchange 上的相关答案之外,并没有增加太多内容;我想我会付出更多努力,搜索 Chromium 和 Firefox 使用的当前相关源代码。
*.intranet
请注意,Chromium 源代码中的注释明确提到不允许使用未知的顶级域名(例如)。
另外:没有提到可以覆盖此行为的用户可配置选项。
Mozilla 源代码
从mozilla-central Mercurial 存储库
与 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.
}
Chromium 源代码
不允许公共/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;
}
评论注册表_控制域.h也相关:
RegistryControlledDomainService 检查传递给它的 GURL 的主机名,并确定由注册商控制的最长部分。虽然从技术上讲,主机名的顶级域名 (TLD) 是名称的最后一个点部分(例如 .com 或 .org),但许多域名(例如 co.uk)的功能就像它们是 TLD 一样,在其下分配任意数量的更具体、本质上不相关的名称。例如,.uk 是一个 TLD,但任何人都不允许直接在 .uk 下注册域名;“有效”TLD 是 ac.uk、co.uk 等等。我们不希望允许 *.co.uk 中的任何网站为整个 co.uk 域设置 cookie,因此能够识别哪些更高级别的域名作为有效 TLD 以及哪些可以注册非常重要。
Chromium 和 Mozilla 项目均基于以下定义:有效顶级域名在公共后缀列表由 Mozilla 发布。
答案2
出于安全原因,HTTPS 客户端应该拒绝匹配 TLD 通配符,如*.com
或*.net
(甚至*
):任何单个证书都不应对整个 TLD 声称拥有权威性。
现在客户端该如何确定 .example 是 TLD(*.example
禁止匹配)还是缩写形式(允许匹配)?特别是考虑到每隔一天就会出现新的 TLD,并且任何静态 TLD 列表很快就会过时。
因此客户端只是拒绝匹配任何通配符*.XYZ
并期望在通配符中看到至少两个点。
请注意,他们仍应维护通配符黑名单等*.co.uk *.co.jp
。