带有短主机名的通配符证书?

Jak*_*sic 6 ssl openssl ssl-certificate wildcard-subdomain wildcards

我正在尝试使用以下subjectAltName生成证书:

hostname
*.hostname
hostname.mydomain.local
*.hostname.mydomain.local
Run Code Online (Sandbox Code Playgroud)

我通过 OpenSSL 生成 CSR,然后从 Microsoft Active Directory 证书服务获取证书。证书适用于以下替代名称:

hostname
hostname.mydomain.local
*.hostname.mydomain.local
Run Code Online (Sandbox Code Playgroud)

但是,*.hostname就是行不通。使用 Curl 进行测试,我得到以下输出:

% curl https://m.example/
curl: (51) SSL: certificate subject name '*.example' does not match target host name 'm.example'
Run Code Online (Sandbox Code Playgroud)

另一方面,如果我将 'm.example' 添加为subjectAltName,则它可以工作。因此,具有缩短主机名的通配符只是拒绝工作。

Ant*_*gan 11

个人经验

不久前,我遇到了类似的问题。

我已经为 Windows 和 Linux 服务器设置了本地 DNS,并将 .staging 作为 TLD。为了节省为每个虚拟主机创建和签署证书并避免配置新 IP 地址(非 SNI Web 服务器),我创建了一个密钥和证书,*.staging但我尝试过的所有客户端(包括 curl)只报告了证书主题名称*.staging每当我尝试使用 TLS 在我们的临时服务器上加载虚拟主机时,都与目标主机名不匹配。

相关 RFC

我花了很长时间试图弄清楚为什么我生成的通配符证书*.staging不起作用。我已经阅读了所有相关的 RFC,但没有一个明确说明这种通配符证书无效或非法。

安全堆栈交换答案

在阅读了这个优秀的 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 当前使用的相关源代码。

请注意,Chromium 源代码中的注释明确提到*.intranet不允许使用未知的顶级域(例如)。

另外:没有引用可以覆盖此行为的用户可配置选项。

Mozilla 源代码

来自mozilla-central Mercurial Repository

和 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.
}
Run Code Online (Sandbox Code Playgroud)

铬源代码

来自Chromium Git 存储库

不允许对公共/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;
}
Run Code Online (Sandbox Code Playgroud)

registry_controlled_domain.h中的注释也相关:

RegistryControlledDomainService 检查传递给它的 GURL 的主机名,并确定由注册商控制的最长部分。尽管从技术上讲,主机名的顶级域 (TLD) 是名称的最后一个点部分(例如 .com 或 .org),但许多域(例如 co.uk)的功能就好像它们是 TLD 一样,分配任何在它们下面有一些更具体的、本质上不相关的名字。例如,.uk 是一个 TLD,但不允许任何人直接在 .uk 下注册域;“有效”顶级域名是 ac.uk、co.uk 等。我们不希望 *.co.uk 中的任何站点为整个 co.uk 域设置 cookie,因此能够识别哪些高级域用作有效 TLD 以及哪些可以注册非常重要。

Chromium 和 Mozilla 项目都基于 Mozilla发布的公共后缀列表有效 TLD的定义。


Nil*_*ann 6

出于安全原因,HTTPS 客户端应拒绝匹配 TLD 通配符,例如*.com*.net(甚至*):任何单个证书都不应声明对整个 TLD 的权限。

现在客户端应该如何确定 .example 是 TLD(*.example禁止匹配)还是短格式(允许匹配)?特别是考虑到新的 TLD 每隔一天弹出一次,并且任何静态 TLD 列表很快就会过时。

因此,客户端只是拒绝匹配任何通配符,*.XYZ并希望在通配符中至少看到两个点。

请注意,他们仍应维护通配符黑名单等*.co.uk *.co.jp