我正在尝试使用以下subjectAltName生成证书:
hostname *.hostname hostname.mydomain.local *.hostname.mydomain.local
我通过OpenSSL生成CSR,然后从Microsoft Active Directory证书服务获取证书。 证书适用于以下替代名称:
hostname hostname.mydomain.local *.hostname.mydomain.local
但是, *.hostname只是不起作用。 使用Curltesting,我得到以下输出:
% curl https://m.example/ curl: (51) SSL: certificate subject name '*.example' does not match target host name 'm.example'
另一方面,如果我添加“m.example”作为subjectAltName ,那么它就起作用了。 所以,缩短主机名的通配符拒绝工作。
后来我有一个类似的问题。
我已经为Windows和Linux服务器设置了一个本地DNS,并将其作为顶级域名。 为了节省为每个虚拟主机创build和签名证书,并避免configuration新的IP地址(非SNI Web服务器),我创build了一个密钥和证书*.staging但我试过的所有客户端(包括curl)只报告证书*.staging名称*.staging与我在使用TLS在我们的Staging服务器上加载虚拟主机时不匹配目标主机名称。
我花了很多年试图弄清为什么我为*.staging生成的通配符证书不起作用。 我已经阅读了所有相关的RFC,但没有一个具体说明这样的通配证书是无效的或非法的。
读完这个出色的Security Stack Exchange后,我终于明白了。
重要的是什么SSL客户端将接受作为“有效的证书”,即一个名称,其中包含一个名称与目标服务器名称(URL中包含的名称)相匹配。 这在名义上在RFC 2818第3.1节中有具体规定,它允许包含诸如“
www.*.*c*”之类的任何通配符名称,在理论上匹配包含三个组件的任何服务器名称,第一个是“www”第三个包含至less一个“c”。
…
所以浏览器厂商自己制定了scheme和限制。 很久以后,发布了一个新的RFC (2011年3月发布的6125), 第6.4.3节专用于处理证书中的通配符名称。 RFC 6125所描述的更符合实际, 是一个“build议的标准”,所以在某种程度上至less有一些意愿可以实现。 但是,RFC 6125没有规定拒绝
*.com; 但浏览器确实拒绝它。
可以为第二级域颁发通配符SSL证书吗? 也值得加票。
我想,除了讲述个人挫折之外,我的答案除了链接到RFC和安全协议栈上的相关答案之外,并没有真正增加很多。 我想我会花更多精力去寻找Chromium和Firefox使用的当前相关的源代码。
请注意,Chromium源代码中的注释明确提到未知的顶级域(如*.intranet )是不允许的。
另外:没有提及可覆盖此行为的用户可configuration选项。
从Mozilla中央水银库
像NSS一样,至less需要两个标签来跟随通配符标签。
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 Git仓库
不允许在公共/ ICANN注册pipe理机构控制域中使用通配符 – 即防止* .com或* .co.uk成为有效的名称
另外,也隐含地阻止了未知的顶级域名(例如,“内联网”域名或尚未添加到注册pipe理机构控制的域名数据集的新顶级域名/新通用顶级域名(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的主机名,并确定由注册服务器控制的最长部分。 尽pipe从技术angular度而言,主机名称的顶级域名(TLD)是名称的最后一个小点部分(如.com或.org),但许多域名(如co.uk)的function就好像它们是顶级域名(TLD)一样,在它们下面的更具体的,基本上不相关的名字的数量。 例如,.uk是一个顶级域名(TLD),但没有人允许直接在.uk下注册一个域名; “有效”顶级域名是ac.uk,co.uk等。 我们不希望允许* .co.uk中的任何网站为整个co.uk域设置一个cookie,因此能够确定哪些更高级别的域可以作为有效的TLD以及哪些可以注册是非常重要的。
Chromium和Mozilla项目都是基于Mozilla发布的公共后缀列表 ,定义了一个有效的TLD 。
HTTPS客户应出于安全原因拒绝匹配*.com或*.net (或甚至* )等TLD通配符:没有任何单一证书应声称对整个TLD拥有权限。
现在,客户端应该如何确定.example是否是TLD(匹配*.example禁止)或简短forms(匹配允许)? 特别是考虑到新的顶级域名(TLD)每隔一段时间就会popup,任何静态顶级域名(TLD)名单都很快就会过时。
所以客户端只是拒绝匹配任何通配符*.XYZ并期望在通配符中至less看到两个点。
请注意,他们仍然应该保留像*.co.uk *.co.jp等通配符黑名单