简体   繁体   English

更改 Windows 服务器 DNS 和 PowerShell 中子域记录的 TTL

[英]Change TTL for subdomain records in Windows Server DNS with PowerShell

I am trying to bulk edit DNS TTL in Windows Server DNS using PowerShell. What I really can't wrap my head around is the absence of any FQDN in Record Objects I get from Get-DnsServerResourceRecord .我正在尝试使用 PowerShell 在 Windows 服务器 DNS 中批量编辑 DNS TTL。我真正无法理解的是我从Get-DnsServerResourceRecord获得的记录对象中没有任何 FQDN。

My DNS setup has a primary zone and many subdomains.我的 DNS 设置有一个主区域和许多子域。

primaryzone.tld
├── sub1
│  ├── record1
│  ├── record2
│  └── subsub1
│     ├── (same as parent)
│     ├── record1.1
│     └── record2.1
├── sub2
└── sub3

As there is no possibility to recurse with Get-DnsServerResourceRecord I have to loop over the subdomains, which I can not gather programatically, to get all records, not just the ones on the root-level of the zone:由于无法使用Get-DnsServerResourceRecord进行递归,我必须遍历无法以编程方式收集的子域,以获取所有记录,而不仅仅是区域根级别的记录:

$DNSServer = "dc.company.tld"
$Zone = "primaryzone.tld"
$ChildZone = "sub1"
$SubDomains = @("","subsub1")
ForEach ($SubDomain in $SubDomains){
    if ( $SubDomain -ne "" ) {
        $FullDomain = "$($SubDomain).$($ChildZone)"
    }
    else {
        $FullDomain = $ChildZone
    } 
    Get-DnsServerResourceRecord -ComputerName $DNSServer -ZoneName $Zone -Name "$($FullDomain)" 

Is this really supposed to be that way?这真的应该是那样吗?

If I now want to change TTL for all records under subsub1 I try it like this:如果我现在想更改subsub1下所有记录的 TTL,我会这样尝试:

 Get-DnsServerResourceRecord -ComputerName $DNSServer -ZoneName $Zone -Name "$($FullDomain)"  |
    ForEach-Object{
            $newRecord = $_.Clone()
            $newRecord.TimeToLive = $ttl
            Set-DnsServerResourceRecord -ComputerName $DNSServer -NewInputObject $newRecord -OldInputObject $_ -ZoneName $Zone
    } 

Which works for the subsub1 (same as parent) record, that has a HostName property of subsub1.sub1 thus giving a full path inside the primaryzone.tld .它适用于subsub1 (same as parent)记录,它具有primaryzone.tldHostName属性,因此在subsub1.sub1中提供完整路径。 Whereas the record1.1 has a HostName of record1.1 stripping it of any information regarding its position in the tree.record1.1HostName名是record1.1 ,它在树中剥离了有关其 position 的任何信息。 This results in this error:这会导致此错误:

Set-DnsServerResourceRecord : Resource record in OldInputObject not found in primaryzone.tld zone on dc.company.tld server.
At C:\Users\me\Desktop\dns_ttl.ps1:24 char:13
+             Set-DnsServerResourceRecord -ComputerName $DNSServer -NewInputObject ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (dc.company.tld:root/Microsoft/...rResourceRecord) [Set-DnsServerResourceRecord], CimException
    + FullyQualifiedErrorId : WIN32 9714,Set-DnsServerResourceRecord

I interpret this as the Set-DnsServerResourceRecord not finding the OldInputObject record because it has no clue where to look, except in the root-level of the zone.我将此解释为Set-DnsServerResourceRecord未找到OldInputObject记录,因为它不知道在哪里查找,除了区域的根级别。

Why can I specify -Name subdomain for Get-DnsServerResourceRecord but when writing it back with Set-DnsServerResourceRecord it does not take a -Name argument?为什么我可以为Get-DnsServerResourceRecord指定-Name subdomain ,但在使用Set-DnsServerResourceRecord将其写回时它不采用-Name参数? Why don't record objects not contain any info on their absolute (FQDN) position in the zone?为什么不记录对象在区域中不包含有关其绝对 (FQDN) position 的任何信息?

How can something so simple be so hard?这么简单的事情怎么会这么难呢?

EDIT:编辑:

I changed my script according to the suggestions by @Cpt.Whale我根据@Cpt.Whale 的建议更改了我的脚本

$DNSServer = "dc.company.tld"
$TargetZone = "primary.tld"
$TTL = [System.TimeSpan]::FromMinutes(1)
$SubDomain = "sub.primary.tld" 

$Zones = Get-DnsServerZone -ComputerName $DNSServer | Where {
    $_.ZoneType -eq 'Primary' -and 
    $_.IsReverseLookupZone -eq $false -and
    $_.ZoneName -ne 'TrustAnchors' -and
    $_.ZoneName -eq $TargetZone
}


Foreach ($DnsZone in $Zones) {
  # Get all records in zone by not specifying -Name:
  $Records = $DnsZone | Get-DnsServerResourceRecord -ComputerName $DNSServer
  $Records | Foreach { 
    if ($_.HostName -match "$SubDomain$") {
        if ($_.TimeToLive -ne $TTL) {
            # This weird copy is due to awkward CIM references
            $oldRecord = $_
            $newRecord = $_.Clone()
            $newRecord.TimeToLive = $TTL

            # Update the TTL on the existing record:
            Set-DnsServerResourceRecord -ComputerName $DNSServer -Old $oldRecord -New $newRecord -ZoneName $DnsZone.ZoneName
            # Report changes
            "{0,-50} TTL changed from {1,12} to {2,12}" -f $_.HostName, $_.TimeToLive, $TTL
        }
     }
  }
}

With this I get full HostName , but still the Error I described above有了这个我得到了完整的HostName ,但仍然是我上面描述的错误

the DNS record-type cim object doesn't have a ZoneName property, but it does keep the subdomain - it's part of the HostName of the record. DNS 记录类型 cim object 没有ZoneName属性,但它确实保留了子域 - 它是记录的HostName名的一部分。 DNS barely cares about subdomains at all unless they are a separate zone. DNS 几乎不关心子域,除非它们是一个单独的区域。

Something to start with is double-checking whether you've actually got only one zone:首先要仔细检查您是否实际上只有一个区域:

$zones = Get-DnsServerZone -ComputerName $DNSServer | Where {
    $_.ZoneType -eq 'Primary' -and 
    $_.IsReverseLookupZone -eq $false -and
    $_.ZoneName -ne 'TrustAnchors'
}
$zones

Then, for example:然后,例如:

$TTL = [System.TimeSpan]::FromHours(2)  ## example TTL

Foreach ($DnsZone in $Zones) {
  # Get all records in zone by not specifying -Name:
  $records = $DnsZone | Get-DnsServerResourceRecord -ComputerName $DNSServer
  $records | Foreach { 
    # This weird copy is due to awkward CIM references
    $old = $_
    $new = $_.Clone()
      $new.TimeToLive = $TTL
    # Update the TTL on the existing record:
    Set-DnsServerResourceRecord -ComputerName $DNSServer -Old $old -New $new -ZoneName $DnsZone.ZoneName
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM