skip to Main Content

I need to parse a windows dns zone file to convert it in another format.
I use Powershell and need to extract values. Here is an example of what the file look like:

;
;  Zone NS records
;

@                       NS  servweb.test.com.
servweb.test.com.  A    31.233.196.98
@                       NS  servweb3.test.com.
servweb3.test.com. A    91.133.157.25

;
;  Zone records
;

@                       A   85.233.152.58
@                       MX  10  mail.factory.com.
@                       MX  20  mx2.factory.com.
@                       MX  50  servmail3.test.fr.
@                       TXT ( "v=spf1 include:spf.sendinblue.com mx ~all" )
@                       TXT ( "MS=ms94956023" )
_dmarc                  TXT ( "v=DMARC1; p=none; sp=none; rua=mailto:[email protected]!10m; ruf=mailto:[email protected]!10m; rf=afrf; pct=100; ri=86400" )
mail._domainkey         TXT ( "k=rsa;p=MIGfMA0GCSqNADCBiQKBgQDeMVIzrCa3T14JsNY0viLQBwXsa7shBD6TrBkswsFUToPyMRWC9tbR/5ey0nRBH0ZVxp+lsmTxid2Y2z+FApQ6raISgXE" )
_autodiscover._tcp      SRV 0 0 443 owa.factory.com.
_sipfederationtls._tcp  SRV 100 1 5061  sipfed.online.lync.com.
_sip._tls               SRV 100 1 443   sipdir.online.lync.com.
appli                   A   193.233.140.115
cpanel                  A   85.33.152.58
cpcalendars             A   85.33.152.58
cpcontacts              A   85.33.152.58
ftp                     CNAME   factory.com.
lyncdiscover            CNAME   webdir.online.lync.com.
mail                    A   90.115.33.93

I think I can use capture groups to extract values and use it to build my file but I’m stuck…

I tried (S+)s+([A-Za-zs]+)[ t](?=d+) but it breaks after a few lines.

If you have any clue you’ll be welcome 🙂

Edit: I found a quick and dirty way that fit my need but I’m sure it can be improve 🙂

$domains = Import-Csv -Path C:tempexport_domaines_termines.csv -Delimiter ";"
foreach ($domain in $domains){


    $ndd = $domain.Name
    $nomfichier = "$ndd.dns"
    $records = get-content -Path "C:tempdnsdns$nomfichier" | Where-Object { $_ -notmatch '^;' -and $_.trim() -ne "" } | Select-Object -Skip 10
    $fichiergandi = New-Item -Path "C:tempdns$nomfichier.txt" -ItemType File -Force -Confirm:$false


    foreach ($record in $records){
        $type = $prio = $value = $donnees = $name = $null
        $match = Select-String '(S+)s+([A-Za-zs]+)[ t](S+)' -InputObject $record
        $type = $match.matches.groups[2].value

            if ($type -like "MX") {
                $match = Select-String '(S+)s+([A-Za-zs]+)[ t](S+)[ t](S+)' -InputObject $record
                $name = $match.matches.groups[1].value
                $prio = $match.matches.groups[3].value
                $MX = $match.matches.groups[4].value
                "$name 10800 IN $type $prio $MX" | Out-File -FilePath $fichiergandi -Append
            }
            elseif ($type -like "TXT") {
                $match = Select-String '(S+)s+([A-Za-zs]+)[ t](S+)[ t](([^)]+))' -InputObject $record
                $name = $match.matches.groups[1].value
                $donnees = ($match.matches.groups[4].value).Trim()
                "$name 10800 IN $type $donnees" | Out-File -FilePath $fichiergandi -Append
            }

            elseif ($type -like "SRV") {
                $match = Select-String '(S+)s+([A-Za-zs]+)[ t](S+)s(S+)s(S+)s(S+)' -InputObject $record
                $name = $match.matches.groups[1].value
                $prio = $match.matches.groups[3].value
                $poids = $match.matches.groups[4].value
                $port = $match.matches.groups[5].value
                $cible = $match.matches.groups[6].value
                "$name 10800 IN $type $prio $poids $port $cible" | Out-File -FilePath $fichiergandi -Append
            }

            else {
                $name = $match.matches.groups[1].value
                $donnees = $match.matches.groups[3].value
                "$name 10800 IN $type $donnees" | Out-File -FilePath $fichiergandi -Append
            }
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    Your solution seems more optimized, I need to extract all records and build a file to import in another dns software. The format of the file need to be :

    @ 10800 IN A 85.236.152.133
    @ 10800 IN MX 10 mail.example.com.
    @ 10800 IN MX 20 mx2.example.com.
    @ 10800 IN MX 50 servmail3.example.fr.
    @ 10800 IN TXT "Sendinblue-code:022f2cda7e5e0c6d945db"
    @ 10800 IN TXT "v=spf1 include:spf.sendinblue.com mx ~all"
    @ 10800 IN TXT "MS=ms94956023"
    _autodiscover._tcp 10800 IN SRV 0 0 443 owa.example.com.
    _sipfederationtls._tcp 10800 IN SRV 100 1 5061 sipfed.online.lync.com.
    _sip._tls 10800 IN SRV 100 1 443 sipdir.online.lync.com.
    

    Each record need to be separated by one space. I think special records like TXT or SRV need to be processed differently for example remove parenthesis but I will try to use your base. If you have a little time to comment your code it will definitively help. Thank you.


  2. I would use a switch statement to process the file line by line. Here is my guess at what would be a useful output.

    $output = switch -Regex ($zonefile){
        '^;' {
            if($_ -match ';s+(?<Category>.+)'){
                $category = $Matches.category
            }
        }
        '^[^;s]' {
            $_ -replace '(?<=^[^s]*)s+','|' -replace '(?<=^[^s]*)s+','|' |
                ConvertFrom-Csv -Delimiter "|" -Header Name, Type, Value |
                    Select-Object -Property @{n='Category';e={$category}},*
        }
    }
    
    # Format-Table is for viewing results only!! 
    $output | Format-Table
    
    # process the results however you desire
    $output | Export-Csv ...
    $output | Out-GridView
    

    Here is the sample output
    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search