PowerShell and NAPTR DNS records. Help!


reading time 6 min

I can’t figure out how to Add- or Remove- an NAPTR record using PowerShell’s DnsServer module. Can you?

I’m not PowerShell expert, nor am I an expert on how Microsoft’s DNS server works.

However, I can tell you that PowerShell lets you list NAPTR records, but the “RecordData” field appears blank:

1
2
3
4
5
> Get-DnsServerResourceRecord -rrtype naptr -zonename my.example.com -name "9.3.5.8.enum"

HostName                  RecordType Type       Timestamp            TimeToLive      RecordData
--------                  ---------- ----       ---------            ----------      ----------
9.3.5.8.enum              NAPTR      35         0                    01:00:00

If you get that field, you get a hex-encoded version of the wire format of the NAPTR record data:

1
2
3
4
5
6
7
8
> $records = Get-DnsServerResourceRecord -rrtype naptr -zonename my.example.com -name "9.3.5.8.enum" ; $records[0].RecordData|SELECT *


Data                  : 01000A000155074532552B7369701B215E2E2A24217369703A383939394031302E3139392E392E39392100
PSComputerName        :
CimClass              : root/Microsoft/Windows/DNS:DnsServerResourceRecordUnknown
CimInstanceProperties : {Data}
CimSystemProperties   : Microsoft.Management.Infrastructure.CimSystemProperties

(That record was created using the Windows GUI.)

The hex string is pretty obviously what will go in the DNS packet. You can decode it and see the ascii strings.

NOTE: That hex string was slightly redacted.

My challenge to you:

  1. Create an NAPTR record using Add-DnsServerResourceRecord (or anything in that family), but specify the RecordData as the individual fields, not a hex string.
  2. Remove- or Get- an NAPTR record using Remove-DnsServerResourceRecord (or equivalent), but specify all the fields such that exactly 0 or 1 records are returned.

Why am I doing this?

Why am I doing this? Because dnscontrol needs to support NAPTR better so that SIP phone systems can be managed better.

Why the Get/Remove requirement that it specify exactly one record? Because I only want to remove one record and there may be multiple matches if the DNS record is not specified completely.

Why would there be multiple matches? Because DNS permits the same label to have many DNS records as long as they are unique.

For example, it is possible to have multiple SRV records on the same label:

1
2
3
4
5
6
7
> Get-DnsServerResourceRecord -rrtype srv -ZoneName my.example.com -name _ldap._tcp

HostName                  RecordType Type       Timestamp            TimeToLive      RecordData
--------                  ---------- ----       ---------            ----------      ----------
_ldap._tcp                SRV        33         0                    00:10:00        [0][100][389][REDACTED.example.com.]
_ldap._tcp                SRV        33         0                    00:10:00        [0][100][389][REDACTED.foo.com.]
_ldap._tcp                SRV        33         0                    00:10:00        [0][100][389][REDACTED.example2.com.]

Here’s how you would remove it:

1
2
> Remove-DnsServerResourceRecord -WhatIf -RRType SRV -ZoneName "my.example.com" -Name "_ldap._tcp" -RecordData 0,100,389,"redacted.example.com."
What if: Removing DNS resource record _ldap._tcp of type SRV from zone my.example.com on TOMDEV server.

Notice that I specified the [0][100][389][REDACTED.example.com.] string in the comma-separated format that PowerShell requires (no spaces, quotes around any non-numeric data). This unambiguously specifies the SRV record.

I can find no equivalent for NAPTR.

Can you?

Rant

Why the heck does everything telephony-related suck when it comes to the internet? Does every SIP phone system in the world get configured using the GUI? Does the telephony world suffer through this and not use any kind of automated setup, infrastructure as code?

Sadly I know the answer to these questions. (Hint: Netheads vs Bellheads and AT&T Fails At Internet.)

Update: 2020-12-29

Win: I’ve successfully decoded and encoded the hex strings in Go. Since a Go program is generating the PowerShell commands, this is fine. See https://github.com/StackExchange/dnscontrol/pull/1009/files

Lose: PowerShell is ignorant of NAPTR records.

I figured… what if I just recycle the hex dump?

1
2
> Add-DnsServerResourceRecord -zonename example.com -Name foo -Type 35 -RecordData "01000A000155074532552B7369701B215E2E2A24217369703A323038304031302E3131302E322E31302100"
Add-DnsServerResourceRecord: Record type number 35 is not an unknown type, represents a NAPTR record. Known record types cannot be added using the unknown records parameter set. Windows DNS server understands the format of this record type and it must be added using the known record parameter sets.

It seems that the PS module just doesn’t know that NAPTR exists. I’ve tried -Naptr and --Rrtype NAPTR. No good.

Others have found this problem:

Maybe I should create the object from scratch?

Update: 2020-12-30:

My conclusion is that the Remove-DnsServerResourceRecord command simply doesn’t have command-line flags that do the right thing. That’s ok, if I can Get-DnsServerResourceRecord and match the record, then I can use Remove-DnsServerResourceRecord and specify that object with the -InputObject to remove it. Right?

Wrong.

This works for A records but not NAPTR!

Here’s my repo case:

I manually added an “A” and a few “NAPTR” records using the GUI. Let’s see if we can delete them:

