如何将 DNS 资源记录更新从 Linux 发送到仅接受安全更新的 Windows Active Directory DNS 区域?

如何将 DNS 资源记录更新从 Linux 发送到仅接受安全更新的 Windows Active Directory DNS 区域?

我的公司有一个现有的 Windows AD DNS 区域,我不直接管理它(但我知道管理它的人)。该区域将接受动态更新,但更新必须是“安全的”。我有一台 Linux 机器(它运行 IPAM 系统),我想从它向 AD 发送任意 DNS 更新。如何做到这一点?

答案1

首先,有几个假设:

  • 您的 AD DNS 服务器已投入运行。它已配置一个区域,只要更新是安全的,该区域就允许更新。
  • 您有一些 AD 凭据,具有更新区域的权限。我认为该DNSAdmin组可能默认被授予权限(不确定),因此让您的用户成为该组的成员。最好使用具有最低权限的服务帐户。
  • 您有一个可以发送更新的 Linux 机器。您的版本nsupdate支持-g启用 GSS-TSIG 的标志。

让我们开始吧。我们需要做一些设置。

首先,我们需要获取并配置 Kerberos 5 身份验证后端。

  1. 如果你使用的是 Ubuntu,可以使用 安装所需的工具apt install sssd-krb5 krb5-user。如果你使用的是其他发行版,请查看评论以查看是否有人指出了你需要哪些软件包。
  2. 接下来,我们需要添加 AD 的信息。这不是 DNS 信息,而是有关如何获取票证的 Kerberos 信息。使用您最喜欢的文本编辑器打开文件krb5.conf;对于 Ubuntu 来说就是/etc/krb5.conf
  3. 在该[libdefaults]部分下,添加如下条目是明智之举:default_realm = CORP.EXAMPLE.LOCAL。不知道为什么,但 Realm 似乎需要大写。
  4. 在该[realms]部分下,我们需要添加 AD 域和服务器(域控制器)信息。请遵循此模板。再次将领域名称设为大写。
[realms]
CORP.EXAMPLE.LOCAL = {
  kdc = ms-dc-01.corp.example.local:88
  kdc = ms-dc-02.corp.example.local:88
  admin_server = ms-dc-01.corp.example.local
  default_domain = corp.example.local
}

好的,让我们看看它是否有效。

接下来,我们将尝试通过身份验证从 AD 获取 Kerberos 票证。

  1. 运行命令。希望它会提示您输入密码。希望仅此而已。kinit [email protected]
  2. 无法kinit接受密码?请尝试启用跟踪输出,如下所示:KRB5_TRACE=/dev/stdout kinit ...。请注意,有时用户名可能会导致大小写问题。
  3. 看看你是否有票。运行命令klist。希望你能看到类似这样的内容。如果没有,请后退一步并尝试读取跟踪输出。
Valid starting       Expires              Service principal
05/19/2023 17:22:42  05/20/2023 03:22:42  krbtgt/[email protected]
  1. 暂停一下。我们所做的是使用我们的凭证向 AD 请求 Kerberos 票证。如果票证被授予,它将被放入客户端的缓存中。当您使用时,您正在查看缓存klist。您可能不应该将其留在缓存中超过您需要的时间,因为 root Linux 用户可以读取和使用缓存。您可以使用命令终止票证kdestroy
  2. 使用该票证,让我们看看是否可以向 DNS 服务器发送 DNS 更新。运行该nsupdate命令。这将为您提供一个新的命令提示符,等待有关您要执行的操作的指令。输入以下命令:
gsstsig
server chicago-dns-14.corp.example.local
zone corp.example.local.
update add my-new-test-record.corp.example.local. 3600 A 1.1.1.1
show
send
quit

注意,有些服务器不需要 TTL 参数,有些则需要。耸耸肩。

  1. 使用您最喜欢的 DNS 实用程序询问 DNS 服务器是否有该记录:host -ta my-new-test-record.corp.example.local chicago-dns-14.corp.example.local
  2. 现在,您可以以几乎相同的方式删除该记录。nsupdate再次运行。输入以下命令:
gsstsig
server chicago-dns-14.corp.example.local
zone corp.example.local.
update delete new-server-test-record.corp.example.local. A 1.1.1.1
send

请注意,删除时不需要包含 TTL。

  1. 运行kdestroy以从缓存中删除您的 Kerberos 票证。

太棒了,下一步是什么?

好的,以上就是手动操作的方法。现在,让我们将密码放入 keytab 文件中,这样我们就不必每次都输入密码,而且密码也不会保存在明文文件中供其他用户阅读。

  1. 运行ktutil命令。输入以下命令:
addent -password -p [email protected] -k 0 -f
  1. 希望您能收到输入密码的提示。然后继续:
wkt username.keytab
quit
  1. 好的,希望您现在有一个 keytab 文件。此文件包含您的密码的大多数安全版本。我不知道具体是怎么回事,但它以某种方式加密了。
  2. 现在我们有了 keytab 文件,我们可以kinit使用一些新参数运行,这样我们就可以避免输入密码:kinit -kt username.keytab [email protected]
  3. 运行 aklist以查看您是否获得了票。
  4. 运行kdestroy以撕毁您的票。

好的,现在让我们看看是否可以将其变成一个真正复杂的单行代码。

  1. 运行命令:
kinit -kt username.keytab [email protected] && echo "gsstsig
server chicago-dns-14.corp.example.local
zone corp.example.local.
update delete new-server-test-record.corp.example.local. 3600 A 1.1.1.1
send" |nsupdate && kdestroy

我知道这看起来不止一行,但是第一行的引号会让 Bash 等待,直到你关闭引号。

你能编写这个脚本吗?

当然

#!/bin/bash

if [ $# == 3 ]; then
 if [ $1 == "add" ] ; then
  kinit -kt DnsAdministrator.keytab [email protected]
  echo "gsstsig
server chicago-dns-14.corp.example.local
zone corp.example.local.
update $1 $2.corp.example.local. 7200 A $3
send" |nsupdate
  kdestroy
 elif [ $1 == "delete" ] || [ $1 == "del" ] ; then
  kinit -kt DnsAdministrator.keytab [email protected]
  echo "gsstsig
server chicago-dns-14.corp.example.local
zone corp.example.local.
update $1 $2.corp.example.local. A $3
send" |nsupdate
  kdestroy
 else
  echo "<action> must be either add or delete."
 fi
else
 echo "There must be precisely 3 parameters: <action>, <record-name> and <ip-address>"
fi

然后像这样使用它:

./my-dns-script.sh add my-new-test-record 1.1.1.1

或者

./my-dns-script.sh delete my-new-test-record 1.1.1.1

相关内容