版本 2.3 |
修订 67 |
3-02-2025 |
草案 |
您对本文档及其内容的任何使用均受以下许可条款的约束。
MIT 许可证 (MIT)
版权所有 (c) 2016 GoDaddy Operating Company, LLC。
特此授予任何人免费许可,以获取本软件和相关文档文件(以下简称“软件”)的副本,从而不受限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售本软件副本的权利,并允许向已获得本软件的人员授予此权限,但须遵守以下条件:
上述版权声明和本许可声明应包含在本软件的所有副本或实质部分中。
本软件按“现状”提供,不提供任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为或其他方面,因本软件或本软件的使用或其他交易而引起或与之相关的。
历史上,为服务配置 DNS 对用户来说一直是一项困难的任务。为了简化这一过程,GoDaddy 创建了一个内部功能,简化了为不同应用程序启用 DNS 的过程。
基于此实现的经验,创建了一个改进且更通用的协议版本并开源。本文档描述了 Domain Connect 2.0,并以使其成为开放标准为目的进行共享,该标准可被多个 DNS 提供商和服务提供商利用,以简化互联网上的这种交互。
本文档中使用的关键词 "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"NOT RECOMMENDED"、"MAY" 和 "OPTIONAL" 应按照 BCP 14 [RFC2119] [RFC8174] 中的描述进行解释,当且仅当它们以全部大写字母出现时,如此处所示。
服务提供商 |
指的是提供附加到域名上的产品和服务的实体。示例包括网络托管提供商(如 Wix 或 SquareSpace)、电子邮件服务提供商(如 Microsoft 或 Google),甚至可能是具有 DNS 功能的设备(如家用路由器或自动化控制设备)的硬件制造商(如 Linksys、Nest 和 Philips)。 |
DNS 提供商 |
指的是提供 DNS 服务的实体,例如注册商(如 GoDaddy 或 1and1)或独立的 DNS 服务(如 Cloudflare)。 |
注册商 |
指的是向注册机构注册域名的实体。需要注意的是,对于给定的域名和 DNS 区域,DNS 提供商和注册商可能是不同的实体。 |
客户/用户 |
指的是这些服务的最终用户。 |
模板/服务模板 |
指的是描述一组 DNS 和域名功能更改的文件,用于启用特定服务。 |
公共模板存储库 |
指的是标准化格式的模板公共存储库(阅读更多内容:公共模板存储库)。 |
根域名 |
指的是已注册的域名(例如 example.com 或 example.co.uk),或 DNS 中的委派区域。 |
子域名 |
指的是根域名的子域名(例如 sub.example.com 或 sub.example.co.uk)。 |
历史上,为服务提供商的应用程序配置 DNS 一直是一项复杂且对用户来说困难的任务。
通常,客户会尝试通过在服务提供商处输入其域名来配置其服务。然后,服务提供商使用多种技术来发现 DNS 提供商,但可靠性参差不齐。这可能包括针对域名服务器的 DNS 查询、针对 whois 的查询以及映射表,以找出注册商或运行 DNS 的公司。
一旦服务提供商发现了 DNS 提供商,他们通常会向客户提供正确配置 DNS 的说明。这可能包括帮助文本、屏幕截图,甚至是指向适当工具的链接。
以这种方式发现 DNS 提供商是不可靠的,并且向用户提供说明会呈现许多终端用户通常不理解的技术(DNS 记录类型、TTL、主机名等)和流程。服务提供商编写的说明通常很快就会过时,进一步加剧了用户的困惑。
本规范的目标是创建一个系统,使服务提供商能够轻松地使其应用程序/服务与客户的域名一起工作。这包括 DNS 提供商的发现以及后续的 DNS 修改。
该系统将使用基于 Web 的简单交互和标准身份验证协议来实现。DNS 设置的创建和修改将通过应用模板而不是直接操作单个 DNS 记录来完成。
模板是 Domain Connect 的核心,因为它们完整地描述了服务提供商拥有的服务,并以一组记录的形式包含了启用和操作/维护该服务所需的所有信息。
模板中的各个记录可以通过 groupId 标识。这允许分阶段应用模板。例如,电子邮件提供商可能首先设置 TXT 记录以验证域名,然后设置 MX 记录以配置电子邮件传递。虽然是分开完成的,但这两个更改从根本上来说是同一服务的一部分。
模板也可能包含可变部分,因为 DNS 中数据的取值通常会根据服务的实现和/或用户而变化(例如,服务的 IP 地址、客户 ID 等)。
模板由服务提供商定义,并根据 公共存储库 中发布的模板定义或服务提供商和 DNS 提供商之间达成的带外协议,手动在 DNS 提供商处进行登记。
通过将协议基于模板而不是 DNS 记录,可以实现几个优势。DNS 提供商非常清楚地了解并控制正在更改的设置以启用服务。并且系统更安全,因为模板是受控和包含的。
本规范是一个开放标准,描述了用于在服务提供商和 DNS 提供商之间启用 Domain Connect 的协议、消息和格式。
任何服务提供商都可以自由定义和发布模板。但是,DNS 提供商登记服务提供商模板的条款和条件超出了本文档的范围。DNS 提供商可以选择他们支持哪些模板,可以要求建立合同关系,甚至可以收取登记费用。
服务提供商可以选择接受哪些 DNS 提供商的一种方式是实施 providerId 白名单。选择使用白名单的服务提供商必须使用 providerId 来区分唯一的 DNS 提供商。DNS providerId 通常是域名。
所有值都区分大小写。这包括变量名、值、参数和返回的对象。
一个例外是域名/主机名。这是因为完全限定域名不区分大小写。
模板中以及通过路径或查询字符串传递的 URI 中的 providerId/serviceId 的值区分大小写。不同的规则适用于 公共模板存储库 中的文件命名。
为了将域名附加到服务提供商提供的服务,客户首先需要输入其域名。
DNS 提供商发现不是依赖于检查域名服务器并将它们映射到 DNS 提供商,而是通过 DNS 中的简单记录和 API 来处理。服务提供商查询区域中的特定记录,该记录返回一个 REST 端点以启动协议。当调用此端点时,符合 Domain Connect 标准的 DNS 提供商会返回有关该域名的信息以及如何使用 Domain Connect 配置它。
要应用对 DNS 的更改,有两种用例。第一种是同步 Web 流程,第二种是使用 OAuth 和 API 的异步流程。
需要注意的是,DNS 提供商可以选择仅实现其中一种流程。实际上,许多服务提供商基于同步流程,只有少数服务提供商基于异步 OAuth 流程。因此,许多 DNS 提供商可能会选择仅实现同步流程。
还需要注意的是,单个服务可能仅适用于同步流程、仅适用于异步流程或两者都适用。
此流程专为需要对 DNS 进行一次性同步更改的服务提供商量身定制。
用户首先在服务提供商网站上输入其域名。
+-----------------------------------------------+ | https://acmewebsiteserviceprovider.example | +-----------------------------------------------+ | ACME 网站服务提供商 | | | | 请输入您希望使用 Acme 网站启用的域名并单击“下一步” | | | | +-------------------------------+ | | 域名 | | | | +-------------------------------+ | | | | +-----------------------+ | | | 下一步 | | | +-----------------------+ | | | +-----------------------------------------------+
服务提供商使用发现机制确定 DNS 提供商后,服务提供商应向用户显示一个链接,指示他们可以将“他们的域名连接”到该服务。
+-----------------------------------------------+ | https://acmewebsiteserviceprovider.example | +-----------------------------------------------+ | ACME 网站服务提供商 | | | | 看起来域名“example.com”当前位于 Virtucon Domains。要配置 | | 此域名以与 Acme 网站一起使用,请单击“下一步”。 | | +-----------------------+ | | | 下一步 | | | +-----------------------+ | | | +-----------------------------------------------+
单击链接后,用户将被定向到 DNS 提供商站点上的浏览器窗口。这可以在另一个选项卡或新浏览器窗口中完成,但也可能是在具有返回 URL 的位置导航。此链接传递正在修改的域名、正在启用的服务提供商/模板,以及应用模板和配置服务所需的任何其他参数(变量)。
到达 DNS 提供商站点后,系统会要求用户进行身份验证(如果需要)。
+-----------------------------------------------+ | https://virtucondomains.example | +-----------------------------------------------+ | Virtucon Domains | | | | 请登录 Virtucon domains | | | | +-------------------------+ | | 登录名 |[email protected] | | | +-------------------------+ | | | | +-------------------------+ | | 密码 |****** | | | +-------------------------+ | | | | +-----------------------+ | | | 下一步 | | | +-----------------------+ | | | +-----------------------------------------------+
在 DNS 提供商处进行身份验证后,DNS 提供商必须验证域名 DNS 区域是否由用户控制。DNS 提供商必须验证传入的其他参数是否有效,并且必须提示用户同意对 DNS 进行更改。DNS 提供商还可以警告用户,应用此 DNS 更改将禁用哪些服务。
+-----------------------------------------------+ | https://virtucondomains.example | +-----------------------------------------------+ | Virtucon Domains | | | | ACME 希望使您的域名 example.com 与 ACME 网站一起工作。 | | | | 单击“确认”以进行更改,或单击“取消” | | | | +-----------------+ +-----------------+ | | | 确认 | | 取消 | | | +-----------------+ +-----------------+ | | | +-----------------------------------------------+
假设用户授予此同意,则将应用 DNS 更改。
如果在弹出窗口或选项卡中调用,则在应用更改后应关闭浏览器窗口。如果在原位置调用,则在应用更改后必须将用户导航回服务提供商。
异步 OAuth 流程专为希望相对于用户交互异步更改 DNS 的服务提供商量身定制,或者希望随着时间的推移对 DNS 进行多次或额外的更改。
异步流程的开始方式与同步流程类似。服务提供商确定 DNS 提供商并链接到 DNS 提供商处的同意对话框。到达 DNS 提供商后,用户登录,验证对域名 DNS 区域的控制权,并授予同意。
OAuth 访问权限不是在用户同意后应用 DNS 更改,而是授予给服务提供商。生成 OAuth 访问代码并返回给服务提供商。然后,服务提供商请求访问(持有者)令牌。
OAuth 令牌中授予的权限是服务提供商有权将请求的模板(或多个模板)应用于特定 DNS 提供商处特定用户控制下的特定域名(和特定子域名)DNS。
服务提供商稍后将调用 DNS 提供商的 API,以使用访问令牌应用模板。
应用模板时,必须以名称/值对形式传递其他参数。
为了促进从域名发现 DNS 提供商,使用了 DNS。这是通过返回区域中 _domainconnect 的 TXT 记录来完成的。
此记录内容的示例:
domainconnect.virtucondomains.example
从实际实现的角度来看,DNS 提供商可能在每个区域中都包含或不包含此数据的副本。相反,DNS 提供商只需使用适当的数据响应针对 _domainconnect TXT 记录的 DNS 查询即可。
如何实现这一点由 DNS 提供商决定。
例如,DNS 提供商可能不会将数据存储在域名的 TXT 记录中,而是选择在区域中放置 CNAME,并在 CNAME 的目标中放置 TXT 记录。另一个 DNS 提供商可能只需在 DNS 层响应适当的记录,而无需在每个区域中都包含数据。
返回的 URL 前缀随后被服务提供商用于确定在此 DNS 提供商处对该域名使用 Domain Connect 的其他设置。这是通过调用 REST API 完成的。
GET
https://{_domainconnect}/v2/{domain}/settings
这必须返回一个 JSON 结构,其中包含在 DNS 提供商处对域名(在路径中传递)使用 Domain Connect 的设置。除非另有说明,否则此 JSON 结构必须包含以下字段。
字段 | 键 | 类型 | 描述 |
---|---|---|---|
提供商 ID |
providerId |
字符串 |
(必需) DNS 提供商的唯一标识符。为确保非协调唯一性,这应该是 DNS 提供商的域名(例如 virtucom.example)。 |
提供商名称 |
providerName |
字符串 |
(必需) DNS 提供商的名称。 |
提供商显示名称 |
providerDisplayName |
字符串 |
(可选) 服务提供商应显示的 DNS 提供商的名称。对于为多个品牌提供支持的某些 DNS 提供商,这可能会因域名而异。 |
同步流程的 UX URL 前缀 |
urlSyncUX |
字符串 |
(可选) 用于链接到 DNS 提供商处同步流程的 Domain Connect UX 的 URL 前缀。如果未返回,则 DNS 提供商不支持此域名的同步流程。 |
异步流程的 UX URL 前缀 |
urlAsyncUX |
字符串 |
(可选) 用于链接到 DNS 提供商处异步流程的 Domain Connect UX 元素的 URL 前缀。如果未返回,则 DNS 提供商不支持此域名的异步流程。 |
API URL 前缀 |
urlAPI |
字符串 |
(必需) REST API 的 URL 前缀 |
窗口宽度 |
width |
数字 |
(可选) 这是在弹出窗口中导航以授予同意时所需窗口的宽度。如果未返回,则默认值应为 750px。 |
窗口高度 |
height |
数字 |
(可选) 这是在弹出窗口中导航以授予同意时所需窗口的高度。如果未返回,则默认值应为 750px。 |
UX URL 控制面板 |
urlControlPanel |
字符串 |
(可选) 这是指向 DNS 提供商处编辑 DNS 的控制面板的 URL。此字段允许模板在 DNS 提供商处不受支持的服务提供商提供直接链接以执行手动编辑。 为了允许深度链接到特定域名,此字符串可能包含 %domain%,必须将其替换为域名。 |
域名服务器 |
nameServers |
字符串列表 |
(可选) 这是 DNS 提供商希望区域成为权威的域名服务器列表。这并不表示权威域名服务器;为此,将查询注册机构。 |
{
"providerId": "virtucondomains.example",
"providerName": "Virtucon Domains",
"providerDisplayName": "Virtucon Domains",
"urlSyncUX": "https://domainconnect.virtucondomains.example",
"urlAsyncUX": "https://domainconnect.virtucondomains.example",
"urlAPI": "https://api.domainconnect.virtucondomains.example",
"width": 750,
"height": 750,
"urlControlPanel": "https://domaincontrolpanel.virtucondomains.ex
ample/?domain=%domain%",
"nameServers": ["ns01.virtucondomainsdns.example", "ns02.virtucon
domainsdns.example"]
}
发现必须仅在根域名(区域)上工作。请记住,区域可以委派给其他用户,这使得此信息对服务提供商很有价值,因为对于单个服务,顶点区域与子域名的 DNS 更改可能不同。
服务提供商必须处理以下情况:对 _domainconnect TXT 记录的查询成功,但查询 JSON 的调用失败。如果区域托管在另一个 DNS 提供商处,但包含不正确的 _domainconnect TXT 记录,则可能会发生这种情况。
如果 DNS 提供商不包含该区域,则必须返回 404。
状态 | 响应 | 描述 |
---|---|---|
成功 |
2xx |
HTTP 状态代码为 2xx 的响应表示调用成功。响应是上述 JSON。 |
未找到 |
404 |
状态代码为 404 的响应表示 DNS 提供商没有该区域。 |
在发现期间 JSON 中返回的 Domain Connect 端点采用 URL 形式。
第一组端点用于服务提供商链接到的 UX。这些用于同步流程(用户可以单击以授予同意并应用更改)和异步 OAuth 流程(用户可以授予 OAuth 访问权限)。
第二组端点用于 REST API。
所有端点都以 DNS 提供商的根 URL 开头,例如:
https://connect.dnsprovider.example
它们也可能包含 DNS 提供商自行决定的任何前缀。例如:
https://connect.dnsprovider.example/api
UX 端点和 API 端点的根 URL 在 DNS 提供商发现期间的 JSON 有效负载中返回。
GET
{urlAPI}/v2/domainTemplates/providers/{providerId}/services
/{serviceId}
服务提供商使用此 URL 来确定 DNS 提供商是否通过同步流程支持特定模板。
返回状态代码 200 而不包含正文表示支持该模板。DNS 提供商可以决定在 JSON 对象中公开模板的版本,字段为 version(请参阅:version field 或已部署模板的完整 JSON 对象)。
返回状态代码 404 表示不支持该模板。
状态 | 响应 | 描述 |
---|---|---|
成功 |
2xx |
HTTP 状态代码为 2xx 的响应表示调用成功。响应可选地包含版本或模板。 |
未找到 |
404 |
状态代码为 404 的响应表示不支持该模板 |
GET
{urlSyncUX}/v2/domainTemplates/providers/{providerId}/services
/{serviceId}/apply?[properties]
这是用户被发送以将模板应用于其拥有的域名的 URL。它从服务提供商处调用以启动同步 Domain Connect 协议。
可以通过以下两种方式之一调用此 URL。
第二种是在当前的浏览器选项卡/窗口中。与上述相同,DNS 提供商登录用户(如果需要)、验证用户对域名 DNS 区域的控制权,并在应用模板之前请求确认。应用模板(或用户取消)后,DNS 提供商必须将浏览器重定向到返回 URL (redirect_uri)。
必须将多个参数附加到此 redirect_uri 的末尾。
-
状态
如果在查询字符串中传递了 state 参数,则必须将其作为 redirect_uri 上的 state= 传递回去。
-
错误
如果无法获得授权或发生错误,则必须附加参数 error=。为了与异步 OAuth 流程保持一致,error 参数的有效值将与 OAuth 2.0 [RFC6749] (4.1.2.1. 错误响应 - “error” 参数) 中指定的有效值相同。有效值为:invalid_request、unauthorized_client、access_denied、unsupported_response_type、invalid_scope、server_error 和 temporarily_unavailable。
-
错误描述
发生错误时,可以返回可选的错误描述,其中包含面向开发人员的错误描述。
在正常操作下,由于多种原因可能会返回 access_denied 错误。例如,用户可能无权访问拥有域名的帐户。即使他们有权访问并成功登录,帐户或域名也可能被暂停。
DNS 提供商不太可能希望将此信息泄露给服务提供商,因此描述可能很模糊。
有一个信息可能对与服务提供商通信很有用。这就是最终用户决定取消操作的时候。如果 DNS 提供商希望将此信息传达给服务提供商,则当 error=access_denied 时,error_description 可能包含前缀“user_cancel”。同样,这由 DNS 提供商自行决定。
为了防止开放重定向,除非请求经过数字签名,否则 redirect_uri 必须在模板中 syncRedirectDomain 中指定的域内。
属性 | 请求参数 | 描述 |
---|---|---|
域名 |
domain |
(必需) 正在配置的域名。这是根域名(已注册域名或委派区域)。 |
主机 |
host |
(可选) 这是子域名的主机名。如果留空,则模板将应用于根域名。否则,模板将应用于域名的子域名。 |
重定向 URI |
redirect_uri |
(可选) 在成功授权或出错时将客户端浏览器定向到的位置。如果省略,DNS 提供商将在完成后关闭浏览器窗口。它必须限定在模板中 syncRedirectDomain 的范围内,或者请求必须签名。 |
状态 |
state |
(可选) 传递的随机且唯一的字符串,以防止 CSRF 或传递回状态。当重定向到上述 redirect_uri 时,必须作为参数返回。 |
名称/值对 |
* |
(必需) 将用作模板中“% 包围的”变量的任何键的替换项。此 API 调用的名称部分对应于模板中指定的变量,值部分对应于应用模板时将使用的值。 |
提供商名称 |
providerName |
(可选) 此参数允许调用者为模板 providerName 提供额外的文本以供显示。此文本应用于扩充模板中的 providerName 值,而不是替换它。仅当模板中设置了“sharedProviderName”属性时,才允许使用此参数。注意:这以前由模板中的“shared”属性控制,该属性已弃用。 |
服务名称 |
serviceName |
(可选) 此参数允许调用者为模板 serviceName 提供额外的文本以供显示。它应用于扩充模板中的 serviceName 值,而不是替换它。仅当模板中设置了“sharedServiceName”属性时,才允许使用此参数。 |
组 ID |
groupId |
(可选) 此参数指定要应用的模板中的组。如果未指定组,则应用所有组。可以在逗号分隔的格式中指定多个组。 |
签名 |
sig |
(可选) 查询字符串的签名。请参阅下面的安全注意事项部分。 |
密钥 |
key |
(可选) 包含 DNS 中主机的值,可以在其中获取签名的公钥。此主机所在的域在模板的 syncPubKeyDomain 中。请参阅下面的安全注意事项部分。 |
查询字符串示例:
GET
https://web-connect.dnsprovider.example/v2/domainTemplates/providers/
exampleservice.example/services/template1/apply?domain=example.com
&IP=192.168.42.42&RANDOMTEXT=shm%3A1542108821%3AHello
此调用指示服务提供商希望使用由提供商 (exampleservice.example) 和他们拥有的服务模板 (template1) 的复合键标识的模板将域名 example.com 连接到服务。在此示例中,此模板中有两个变量“IP”和“RANDOMTEXT”。这些变量作为名称/值对传递。
通过应用带有参数的模板,存在必须考虑的安全问题。
考虑上面的模板,其中 A 记录的 IP 地址通过变量传递。不良行为者可以生成一个带有恶意 IP 的 URL,并通过发送电子邮件要求用户“重新配置”其服务来对用户进行网络钓鱼。如果最终用户被说服单击此链接,他们将登陆 DNS 提供商站点以确认更改。对于用户而言,这似乎是配置域名的有效请求。然而,IP 将会劫持服务。
并非所有模板都存在此问题。但当它们存在问题时,有几个选项。
一种选择是禁用同步流程并使用异步 OAuth。这可以通过模板中的 syncBlock 值来控制。但是,如下文所示,OAuth 的实现负担更高,并且需要在每个服务和 DNS 提供商之间进行登记。
另一种选择是对查询字符串进行数字签名。签名作为额外的查询字符串参数附加,经过正确 URL 编码,格式如下:
sig=V2te9zWMU7G3plxBTsmYSJTvn2vzMvNwAjWQ%2BwTe91DxuJhdVf4cVc4vZBYfEYV
7u5d7PzTO7se7OrkhyiB7TpoJJW1yB5qHR7HKM5SZldUsdtg5%2B1SzEtIX0Uq8b2mCmQ
F%2FuJGXpqCyFrEajvpTM7fFKPk1kuctmtkjV7%2BATcvNPLWY7KyE4%2Bqc8jpfN61cP
5l8iA4krAa3%2BfTro5cmWR8YUJ5yrnRs6KT4b5D71HFvOUk0sGEUddUUlsyRQKRHUFN6
HjEya50YDHfZJlYHkHlK0xX6Yqeii9QZ2I35U9eJbSvZGQko5beqviWFXdsVDbvd3DYcb
SHgJq9%2FXoMTTw%3D%3D
服务提供商使用私钥生成此签名。如指示,此签名是从经过正确 URL 编码的查询字符串生成的。
服务提供商必须发布其公钥并将其放置在 syncPubKeyDomain 中模板指定的域名的 DNS TXT 记录中。为了允许密钥轮换,TXT 记录的主机名必须作为另一个变量附加到查询字符串,格式如下:
key=_dcpubkeyv1
此示例指示可以通过对模板中 syncPubKeyDomain 指定的域名中名为 _dcpubkeyv1 的 TXT 记录执行 DNS 查询来找到公钥。
为了考虑 TXT 记录大小限制的 DNS 服务器,DNS TXT 查询可能存在多个记录。例如,公钥:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA18SgvpmeasN4BHkkv0SBjAzIc
4grYLjiAXRtNiBUiGUDMeTzQrKTsWvy9NuxU1dIHCZy9o1CrKNg5EzLIZLNyMfI6qiXnM
+HMd4byp97zs/3D39Q8iR5poubQcRaGozWx8yQpG0OcVdmEVcTfyR/XSEWC5u16EBNvRn
NAOAvZYUdWqVyQvXsjnxQot8KcK0QP8iHpoL/1dbdRy2opRPQ2FdZpovUgknybq/6FkeD
tW7uCQ6Mvu4QxcUa3+WP9nYHKtgWip/eFxpeb+qLvcLHf1h0JXtxLVdyy6OLk3f2JRYUX
2ZZVDvG3biTpeJz6iRzjGg6MfGxXZHjI8weDjXrJwIDAQAB
可能包含多个 TXT 记录。记录的格式如下:
p=1,a=RS256,d=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA18SgvpmeasN
4BHkkv0SBjAzIc4grYLjiAXRtNiBUiGUDMeTzQrKTsWvy9NuxU1dIHCZy9o1CrKNg5EzL
IZLNyMfI6qiXnM+HMd4byp97zs/3D39Q8iR5poubQcRaGozWx8yQpG0OcVdmEVcTfy
p=2,a=RS256,d=R/XSEWC5u16EBNvRnNAOAvZYUdWqVyQvXsjnxQot8KcK0QP8iHpoL/1
dbdRy2opRPQ2FdZpovUgknybq/6FkeDtW7uCQ6Mvu4QxcUa3+WP9nYHKtgWip/eFxpeb+
qLvcLHf1h0JXtxLVdyy6OLk3f2JRYUX2ZZVDvG3biTpeJz6iRzjGg6MfGxXZHjI8
p=3,a=RS256,d=weDjXrJwIDAQAB
此处公钥在 DNS 中分解为四个记录,数据还指示签名算法是使用 x509 证书的 RSA Signature with SHA-256。如果省略 “a” 的值,则假定为 RS256,如果省略 “t” 的值,则假定为 x509。
注意:当前唯一支持的算法是 SHA-256 with x509 证书。此处放置这些值是为了将来兼容性。
上述数据是为以下查询字符串生成的:
a=1&b=2&ip=10.10.10.10&domain=example.net
服务提供商对查询字符串进行签名是可选的。并非所有服务提供商模板都需要或能够提供此级别的安全性。模板中 syncPubKeyDomain 的存在表示模板需要签名验证。
注意:
数字签名将仅在完整的查询字符串上生成,不包括 sig 和 key 参数。这是 ? 之后的所有内容,但 sig 和 key 值除外。
在生成签名之前,必须对每个查询字符串值键/值对的值进行正确 URL 编码。
某些模板可以被多家公司调用,或者用于不同的目的。
例如,大多数服务由同一家公司销售和提供。但是,某些服务提供商具有经销商渠道。这允许服务由服务提供商提供,但通过第三方销售。通常是此第三方经销商配置 DNS。
虽然每个经销商都可以启用 Domain Connect,但这对于 DNS 提供商来说效率低下。启用由多个经销商共享的单个模板将更优化。
作为另一个示例,某些模板可能被同一家公司用于不同的目的。
为了促进这些用例,启用了传入 providerName 和 serviceName 显示的附加上下文的功能。仅当模板通过 sharedProviderName 和/或 sharedServiceName 标志启用此功能时,才允许这样做。
注意:shared 标志以前用于此目的,但已弃用。
呈现给用户的确切消息由 DNS 提供商决定。但是,建议这些字段用于扩充模板中的 serviceName 和 providerName 的显示,而不是替换它。
注意:当服务提供商拥有庞大的经销商渠道时,强烈建议服务提供商为其经销商创建一个 API,以简化 Domain Connect 的实施。在 Domain Discovery 和 URL Formatting 方面,这样做有一些便利因素。但如果模板需要签名,则这将是必需的。
对于具有可能需要多个步骤和/或与用户交互异步的更复杂配置的服务提供商,使用 OAuth 流程是一种更高级的用例。
OAuth 实现的详细信息超出了本规范的范围。相反,此处给出了 Domain Connect 如何使用 OAuth 的概述。
并非所有 DNS 提供商都支持异步流程。因此,建议依赖 OAuth 实现的服务提供商也实现同步实现。
希望使用 OAuth 流程的服务提供商必须在每个 DNS 提供商处注册为 OAuth 客户端。这是一个手动过程。
要注册,服务提供商将提供(除了他们的模板之外)DNS 提供商 OAuth 实现所需的任何配置。这包括成功或出错时重定向的有效 URL 和域名。
注意:重定向的有效性在任何 OAuth 实现中都非常重要。大多数 OAuth 漏洞都是开放重定向和/或泄露的密钥的组合。
作为回报,DNS 提供商将为服务提供商提供客户端 ID 和密钥,这些密钥将在请求令牌时使用。为了简单起见,客户端 ID 应与 providerId 相同。
GET
{urlAsyncUX}/v2/domainTemplates/providers/{providerId}
为了启动 OAuth 流程,服务提供商首先链接到 DNS 提供商以获得同意。
此端点类似于上述同步流程。DNS 提供商必须验证用户身份、验证用户是否控制域名 DNS 区域,并请求用户许可。许可不再是更改 DNS,而是允许服务提供商代表他们进行更改。同样,DNS 提供商可以警告用户,(最终)应用模板可能会更改现有记录和/或中断附加到域名的现有服务。
虽然应用模板的变量将在稍后提供,但某些变量的值可能对于确定冲突是必要的。因此,任何影响冲突记录的变量都应在同意流程中提供。今天,这包括主机中的变量和某些 TXT 记录的数据部分中的变量。随着冲突解决的发展,此列表可能会增长。
该协议允许服务提供商获得同意以应用多个模板。这些模板在 scope 参数中指定。它还允许服务提供商获得同意以将这些模板应用于域名或域名及其多个子域名。这些在 domain 和 host 参数中指定。如果 DNS 提供商实施了冲突检测,他们应考虑所有排列组合。
scope 参数是以空格分隔的模板 serviceId 列表(根据 OAuth 协议)。host 参数是可选的逗号分隔的主机列表。主机的空白条目表示模板可以应用于根域名。例如:
查询字符串 | 描述 |
---|---|
scope=t1+t2&domain=example.com |
模板“t1”和“t2”可以应用于 example.com |
scope=t1+t2&domain=example.com&host=sub1,sub2 |
模板“t1”和“t2”可以应用于 sub1.example.com 或 sub2.example.com |
scope=t1+t2&domain=example.com&host=sub1, |
模板“t1”和“t2”可以应用于 example.com 或 sub1.example.com |
在用户成功授权/验证/同意后,DNS 提供商会将最终用户的浏览器定向到重定向 URI。授权码将作为查询参数 “code=” 附加到此 URI,如 OAuth 规范中所述。
与同步流程类似,出错时,DNS 提供商可以附加错误代码作为查询参数 “error”。这些错误也来自 OAuth 2.0 [RFC6749] (4.1.2.1. 错误响应 - “error” 参数)。有效值包括:invalid_request、unauthorized_client、access_denied、unsupported_response_type、invalid_scope、server_error 和 temporarilly_unavailable。DNS 提供商还可以自行决定返回可选的 error_description,该描述适用于开发人员。此处适用与同步流程中相同的注意事项。
传入调用的状态值必须在查询字符串上作为 “state=” 传回。
下表描述了 OAuth 同意流程请求的查询字符串参数中的值,除非另有说明,否则必须包含这些值
属性 | 键 | 描述 |
---|---|---|
域名 |
domain |
(必需) 正在配置的域名。这是根域名(已注册域名或委派区域)。 |
主机 |
host |
(可选) 模板可以应用于其上的逗号分隔主机名列表。空字符串表示根域名。 |
客户端 ID |
client_id |
(必需) 这是 DNS 提供商在注册期间提供给服务提供商的客户端 ID。建议这应与模板中的 providerId 相同。 |
重定向 URI |
redirect_uri |
(必需) 在成功授权或出错时将客户端浏览器定向到的位置。DNS 提供商将验证 redirect_uri 是否与登记期间提供的值匹配。 |
响应类型 |
response_type |
(可选) 如果包含,则必须是字符串 “code”,以指示正在请求授权码。 |
范围 |
scope |
(必需) OAuth 范围对应于请求的模板。这是以空格分隔的 serviceId 列表。 |
提供商名称 |
providerName |
(可选) 此参数允许调用者为模板 providerName 提供额外的文本以供显示。此文本应用于扩充模板中的 providerName 值,而不是替换它。 |
服务名称 |
serviceName |
(可选) 此参数允许调用者为模板 serviceName(s) 提供额外的文本以供显示。它应用于扩充模板中的 serviceName 值,而不是替换它。 |
状态 |
state |
(可选) 这是传递的随机、唯一的字符串,以防止 CSRF 或将状态值传回给调用者。它将作为参数附加到上述 redirect_url 返回。 |
名称/值对 |
* |
(可选) 将用作模板中“% 包围的”值替换的任何键,这些值是冲突检测所需的。这包括主机中使用的变量和某些 TXT 记录中的数据。 |
POST
{urlAPI}/v2/oauth/access_token
获得授权后,服务提供商必须使用提供的授权码来请求访问令牌。OAuth 规范建议授权码是短期令牌,合理的建议设置是十分钟。因此,此交换需要在该时间到期之前完成,否则需要重复该过程。
此令牌交换通常通过从服务提供商到 DNS 提供商的服务器到服务器 API 调用(使用 POST)完成。以此方式调用时,会提供密钥以及授权码。
OAuth 确实允许在没有密钥的情况下检索访问令牌。这通常在 OAuth 客户端是客户端应用程序时完成。在与 DNS 提供商登记时,需要启用此功能。
当提供密钥时(这是正常情况),必须小心。恶意用户可以创建一个域名,该域名返回错误的 _domainconnect TXT 记录,并随后调用 JSON 到他们自己的服务器以获取 API 端点。通过这样做,他们可以随后在其域名上运行 Domain Connect 并检索密钥。
因此,服务提供商用于 OAuth 的 urlAPI 应按 DNS 提供商维护,而不是发现期间检索的值。
下表描述了在访问令牌请求中必须包含的 POST 参数,除非另有说明。 应通过查询字符串或 post 的正文接受参数。这对于 client_secret 尤其重要,因为通常不赞成通过查询字符串传递密钥,因为各种系统通常会记录 URL。
post 的正文采用 application/json 编码。
属性 | 键 | 描述 |
---|---|---|
授权码/刷新码 |
code/refresh_token |
(必需) 当客户接受授权请求时,在上一步中提供的授权码,或用于后续访问令牌的 refresh_token。 |
重定向 URI |
redirect_uri |
(可选) 如果 redirect_uri 传递给请求授权码,则这是必需的。如果包含,则需要与此步骤中提供的 redirect_uri 相同。 |
授权类型 |
grant_type |
(必需) 请求中代码的类型。通常是字符串 “authorization_code” 或 “refresh_token” |
客户端 ID |
client_id |
(必需) 这是 DNS 提供商在注册期间提供给服务提供商的客户端 ID |
客户端密钥 |
client_secret |
(必需) 在注册期间提供给服务提供商的密钥。通常是必需的,除非是罕见的无密钥 OAuth 情况。 |
成功进行令牌交换后,DNS 提供商将在响应正文中返回 4 个属性的响应。
属性 | 描述 |
---|---|
access_token |
用于发出 API 请求的访问令牌 |
token_type |
始终是字符串 “bearer” |
expires_in |
访问令牌到期前的秒数 |
refresh_token |
当此访问令牌过期时,可用于请求新访问令牌的令牌。 |
状态 | 响应 | 描述 |
---|---|---|
成功 |
2xx |
HTTP 状态代码为 2xx 的响应表示调用成功。响应是上述 JSON。 |
错误 |
4** |
所有其他响应都表示错误。 |
服务提供商拥有访问令牌后,他们可以调用 DNS 提供商的 API,通过应用和(可选)删除授权模板来更改域名上的 DNS。这些模板可以应用于根域名或已授权的根域名的任何子域名。
所有对此 API 的调用都在 API 调用的请求的 Authorization 标头中传递访问令牌。更多详细信息可以在 OAuth 规范中找到,但作为一个示例:
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer mF_9.B5f-4.1JqM
虽然以下调用没有传递密钥的相同安全考虑因素,但建议 urlAPI 来自存储的值,而不是此处发现期间返回的值。
POST
{urlAPI}/v2/domainTemplates/providers/{providerId}/services
/{serviceId}/apply?[properties]
API 的主要功能是将模板应用于客户域名。
虽然 providerId 在授权中已暗示,但它在路径上是为了与同步流程和其他 API 保持一致。如果与授权内容不匹配,则必须返回错误。
将模板应用于域名时,可能会与之前的设置存在冲突。虽然建议在用户授予同意时检测到冲突,但由于 OAuth 是异步的,因此用户可能会引入新的冲突。
虽然 DNS 提供商可以自行决定什么是冲突(请参阅下面的“冲突”部分),但当检测到冲突时,调用此 API 必须返回错误。此错误应以如下所述的格式枚举冲突记录。
由于用户通常不在发生此错误时出现,因此由服务提供商决定如何处理这种情况。一些提供商可能会决定通知用户。其他提供商可能会决定使用 “force” 参数无论如何都应用其模板。此参数将绕过冲突的错误检查,并且在调用后,服务将处于其所需状态。
通过 OAuth 调用以应用模板需要将以下参数发布到上述 URL,除非另有说明。 DNS 提供商必须接受此 post 的查询字符串或正文中的参数。
正文采用 application/json 编码。
属性 | 键 | 描述 |
---|---|---|
域名 |
domain |
(必需) 正在配置的根域名。它必须与令牌中授权的域名匹配。 |
主机 |
host |
(可选) 令牌中授权的根域名的子域名的主机名。如果省略或留空,则模板将应用于根域名。 |
名称/值对 |
* |
(必需) 此模板使用的任何变量字段。此 API 调用的名称部分对应于记录中指定的变量,值部分对应于应用模板时必须使用的值,如实现说明中所述。 |
组 ID |
groupId |
(可选) 指定要应用的模板中的更改组。如果省略,则应用所有更改。这也可能是以逗号分隔的 groupId 列表。 |
强制 |
force |
(可选) 指定必须应用模板,而与域名上可能存在的任何冲突无关。这可以是值 0 或 1。 |
提供商名称 |
providerName |
(可选) 此参数允许调用者为应用模板的 providerName 提供额外的上下文。某些 DNS 提供商可能会使用它来显示有关已应用哪些模板的状态。仅当模板中设置了 “sharedProviderName” 属性时,才允许使用它。 |
服务名称 |
serviceName |
(可选) 此参数允许调用者为应用模板的 serviceName 提供额外的上下文。某些 DNS 提供商可能会使用它来显示有关已应用哪些模板的状态。仅当模板中设置了 “sharedProviderName” 属性时,才允许使用它。 |
实例 ID |
instanceId |
(可选) 仅适用于支持多实例的模板(请参阅 multiInstance 模板属性)。允许 DNS 提供商存储此信息,以便稍后删除一个模板实例。 |
以下是调用示例。在此示例中,考虑了此模板中有两个变量 “IP” 和 “RANDOMTEXT”,它们都需要值。这些变量作为名称/值对传递。
POST
https://connect.dnsprovider.example/v2/domainTemplates/providers/
exampleservice.example/services/template1/apply?IP=192.0.2.42
&RANDOMTEXT=shm%3A1542108821%3AHello&force=1
API 必须验证访问令牌,以及域名属于客户并且由正在呈现的令牌表示。任何变量错误、冲突模板或域名状态问题都会返回;否则将应用模板。
此调用的结果可以包括指示成功或错误的信息。错误将是 400 状态代码,并定义了以下代码。
状态 | 响应 | 描述 |
---|---|---|
成功 |
2xx |
HTTP 状态代码为 204 的响应表示调用成功并且已应用模板。请注意,任何 200 级别的代码都必须被视为成功。 |
错误请求 |
400 |
状态代码为 400 的响应表示服务器无法处理请求,因为它格式错误或有错误。此响应代码旨在用于编程错误。 |
未授权 |
401 |
状态代码为 401 的响应表示调用者未被授权进行此调用。这可能是因为令牌已被吊销或其他访问问题。 |
冲突 |
409 |
这表示调用良好且调用者已授权,但由于模板冲突,无法应用更改。仅当 force 不等于 1 时,才会返回由于冲突导致的错误。 |
错误 |
4xx |
当请求出现问题导致应用模板出现问题时,可能会返回其他 4xx 错误代码;最常见的是帐户出现问题并且需要注意。 |
当返回 409 时,响应正文应包含冲突记录的详细信息。这应该是包含错误代码的 JSON、适合开发人员的消息以及包含冲突记录类型、主机和数据元素的元组数组。
例如:
{
"code": "409",
"message": "Conflicting records",
"records": [
{
"type": "CNAME",
"host": "www",
"data": "@"
},
{
"type": "A",
"host": "@",
"data": "random ip"
}
]
}
在此示例中,服务提供商尝试应用新的托管模板。域名已应用了用于托管的现有服务。
此调用还原从域名应用特定模板。
此调用的实现是可选的。如果不支持,则必须返回 501。
POST
{urlAPI}/v2/domainTemplates/providers/{providerId}/services
/{serviceId}/revert?domain={domain}&host={host}
此 API 允许使用 OAuth 请求从客户域名/主机中删除模板。
URL 中的提供商和服务名称必须与授权期间提供的值匹配。
此调用必须验证模板是否存在并且已由服务提供商应用于域名,否则必须返回警告,指出该调用将无效。
查询字符串示例可能如下所示:
POST
https://connect.dnsprovider.example/v2/domainTemplates/providers
/exampleservice.example/services/template1/revert?domain=example.com
允许的参数:
属性 | 键 | 描述 |
---|---|---|
域名 |
domain |
(必需) 正在配置的根域名。它必须与令牌中授权的域名匹配。 |
主机 |
host |
(可选) 令牌中授权的根域名的子域名的主机名。如果省略或留空,则模板将应用于根域名。 |
实例 ID |
instanceId |
(可选) 仅适用于支持多实例的模板(请参阅 multiInstance 模板属性)。对于存储有关已应用模板信息的 DNS 提供商,允许删除单个模板实例。如果缺少,则应删除模板的所有实例。 |
DNS 提供商应能够通过查询字符串或 POST 的正文(使用 application/json
编码)接受这些参数。
响应代码“成功”、“授权”和“错误”与上述相同,但添加了 501 代码。
如果对模板进行了重大更改,建议创建一个新模板。虽然表面上版本控制看起来很有吸引力,但实际上很少需要它。
对模板的任何更改都需要考虑 DNS 中现有客户的设置,其中一些是通过 Domain Connect 应用的,另一些是手动应用的。因此,进行更改时,它们通常是向后兼容的。
请注意,当模板更改时,确实需要在 DNS 提供商处进行登记。
模板定义的 version field 字段用于在发生此类更改时提高 DNS 提供商和服务提供商之间的透明度。
模板定义为包含以下数据的标准 JSON 数据结构。除非另有说明,否则字段为必需。
数据元素 | 类型 | 键 | 描述 |
---|---|---|---|
服务提供商 ID |
字符串 |
providerId |
(必需) 创建此模板的服务提供商的唯一标识符。这在 URL 中用于标识服务提供商。为确保非协调唯一性,这应该是服务提供商的域名(例如 exampleservice.example)。 |
服务提供商名称 |
字符串 |
providerName |
(必需) 适合显示的服务提供商名称。这可能会在 DNS 提供商同意 UX 上向用户显示。 |
服务 ID |
字符串 |
serviceId |
(必需) 模板的名称或标识符。这在 URL 中用于标识模板。它也用于 OAuth 的范围参数中。它不得包含空格字符,并且必须是 URL 友好的。 |
服务名称 |
字符串 |
serviceName |
(必需) 适合向用户显示的服务名称。这可能会在 DNS 提供商同意 UX 上向用户显示。 |
版本 |
整数 |
version |
(可选) 如果存在,则表示模板的版本,并且应在每次更新模板内容时增加。此值主要用于提高提供商之间的沟通和透明度。 |
徽标 |
字符串 |
logoUrl |
(可选) 代表服务提供商和/或服务的图形徽标,用于任何基于 Web 的流程中。如果存在,则可能会在 DNS 提供商同意 UX 上向用户显示。 |
描述 |
文本 |
description |
(可选) 对此模板尝试执行的操作的文本描述。这旨在帮助开发人员,绝不能向用户显示。 |
变量描述 |
文本 |
variableDescription |
(可选) 对变量是什么的文本描述。这旨在帮助开发人员,绝不能向用户显示。 |
同步阻止 |
布尔值 |
syncBlock |
(可选) 指示必须为此模板禁用同步协议。默认值为 false。 |
共享 |
布尔值 |
shared |
(可选) 此标志已弃用。它以前用于指示模板允许查询字符串上的动态 providerName。它已在规范的 v2.2 中替换为 sharedProviderName 标志。 |
共享提供商名称 |
布尔值 |
sharedProviderName |
(可选) 此标志指示模板允许调用者传入 providerName 的附加信息。此信息应扩充模板中 providerName 的显示。默认值为 false。为了向后兼容不使用规范 V2.2 的 DNS 提供商,建议也设置 shared 标志。 |
共享服务名称 |
布尔值 |
sharedServiceName |
(可选) 此标志指示模板允许调用者传入 serviceName 的附加信息。此信息应扩充模板中 serviceName 的显示。默认值为 false。 |
同步公钥域名 |
字符串 |
syncPubKeyDomain |
(可选) 存在时,指示同步应用模板的调用必须经过数字签名。该值指示用于从 DNS 查询包含用于签名的公钥的 TXT 记录的域名。 |
同步重定向域名 |
字符串 |
syncRedirectDomain |
(可选) 存在时,这是逗号分隔的域名列表,应用同步流程的模板后必须将重定向发送到这些域名。 |
布尔值 |
multiInstance |
(可选) 默认为 False。设置为 True 时,表示模板可以多次应用。这仅影响在 DNS 中维护模板状态的 DNS 提供商。 |
|
警告网络钓鱼 |
布尔值 |
warnPhishing |
(可选) 存在时,这告诉 DNS 提供商,模板可能包含容易受到网络钓鱼攻击的变量,并且提供商无法对请求进行数字签名。设置此标志后,DNS 提供商应向用户显示警告。默认值为 false。 |
需要主机 |
布尔值 |
hostRequired |
(可选) 默认为 false。存在时,这表示模板已编写为仅在同时提供域名和主机时才有效。例如,当完全限定域名上设置 CNAME 时,这将为真。这在很大程度上是信息性的,因为大多数 DNS 提供商已经强制执行此类规则。 |
模板记录 |
模板记录数组 |
records |
(必需) 模板的记录列表。 |
每个模板记录都是一个条目,其中包含类型和几个其他值,具体取决于类型。
这些值中的许多值可以包含变量。有三个内置变量。
-
%host%: 这是从查询字符串传递的主机
-
%domain%: 这是从查询字符串传递的域名
-
%fqdn%: 这是完全限定域名,例如 [host.]domain
@ 符号具有特殊含义,可以在主机/名称字段或 pointsTo/数据字段中单独使用。
对于主机/名称字段,它是值 “%fqdn%.” 的快捷方式。当仅将模板应用于域名时,它表示 “example.com.”。当应用于子域名(主机)时,它表示 “subdomain.example.com.”。
注意:此处的尾随点类似于 bind 表示法,它表示该值是绝对的。如果没有尾随点 “.”,则此字段中的值相对于 [host.]example.com 值。
对于 pointsTo/数据字段,它是 “%fqdn%” 的快捷方式。当仅应用模板到域名时,它表示 “example.com”。当应用于子域名(主机)时,它表示 “subdomain.example.com”。
注意:pointsTo 和数据文件对于这些字段始终是绝对的。
需要注意的是,最佳实践是将变量部分限制为尽可能小的结果 DNS 记录部分。
例如,假设服务提供商要求其用户的 CNAME 值为三个值之一:s01.example.com、s02.example.com 和 s03.example.com。
模板中的值可以简单地包含 %servercluster%,并传入完全限定的字符串。或者,模板中的值可以包含 %var%.example.com,并传入值 01、02 或 03。通过在模板中放置更多固定数据,模板更安全。
每个记录将包含以下元素。
数据元素 | 类型 | 键 | 描述 |
---|---|---|---|
类型 |
枚举 |
type |
(必需) 描述 DNS 中的记录类型或影响 DNS 的操作。 |
type |
(必需) 描述 DNS 中的记录类型或影响 DNS 的操作。 有效值包括:A、AAAA、CNAME、MX、TXT、SRV 或 SPFM。 对于每种类型,都需要其他字段。 |
组 ID |
字符串 |
groupId |
(可选) 此参数标识应用更改时记录所属的组。这不得包含变量。 |
枚举 |
|
essential |
(可选) 此参数指示在与现有模板进行冲突检测期间如何处理记录。 如果 DNS 提供商未在 DNS 中实现已应用的模板状态,则忽略此参数。 Always(默认)- 记录必须与模板一起应用和保留 OnApply - 记录必须应用,但稍后可以删除,而无需删除整个模板 |
主机 |
字符串 |
host |
(必需) A、AAAA、CNAME、NS、TXT 和 MX 值的 host。 此值相对于应用的 host 和域名,除非以 “.” 结尾。 空值或 @ 值表示应用的 host 和域名的根。换句话说,“[host.]example.com.”。 除非绝对必要,否则此值不应包含变量。这将在下面讨论。 |
名称 |
字符串 |
name |
SRV 记录的名称。 此值相对于应用的 host 和域名。空值或 @ 值表示应用的 host 和域名的根。 除非绝对必要,否则此值不应包含变量。这将在下面讨论。 |
字符串 |
|
pointsTo |
A、AAAA、CNAME、NS 和 MX 记录的 pointsTo 位置。 空值或 @ 值表示正在应用的 host 和域名或 [host.]example.com |
TTL |
整数或整数的字符串表示形式 |
ttl |
DNS 中记录的生存时间。对 A、AAAA、CNAME、NS、TXT、MX 和 SRV 记录有效。为了避免模板的操作不可预测性以及下面概述的挑战,除非绝对必要,否则此值不应包含变量。如果包含变量,则必须将变量作为字符串包含在模板定义中以构建有效的 JSON,并且变量必须是唯一的值内容。不得使用前缀、后缀或多个变量。 无论此值是变量还是常量,DNS 提供商都将其理解为 “尽力而为”,并且可能会在运行时或模板登记期间受到本地策略的限制或调整,例如应用 TTL 的特定最小值或最大值或 DNS 提供商支持的 TTL 值枚举。DNS 提供商不应由于值无效而拒绝模板应用,而应选择最接近的支持值或默认值,以避免应用程序流程需要按提供商进行调整。 DNS 提供商可以选择是否支持此字段中的变量。 |
数据 |
字符串 |
data |
DNS 中 TXT 记录的数据。空值或 @ 值表示正在应用的 host 和域名或 [host.]example.com 对于任何未指定的记录类型,此字段包含给定记录的规范表示格式。该表示形式应遵循 [RFC3597] 作为通用或类型特定编码。这绝不能用于 Type 字段中明确列出的任何具有特定数据字段的记录类型。 |
数据 |
字符串 |
rdata |
TXT 冲突匹配模式 |
字符串 |
|
txtConflictMatchingMode |
描述如何检测 TXT 记录上的冲突。可能的值为 None、All 或 Prefix。默认值为 None。请参阅下文。 |
TXT 冲突匹配前缀 |
字符串 |
txtConflictMatchingPrefix |
当 txtConflict-MatchingMode 为 “Prefix” 时,用于检测冲突的前缀。这不得包含变量。请参阅下文。 |
优先级 |
整数或整数的字符串表示形式 |
priority |
MX 或 SRV 记录的优先级。这可以包含变量,但如果包含,则必须将变量作为字符串包含在模板定义中以构建有效的 JSON,并且变量必须是值字段的唯一内容。不得使用前缀、后缀或多个变量。 DNS 提供商可以选择是否支持此字段中的变量。 |
权重 |
整数或整数的字符串表示形式 |
weight |
SRV 记录的权重。这可以包含变量,但如果包含,则必须将变量作为字符串包含在模板定义中以构建有效的 JSON,并且变量必须是值字段的唯一内容。不得使用前缀、后缀或多个变量。 DNS 提供商可以选择是否支持此字段中的变量。 |
端口 |
整数或整数的字符串表示形式 |
port |
SRV 记录的端口。这可以包含变量,但如果包含,则必须将变量作为字符串包含在模板定义中以构建有效的 JSON,并且变量必须是值字段的唯一内容。不得使用前缀、后缀或多个变量。 DNS 提供商可以选择是否支持此字段中的变量。 |
协议 |
字符串 |
protocol |
SRV 记录的协议。 |
服务 |
字符串 |
service |
SRV 记录的符号名称。 |
目标 |
字符串 |
target |
SRV 记录的目标。 |
字符串 |
DNS 提供商可以选择在 DNS 中的记录内维护状态,指示写入记录的模板。其他提供商可以选择不维护此状态。
维护此状态的 DNS 提供商可以为客户提供改进的体验,告知他们已启用的服务。他们还可以更高级地处理冲突。
为了使 DNS 提供商的实施负担合理,Domain Connect 不指定方法。
在授予权限和/或应用 DNS 更改时,披露哪些内容由 DNS 提供商自行决定。这包括披露正在应用的记录和可能被覆盖的记录。
对于正在进行的更改,一个 DNS 提供商可能决定仅告知用户正在启用的服务名称。另一个提供商可能决定显示正在设置的记录。另一个提供商可能会逐步显示两者。
对于冲突检测,一个 DNS 提供商可能会在不发出警告的情况下简单地覆盖已更改的记录。另一个提供商可能会检测到冲突并警告用户将更改的记录。另一个提供商可能会实施逻辑以进一步检测、警告和删除任何与新应用的模板重叠的现有模板(这假定它们是在 DNS 中维护模板状态的 DNS 提供商)。
例如,考虑应用一个模板,该模板在区域中设置两个记录(recordA 和 recordB)。接下来考虑应用第二个模板,该模板与第一个模板重叠(recordB 和 recordC)。如果 DNS 维护模板状态并删除冲突模板,则应用第二个模板将删除第一个模板。应用第二个模板将与 recordB 冲突,并且将删除整个第一个模板。
用户在 DNS 提供商处进行的手动更改也可能具有适当的警告,以防止不必要的更改;可以进行覆盖并删除冲突的模板。
对于同步流程,这发生在用户在场时。
对于异步流程,同意 UX 类似。但是,更改稍后使用 API 和 OAuth 进行。DNS 提供商可以决定检测冲突,并使用正确的响应代码从 API 返回这些冲突,而不应用更改。如果设置了 force 参数,则必须应用更改,而与冲突无关。
最终,披露量和/或冲突检测量由 DNS 提供商自行决定。唯一的要求是,在应用模板后,必须完全应用新记录。
UX 的合理建议集可能包括:
-
同意 UX 应告知客户将启用的服务。如果客户想知道具体信息,DNS 提供商可以向用户提供 “显示详细信息” 链接。这可以向他们显示 DNS 中正在设置的特定记录。
-
如果存在冲突(在模板级别或记录级别),则同意 UX 应警告用户这些冲突。对于模板,这将是将被禁用的服务。对于记录,这将是被删除或覆盖的记录。这可以逐步披露。
DNS 提供商在应用模板之前执行的冲突检测必须考虑每种 DNS 记录类型的具体情况。下面概述的规则确保了 DNS 提供商之间可预测的冲突解决。除非另有说明,否则每条规则都适用于完全相同主机上的记录。
-
CNAME 记录与 TXT、MX、AAAA、A 和现有 CNAME 记录冲突,并且这些类型中的任何其他记录与现有 CNAME 记录冲突。注意:CNAME 记录不能位于区域的根目录。
-
NS 记录与所有其他记录冲突。这包括同一主机的记录,以及任何以 NS 主机结尾的记录。例如,NS 记录 foo 将与任何 foo、www.foo、bar.foo 等冲突。同样,所有其他记录类型都以相同的方式与 NS 记录冲突。
-
MX、SRV 记录始终与相同类型的记录冲突
-
A 和 AAAA 记录与任何其他 A 和/或 AAAA 记录冲突,以避免 IPv4 和 IPv6 指向不同的服务。
-
TXT 记录冲突检测通过查看 txtConflictMatchingMode 参数来处理
-
None:这表示 TXT 记录不与任何其他 TXT 记录冲突。这是默认设置,如果未指定。
-
All:这表示 TXT 记录与任何其他 TXT 记录冲突
-
Prefix:这表示 TXT 记录与任何其他包含以 txtConflictMatchingPrefix 开头的值的 TXT 记录冲突
-
对于在重新应用模板时维护已应用模板状态的 DNS 提供商,还有一个额外的注意事项。
为了避免对用户发出不必要的冲突警告,在正常使用情况下,当重新应用模板时,此类 DNS 提供商应删除先前应用于同一主机的模板。
这可能不适用于所有模板,因为有限的一组模板旨在多次应用。为了促进这一点,模板可以设置 multiInstance 标志。这告诉 DNS 提供商,模板有望多次写入,并且重新应用绝不能删除以前的实例。
此设置仅影响维护已应用模板状态的 DNS 提供商。不维护已应用模板状态的 DNS 提供商必须依赖正常的冲突解决规则,并且此标志无效。
通常,模板指定服务所需的一系列 DNS 记录。在某些情况下,某些记录仅在非常短的时间内需要,并且稍后删除或更改记录(无论是最终用户还是通过应用另一个模板)都不应触发冲突检测。
这可以通过模板中记录的 essential 属性来控制。
同样,此设置仅影响维护已应用模板状态的 DNS 提供商。
对于维护模板状态的 DNS 提供商,单个模板的范围限定为应用于完全限定域名的记录集。这包括在应用时应用的根域名和主机(也称为子域名)。
例如,如果在 domain=example.com&host=sub1 上应用模板,则稍后在 domain=example.com&host=sub2 上应用模板必须被视为不同的模板。如果稍后检测到与 “sub2.example.com” 中设置的记录发生冲突,则只会删除使用此模板设置的记录。
模板记录包含要在区域中设置的记录的主机名(对于 SRV 记录称为名称)。除非后跟尾随 “.”,否则此值必须被视为相对于应用模板时的域名/主机。
考虑类型为 A 的模板记录,其主机值为 “xyz”。当模板应用于 domain=example.com 和空主机值时,应用模板后生成的区域将包含 “xyz” 的 A 记录(或 bind 格式的 “xyz.example.com.”)。
如果相同的模板应用于 domain=example.com 和 host=bar,则区域将包含 “xyz.bar” 的 A 记录(或 bind 格式的 “xyz.bar.example.com.”)。
模板中 host 的 @ 值是空值的占位符。换句话说,当相同的模板应用于 domain=example.com 和 host=bar 时,@ 将指向 “bar.example.com.”。
某些类型的模板记录包含要在区域中设置的 pointsTo 值。对于 CNAME 等记录类型,这可以是完全限定域名。
模板中 pointsTo 字段中的 @ 值是正在应用的域名/主机的完全限定域名的快捷方式。
考虑类型为 CNAME 且 pointsTo 值为 “@” 的模板记录。在应用 domain=example.com 和空主机的模板后,生成的区域中的 pointsTo 值(或相应字段)将为 “example.com”。在应用 domain=example.com 和 host=bar 的模板后,pointsTo 值将为 “bar.example.com”。
模板中 pointsTo 字段中的任何域名都必须被视为完全限定域名而不是相对域名。
虽然模板确实允许在主机或名称字段值中使用变量,但应非常谨慎地使用这些变量。
例如,考虑为站点设置托管。但是,不是将模板应用于域名/主机,而是将主机的名称作为变量放置在模板中。
此类模板可能包含格式如下的 A 记录:
{
"type": "A",
"host": "%var%",
"pointsTo": "192.0.2.2",
"ttl": 1800
}
此模板可以应用于像 example.com 这样的域名,并将 var 设置为 “sub”、“sub1”、“sub2” 等。
此模板的应用将在 “example.com” 的域名级别。这会导致模板的应用/重新应用、冲突检测和模板删除出现问题。
由于此模板将仅应用于域名,因此维护模板状态的 DNS 提供商将在重新应用之前删除模板的先前实例。这意味着应用 var=sub 的此模板将导致 sub.example.com 的 A 记录设置为值 192.0.2.2。稍后,在 “example.com” 上应用 var=sub2 的模板应在设置新模板之前删除旧模板。sub.example.com 将被删除,sub2.example.com 将设置为值 192.0.2.2。
此外,当用户授予异步操作(OAuth)的同意时,确定冲突将是不可能的。这是因为主机将是不确定的。
为了解决此问题,模板的范围限定为域名和主机值。对于同步操作,主机值在 URL 中指定。对于异步操作,权限是针对特定主机值授予的,这些值稍后在应用模板时指定。
注意:有些模板利用 CNAME 或 TXT 记录,其主机值包含某种形式的用户标识,用于验证域名所有权,这些值通常在变量中传递。
为了支持此用例,允许主机名使用变量。但这仅限于这种情况。
为了允许在模板中使用主机名或域名,可以使用 %host% 和 %domain% 的值。还可以使用第三个值 %fqdn%。此值是将主机名和域名与必要的 “.” 组合的结果。
例如,对于查询字符串 “domain=example.com&host=”,模板中的 %fqdn% 将为 “example.com”,对于 “domain=example.com&host=sub1”,模板中的 %fqdn% 将为 “sub1.example.com”。
模板示例:
[{
"type": "CNAME",
"host": "www",
"pointsTo": "@",
"ttl": 1800
},
{
"type": "A",
"host": "@",
"pointsTo": "192.0.2.1",
"ttl": 1800
}]
应用于 domain=example.com 且 host 参数缺失或为空的模板:
www 1800 IN CNAME example.com.
@ 1800 IN A 192.0.2.1
或者
www.example.com. 1800 IN CNAME example.com.
example.com. 1800 IN A 192.0.2.1
应用于 domain=example.com 和 host=bar 的模板:
www.bar 1800 IN CNAME bar.example.com.
bar 1800 IN A 192.0.2.1
或者
www.bar.example.com. 1800 IN CNAME bar.example.com.
bar.example.com. 1800 IN A 192.0.2.1
SPF 代表发件人策略框架,在 [RFC7208] 中指定。它是一个记录,指定授权主机名和/或 IP 地址的列表,邮件可以从这些主机名和/或 IP 地址源自给定域名。
它表现为 TXT 记录。其格式以 v=spf1 开头,后跟要包含/排除的 “规则” 列表。如果规则通过,则允许邮件。如果失败,则移至下一条规则。典型记录可能如下所示:
v=spf1 include:policy.exampleprovider.example -all
这是一个包含两条规则的 SPF 记录。第一条规则指示 SPF 记录 policy.exampleprovider.example 的规则包含在此记录中。第二条规则是全部捕获规则 (_all)。规则的默认修饰符是 pass (+)。其他修饰符是 硬故障(-)、软故障 (~) 和 中性 (?)。
注意:SPF 中的故障并不意味着不会发生传递,但是,根据接收系统的策略,标记为 硬故障 或 软故障 的邮件可能不会被传递或标记为垃圾邮件。
在末尾使用 “all” 非常常见,尽管一些提供商将其标记为 ~(软故障)或 ?(中性)。现实情况是,良好的 SPF 记录是根据附加到域名的服务进行调整的。不仅仅是一个单独的服务。
如果只有一个电子邮件发送服务处于活动状态,则提供商推荐的 SPF 记录就足够了。但是,来自域名的邮件通常可以来自多个不同的服务。
一个非常典型的用例可能是最终用户邮件和电子邮件新闻稿服务。让我们看看为各个服务推荐的 SPF 记录。
Mailer1: v=spf1 include:spf.mailer1.example –all Newsletter1: v=spf1 include:_spf.newsletter.example ~all
所有这些示例都使用 include 语法。这非常常见。在末尾使用 all 很常见,尽管与修饰符通常不一致。
如果客户安装了 Mailer1 和 Newsletter1,则他们的组合 SPF 记录应该是这样的:
v=spf1 include:spf.mailer1.example include:_spf.newsletter.example ~all
我们合并了这两条规则,在本例中选择了限制性最弱的 all 修饰符。
SPF 记录和 Domain Connect 的挑战在于,单个服务可能会推荐 SPF 记录。如果只有一个服务处于活动状态,这将是准确的。但是,当多个服务一起运行时,只有 DNS 提供商才能确定 SPF TXT 记录的有效形状。
解决此问题的一种方法是合并所有相关记录。在最高级别,这意味着从每个记录中获取 “v=spf1” 和 “all” 之间的所有内容并将它们合并在一起,最后以 all 上的硬编码修饰符结尾。为了使 SPF 记录实现其防止恶意电子邮件传递的目的,Domain Connect 建议使用固定的修饰符 “~”,建议降低来自 SPF 中未指定的其他来源的消息的评级。此设置提供了合理的邮件传递保护级别,另一方面,如果存在转发工具,则不会拒绝消息。
@ TXT v=spf1 include:spf.mailer1.example include:_spf.newsletter.exam ple ~all
另一种方法是编写中间记录,并在本地引用这些记录。
r1.example.com. TXT v=spf1 include:spf.mailer1.example ~all r2.example.com. TXT v=spf1 include:_spf.newsletter.example ~all @ TXT v=spf1 include:r1.example.com include:r2.example.com ~all
这两种方法都有优点和缺点。SPF 记录限制为 10 次 DNS 查找,记录长度限制为 255 个字符。因此,根据嵌入的记录,这两种方法都可能具有优势。
实现将留给 DNS 提供商,但为了促进这一点,SPF 记录不得包含在模板中。相反,我们在模板中引入了一种新的伪记录类型,称为 SPFM。它具有以下属性:
- spfRules
-
确定所需的规则,基本上是除了前导 “v=spf1” 和尾随 all 规则之外的所有内容 - 请参阅:SPF 规则
当在模板中添加或删除带有 SPFM 记录的模板时,某些代码需要获取所有已应用模板中所有 SPFM 记录的聚合值以及主机上现有的 SPF TXT 记录,并重新计算生成的 SPF TXT 记录。如果多个来源使用不同的策略指定相同的规则,则 DNS 提供商应将限制性最弱的策略作为结果应用。软故障 应优先于 硬故障,中性 应优先于 软故障。
DNS 提供商还应允许最终用户在合并后修改 SPF 记录。
由于中间的合并步骤,生成的 SPF TXT 记录被视为非必要的(请参阅:非必要记录)。这意味着用户可以决定覆盖最终计算的值或删除整个 SPF 记录。如果 DNS 提供商实施了冲突检测和模板完整性例程,则此操作绝不能导致删除任何相关的冲突模板。
如果现有 TXT 记录使合并操作不可能,则 DNS 提供商必须以与冲突相同的方式处理这种情况,并在 UX 中让最终用户解决它(在同步和异步流程中),或者在异步流程中返回冲突作为错误,除非使用 force=true 参数,从而有效地删除现有记录。
服务提供商应避免完全匹配检查 TXT SPF 记录的内容,因为它可能会受到 DNS 提供商合并策略和用户操作的强烈影响。
请参阅 示例:SPF 记录合并。
公共模板存储库是一个开放访问的位置,服务提供商可以在其中以本规范中指定的格式发布其服务模板。DNS 提供商可以根据自己的登记策略支持所有已发布的模板、仅支持一部分或不支持任何模板(另请参阅:登记注意事项)。
模板格式主要用于 DNS 提供商和服务提供商之间的文档和通信,并且没有用于创建或修改这些对象的编纂端点。相反,Domain Connect 通过 ID 引用模板。
因此,DNS 提供商可以在其内部实现中使用或不使用此格式的模板。通过定义标准模板格式,相信这将使服务提供商更容易跨 DNS 提供商共享其配置。
模板存储库维护在 https://github.com/Domain-Connect/templates 下。
此存储库中的文件名必须全部为小写,包括 providerId 和 serviceId。因此,虽然 providerId 和 serviceId 可以是混合大小写,但当小写时,此存储库中的所有 providerId 和 serviceId 都必须是唯一的。
模板必须根据以下模式命名:providerId.serviceId.json
providerId: example.com
serviceId: WebsiteBuilder
模板文件名: example.com.websitebuilder.json
实施者负责数据完整性,应使用记录类型字段来验证变量输入是否满足每种不同数据类型的标准。
硬编码的主机名由 DNS 提供商负责保护。也就是说,DNS 提供商负责确保主机名不会干扰已知值(如 m. 或 www. 或 mail.)或提供超出本规范范围的关键功能的内部名称。
可以在每个 DNS 提供商的基础上实现模板中记录的其他记录类型和/或扩展。但是,在定义扩展时应注意,以免与其他协议和标准冲突。某些记录名称保留用于 DNS 中诸如 DNSSEC (DNSKEY, RRSIG) [RFC9364] 之类的协议(在注册机构级别)。
在本规范中以开放方式定义这些可选扩展是为了提供一致性。以下是 DNS 提供商/服务提供商可以支持的初始可选扩展。
某些服务提供商希望 CNAME 记录的行为,但在顶点记录中。这将允许在域名的根目录处使用 A 记录,但可以在运行时动态确定。
对于希望支持此功能的 DNS 提供商,建议的记录类型是 APEXCNAME 记录。此记录中包含的其他字段将包括 pointsTo 和 TTL。
在 DNS 中为此类功能定义标准超出了本规范的范围。但是,对于支持此功能的 DNS 提供商,跨 DNS 提供商使用相同的记录类型名称可以实现模板重用。
某些服务提供商希望与 A 记录关联的重定向服务。一个典型的示例是需要将域名(例如 example.com)重定向到 www 变体(www.example.com)的服务。www 通常包含 CNAME。
由于重定向服务的实现通常很简单,因此建议服务提供商自行实现重定向。但是,对于具有重定向服务的 DNS 提供商,支持具有此功能的简单模板可能是理想的。
虽然从技术上讲,重定向服务不是 DNS 中的 “记录”,但在支持此可选功能时,建议应使用两种新的记录类型来实现这一点。
REDIR301 和 REDIR302 将分别实现 301 和 302 重定向。与此记录关联的将是名为 “target” 的单个字段,其中包含重定向的目标 URL。
一些服务提供商要求支持更新与域名关联的注册机构处的域名服务器记录的功能。
在实现此功能时,应提供两个记录。NS1 和 NS2,每个记录都包含一个 pointsTo 参数。
需要注意的是,域名服务器更新将要求 DNS 提供商是注册商。情况并非总是如此。
此功能再次被认为是可选的,并由 DNS 提供商自行决定是否支持。
{
"providerId": "example.com",
"providerName": "Example Web Hosting",
"serviceId": "hosting",
"serviceName": "Wordpress by example.com",
"version": 1,
"logoUrl": "https://www.example.com/images/billthecat.jpg",
"description": "This connects your domain to our web hosting",
"records": [
{
"type": "A",
"groupId": "service",
"host": "www",
"pointsTo": "%var1%",
"ttl": 600
},
{
"type": "A",
"groupId": "service",
"host": "m",
"pointsTo": "%var2%",
"ttl": 600
},
{
"type": "CNAME",
"groupId": "service",
"host": "webmail",
"pointsTo": "%var3%",
"ttl": 600
},
{
"type": "TXT",
"groupId": "verification",
"host": "example",
"ttl": 600,
"data": "%var4%"
}
]
}
考虑一个用于设置单个主机记录的模板。模板的记录部分将具有单个类型为 “A” 的记录,并且可能具有以下值:
[{
"type": "A",
"host": "www",
"pointsTo": "192.0.2.1",
"ttl": 600
}]
这将没有变量替换,并且将此模板应用于域名将仅将主机名 “www” 设置为 IP 地址 “192.0.2.1”。
在用于从变量设置单个主机记录的模板的情况下,模板将具有单个类型为 “A” 的记录,并且可能具有以下值:
[{
"type": "A",
"host": "@",
"pointsTo": "198.51.100.%srv%",
"ttl": 600
}]
带有键/值对的查询字符串
srv=2
将导致将此模板应用于域名,以将顶点 A 记录的主机名设置为 IP 地址 “198.51.100.2”,TTL 为 600。
此示例演示如何在 CAA 记录示例中包含一组未指定的记录类型:
[
{
"type": "CAA",
"host": "@",
"data": "0 issue \"ca1.example.net\"",
"ttl": 1800
},
{
"type": "CAA",
"host": "@",
"data": "0 issuewild \"ca2.example.\"",
"ttl": 1800
}
]
这将没有变量替换,并且将此模板应用于域名将添加 2 个 CAA 记录。
考虑应用模板之前的 DNS 区域:
$ORIGIN example.com.
@ 3600 IN SOA ns11.example.net. support.example.net. 2017050817 7200
1800 1209600 3600
@ 3600 IN NS ns11.example.net.
@ 3600 IN NS ns12.example.net.
@ 3600 IN A 192.0.2.1
@ 3600 IN A 192.0.2.2
@ 3600 IN AAAA 2001:db8:1234:0000:0000:0000:0000:0000
@ 3600 IN AAAA 2001:db8:1234:0000:0000:0000:0000:0001
@ 3600 IN MX 10 mx1.example.net.
@ 3600 IN MX 10 mx2.example.net.
@ 3600 IN TXT "v=spf1 a include:spf.example.org ~all"
www 3600 IN CNAME other.host.example.
现在应用以下模板:
[
{
"type":"A",
"host":"@",
"pointsTo":"203.0.113.2",
"ttl":"1800"
},
{
"type":"A",
"host":"www",
"pointsTo":"203.0.113.2",
"ttl":"1800"
},
{
"type":"SPFM",
"host":"@",
"spfRules":"a include:spf.hoster.example"
}
]
应用模板后应生成以下 DNS 区域:
$ORIGIN example.com.
@ 3600 IN SOA ns11.example.net. support.example.net. 2017050920 7200
1800 1209600 3600
@ 3600 IN NS ns11.example.net.
@ 3600 IN NS ns12.example.net.
@ 1800 IN A 203.0.113.2
@ 3600 IN MX 10 mx1.example.net.
@ 3600 IN MX 10 mx2.example.net.
@ 1800 IN TXT "v=spf1 a include:spf.example.org include:spf.hoster.ex
ample ~all"
www 1800 IN A 203.0.113.2
考虑应用模板之前的 DNS 区域:
$ORIGIN example.com.
@ 3600 IN SOA ns11.example.net. support.example.net. 2017050817 7200
1800 1209600 3600
@ 3600 IN NS ns11.example.net.
@ 3600 IN NS ns12.example.net.
现在应用以下邮件服务模板:
[
{
"type":"MX",
"host":"@",
"priority": "10",
"pointsTo":"mx1.example.net",
"ttl":"1800"
},
{
"type":"MX",
"host":"www",
"priority": "10",
"pointsTo":"mx2.example.net",
"ttl":"1800"
},
{
"type":"SPFM",
"host":"@",
"spfRules":"a include:spf.example.net"
}
]
DNS 区域中的预期结果
$ORIGIN example.com.
@ 3600 IN SOA ns11.example.net. support.example.net. 2017050817 7200
1800 1209600 3600
@ 3600 IN NS ns11.example.net.
@ 3600 IN NS ns12.example.net.
@ 3600 IN MX 10 mx1.example.net.
@ 3600 IN MX 10 mx2.example.net.
@ 3600 IN TXT "v=spf1 a include:spf.example.net ~all"
在下一步中,应用以下新闻稿服务模板:
[
{
"type":"SPFM",
"host":"@",
"spfRules":"include:_spf.newsletter.example"
}
]
DNS 区域中的预期结果
$ORIGIN example.com.
@ 3600 IN SOA ns11.example.net. support.example.net. 2017050817 7200
1800 1209600 3600
@ 3600 IN NS ns11.example.net.
@ 3600 IN NS ns12.example.net.
@ 3600 IN MX 10 mx1.example.net.
@ 3600 IN MX 10 mx2.example.net.
@ 3600 IN TXT "v=spf1 a include:spf.example.net include:_spf.newslett
er.
example ~all"