Ssl

具有短主機名的萬用字元證書?

  • April 2, 2015

我正在嘗試使用以下subjectAltName生成證書:

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’ 添加為subjectAltName,那麼它可以工作。因此,帶有縮短主機名的萬用字元只是拒絕工作。

個人經驗

不久前,我遇到了類似的問題。

我已經為 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 使用的目前相關原始碼。

*.intranet請注意,Chromium 原始碼中的註釋明確提到不允許使用未知的頂級域(例如)。

另外:沒有引用可以覆蓋此行為的使用者可配置選項。

Mozilla 原始碼

來自Mozilla 中央 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 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;
}

registry_controlled_domain.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發布的公共後綴列表對有效 TLD的定義。

引用自:https://serverfault.com/questions/675229