1
2
3
4
5
6
7
8
9
> Get-DnsServerResourceRecord -ZoneName "example.com"

HostName                  RecordType Type       Timestamp            TimeToLive      RecordData
--------                  ---------- ----       ---------            ----------      ----------
@                         SOA        6          0                    01:00:00        [26347][tomdev.][hostmaster.]
@                         NAPTR      35         0                    01:00:00
mya                       A          1          0                    01:00:00        1.2.3.4
testdata                  NAPTR      35         0                    01:00:00
testdata                  NAPTR      35         0                    01:00:00

First let’s delete the “A” record:

1
2
3
4
> $OldObj = Get-DnsServerResourceRecord -ZoneName "example.com" -Name "mya" -RRType A | 
    Where-Object {$_.HostName -eq "mya" 
        -and $_.RecordData.IPv4Address -eq "1.2.3.4"} ; 
    if($OldObj.Length -ne 1){ throw "Error, matched 0 or > 1 records" }

That found the object. Let’s remove it:

1
2
3
4
5
6
> Remove-DnsServerResourceRecord  -InputObject $OldObj  -ZoneName "example.com" -Confirm -Force

Confirm
Are you sure you want to perform this action?
Removing DNS resource record mya of type A from zone example.com on TOMDEV server.
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): y

Worked as expected! Now let’s try that with an NAPTR record:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
> $OldObj = Get-DnsServerResourceRecord -ZoneName "example.com" -Name "testdata" -RRType naptr |
    Where-Object {$_.HostName -eq "testdata" 
        -and $_.RecordData.Data -eq "020003000155074532552B7369701D215E282E2A2924217369703A5C5C314031302E3131302E322E3130216000"} ; 
        if($OldObj.Length -ne 1){ throw "Error, matched 0 or > 1 records" }
> $OldObj

HostName                  RecordType Type       Timestamp            TimeToLive      RecordData
--------                  ---------- ----       ---------            ----------      ----------
testdata                  NAPTR      35         0                    01:00:00

> $OldObj.RecordData.Data
020003000155074532552B7369701D215E282E2A2924217369703A5C5C314031302E3131302E322E3130216000
> Remove-DnsServerResourceRecord -InputObject $OldObj -ZoneName "example.com"
Remove-DnsServerResourceRecord: InputObject for resource record has an invalid value. Failed to remove the resource record on TOMDEV server. Please check extended error for additional details.
PS C:\Users\tlimoncelli\git\dnscontrol\integrationTest> get-error

OriginInfo            :
Exception             :
    Type            : Microsoft.Management.Infrastructure.CimException
    NativeErrorCode : InvalidParameter
    ErrorData       : MSFT_WmiError
    MessageId       : WIN32 13
    ErrorSource     : TOMDEV
    StatusCode      : 4
    TargetSite      :
        Name          : ProcessNativeCallback
        DeclaringType : Microsoft.Management.Infrastructure.Internal.Operations.CimAsyncObserverProxyBase`1[T]
        MemberType    : Method
        Module        : Microsoft.Management.Infrastructure.dll
    StackTrace      :
   at Microsoft.Management.Infrastructure.Internal.Operations.CimAsyncObserverProxyBase`1.ProcessNativeCallback(OperationCallbackProcessingContext callbackProcessingContext, T currentItem, Boolean
moreResults, MiResult operationResult, String errorMessage, InstanceHandle errorDetailsHandle)
    Message         : InputObject for resource record has an invalid value. Failed to remove the resource record on TOMDEV server. Please check extended error for additional details.
    Source          : Microsoft.Management.Infrastructure
    HResult         : -2146233088
TargetObject          : PS_DnsServerResourceRecord
CategoryInfo          : InvalidData: (TOMDEV:root/Microsoft/Wind…erverResourceRecord) [Remove-DnsServerResourceRecord], CimException
FullyQualifiedErrorId : WIN32 13,Remove-DnsServerResourceRecord
InvocationInfo        :
    MyCommand        : Remove-DnsServerResourceRecord
    ScriptLineNumber : 1
    OffsetInLine     : 1
    HistoryId        : 426
    Line             : Remove-DnsServerResourceRecord -InputObject $OldObj -ZoneName "example.com"
    PositionMessage  : At line:1 char:1
                       + Remove-DnsServerResourceRecord -InputObject $OldObj -ZoneName "exampl …
                       + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    InvocationName   : Remove-DnsServerResourceRecord
    CommandOrigin    : Internal
ScriptStackTrace      : at Remove-DnsServerResourceRecord<End>, <No file>: line 4550
                        at <ScriptBlock>, <No file>: line 1

Nope! Looks like this causes some kind of internal error.

Sadly I don’t know enough WMI to understand what’s going on.

Anyone have suggestions?




Tom Limoncelli

Tom Limoncelli

Recent Posts


  1. The Greater Fool
  2. Our House
  3. Niklaus Wirth has passed away at age 89
  4. Apple Vision… thoughts
  5. Removing Dead Code From DNSControl

Archive


Categories


Tags


I agree that this website may store my data to personalize my journey in accordance with their Terms & conditions

Powered by Hugo | Theme - YesThatTheme © 2017 - 2024 Tom Limoncelli