Назад | Перейти на главную страницу

использование (windows) PowerShell для выполнения динамического обновления DNS с TSIG на сервере BIND9

Я запускаю DNS-серверы BIND9 и разрешаю динамическое обновление DNS от моих клиентов с помощью ключа TSIG.

Один из моих клиентов использует только среду Windows и, следовательно, PowerShell для запуска скриптов. Он хочет использовать PowerShell для отправки динамических обновлений на мои серверы.

Сделать это для тестирования из оболочки Linux очень просто: используйте nsupdate.

из: https://www.freeipa.org/page/Howto/DNS_updates_and_zone_transfers_with_TSIG

Клиент

Для nsupdate из пакета bind-utils вы должны либо использовать опцию -y алгоритм: keyname: keyvalue, либо опцию -k keyfilename. Например.

$ nsupdate -y hmac-sha512:keyname:keyvalue

или

$ nsupdate -k Kkeyname.+165+0316.private

затем сделайте свое обновление:

из https://linux.die.net/man/8/nsupdate:

# nsupdate
> update delete oldhost.example.com A
> update add newhost.example.com 86400 A 172.16.1.1
> send

Чтобы сделать обновление из Powershell без TSIG ... довольно просто ... я думаю ?: используйте командлет (например) Add-DnsServerResourceRecordA

Add-DnsServerResourceRecordA -Name "host23" -ZoneName "contoso.com" - AllowUpdateAny -IPv4Address "172.18.99.23" -TimeToLive 01:00:00

После просмотра документации я не вижу никаких ссылок на подписи транзакций или использование ключа TSIG.

Как отправить динамическое обновление с помощью ключа TISG на сервер BIND9 из Powershell?

Это очень сложно найти пример. Большинство примеров, которые я могу найти, используют PowerShell для отправки обновлений через API, который затем (возможно) выполняет какое-то развертывание или динамическое обновление внутри черного ящика. Я хочу просто создать обновление DDNS и отправить его с помощью PowerShell.

Им нужно будет загрузить nsupdate из BIND (https://www.isc.org/downloads/). Можно вызвать nsupdate с хоста PowerShell.

Решение для тех, у кого нет статического IP-адреса и нужно динамически обновлять IP-адрес для зоны DNS и обратных записей DNS PTR.

            $Server = "your server"; $Hostname = "mail"; $Zonename = "your zone"; 
            $MZone = $Hostname + "." + $Zonename
            <# No need to edit below unless you have to change some internal component #>

            $oldobj = get-dnsserverresourcerecord -ComputerName $Server -name $Hostname -zonename $zonename -rrtype "A"
            $newobj = get-dnsserverresourcerecord -ComputerName $Server -name $Hostname -zonename $zonename -rrtype "A"
            $ip =  (Invoke-WebRequest ifconfig.me/ip).Content.Trim()   
            $oip = $oldobj.recorddata.Ipv4address.IpAddressToString
            $oipSplit = $oip.Split("."); $oipr = $oipSplit[2] + "." + $oipSplit[1] + "." + $oipSplit[0] + ".in-addr.arpa"
            $ipSplit = $ip.Split("."); $ipr = $ipSplit[2] + "." + $ipSplit[1] + "." + $ipSplit[0] + ".in-addr.arpa"
            $newobj.recorddata.ipv4address=[System.Net.IPAddress]::parse($ip)
            if ($oip -ne $ip) {
                Set-dnsserverresourcerecord -ComputerName $Server -newinputobject $newobj -oldinputobject $oldobj -zonename $zonename -passthru
                echo "updated A record"
            }
            $oiprZ = Resolve-DnsName -Name $oipr -Server $Server; $oiprR = 0;
            if ($oiprZ.count -gt 0) {
                $oiprR = get-dnsserverresourcerecord -ComputerName $Server -ZoneName $oipr -rrtype "PTR"  -Name $oipSplit[3] | Select-Object HostName, @{Name='RecordData';Expression={$MZone}} 
                if ($oiprR -ne 0 -And $oiprR -ne $null -and -not ($oiprR[0].HostName -eq $ipSplit[3] -and $oiprR[0].RecordData -eq $MZone -and  $oipr -eq $ipr )  ){
                    Remove-DnsServerResourceRecord -ComputerName $Server -ZoneName $oipr -rrtype "PTR" -Name $oipSplit[3] -RecordData $MZone -Force
                    echo "removing existing ptr record"
                    echo $oiprR
                    echo "removed existing ptr record"
                }
                $oiprR =get-dnsserverresourcerecord -ComputerName $Server -ZoneName $oipr -rrtype "PTR"
                if (((($oiprR) -eq $null) -or (($oiprR).Count  -eq 0)) -And $oipr -ne $ipr )  {
                    Remove-DnsServerZone  -ComputerName $Server $oipr -PassThru -Verbose -Force
                    echo "Removing RDNS Zone"
                    echo $oiprZ
                    echo "Removing RDNS Zone"

                }
            }


            $ipNID = $ipSplit[0] + "." + $ipSplit[1] + "." + $ipSplit[2] + ".0/24"
            $iprZ = Resolve-DnsName -Name $ipr -Server $Server; $iprR = 0;
            if ($iprZ.count -gt 0) {
                $iprR = get-dnsserverresourcerecord -ComputerName $Server -ZoneName $ipr -rrtype "PTR"  -Name $ipSplit[3] | Select-Object HostName, @{Name='RecordData';Expression={$MZone}} 
                if ($iprR -eq $null ){
                Add-DnsServerResourceRecordPtr  -ComputerName $Server  -Name $ipSplit[3] -ZoneName $ipr -AllowUpdateAny -TimeToLive 01:00:00 -AgeRecord -PtrDomainName $MZone
                    echo "adding ptr record"
                    echo $iprR
                    echo "added ptr record"
                }
                else
                {

                }
            }
            if ($iprZ.count -eq 0) {
                Add-DnsServerPrimaryZone  -ComputerName $Server -DynamicUpdate Secure -NetworkId $ipNID -ReplicationScope Domain
                Add-DnsServerResourceRecordPtr  -ComputerName $Server  -Name $ipSplit[3] -ZoneName $ipr -AllowUpdateAny -TimeToLive 01:00:00 -AgeRecord -PtrDomainName $MZone
            }

Вот сценарий, который будет создавать и отправлять запросы DDNS, если предоставлен файл tsig. Убедитесь, что разрешения NTFS установлены для предотвращения доступа неавторизованных пользователей (включая других администраторов) к этому файлу.

Это предполагает, что вы установили nsupdate.exe и связанную с ним dll в C: \ windows \ system32, но его можно изменить для других путей.

Я приветствую любые запросы на включение. https://github.com/ACiDGRiM/UsefulScripts/blob/master/Update-DNS.ps1

Param (
    [String]$KeyPath = "C:\Windows\System32\drivers\etc\windows-update-client.txt",
    [String]$NSScriptPath = "$env:Temp\nsupdate.txt",
    [String]$NSUpdatePath = "$env:SystemRoot\System32"
)

begin {
    #Gather status of system IP Addresses, DNS Servers, and domains
    $IPAddresses = Get-NetIPAddress | Where-Object -FilterScript { ($_.InterfaceAlias -like "Ethernet*" -or $_.InterfaceAlias -like "Wi-Fi*") -and $_.IPAddress -notlike "fe*"}
    $DNSServers = Get-DnsClientServerAddress | Where-Object -FilterScript { $_.InterfaceAlias -like "Ethernet*" -or $_.InterfaceAlias -like "Wi-Fi*"}
    $DNSClient = Get-DnsClient | Where-Object -FilterScript { $_.InterfaceAlias -like "Ethernet*" -or $_.InterfaceAlias -like "Wi-Fi*"}
}

process {
    [array]$RequestOutput = @()
    #Parse network status into simplified objects
    foreach ( $if in $IPAddresses ) {
        $requesthash = @{
            IPAddress = @{Address = $if.IPAddress;AddressFamily = $if.AddressFamily}
            Zone = $DNSClient | Where-Object -FilterScript { $_.InterfaceAlias -eq $if.InterfaceAlias } | Select-Object -ExpandProperty "ConnectionSpecificSuffix" -First 1
            Servers = $DnsServers | Where-Object -FilterScript { $_.InterfaceAlias -eq $if.InterfaceAlias } | Select-Object -ExpandProperty "ServerAddresses"
        }
        $RequestObj = New-Object -TypeName psobject -Property $requesthash
        $RequestOutput += $RequestObj 

    }

    #Condense zones from multiple interfaces
    [array]$UniqueZones = ($RequestOutput.Zone|Sort-Object -Unique)
    #Combine IPv6 and IPv4 addresses into a single object property for each zone
    [array]$CombinedOutput = @()
    for ($i=0;$i -lt $UniqueZones.count;$i++) {
        $Combinedhash = @{
            Addresses = $RequestOutput | Where-Object -FilterScript {$_.Zone -eq $UniqueZones[$i]} | Select-Object -ExpandProperty "IPAddress"
            Servers = $RequestOutput | Where-Object -FilterScript {$_.Zone -eq $UniqueZones[$i]} | Select-Object -ExpandProperty "Servers" | Sort-Object -Unique
            Zone = $UniqueZones[$i]
        }
        $CombinedObj = New-Object -TypeName psobject -Property $Combinedhash
        $CombinedOutput += $CombinedObj 
    }

    foreach ( $o in $CombinedOutput ) {
        foreach ( $s in $o.Servers ) {
            $CurrentRecords = Resolve-DnsName $env:COMPUTERNAME`.$($o.Zone) -Server $s -Type "A_AAAA" -DnsOnly -DnssecOK -QuickTimeout -ErrorAction "SilentlyContinue" | Select-Object -ExpandProperty "IPAddress" -ErrorAction "SilentlyContinue"
            if ( $CurrentRecords ) {
                $CurrentState = Compare-Object $IPAddresses.IPAddress $CurrentRecords -ErrorAction "SilentlyContinue"
            } else {
                $CurrentState = $true
            }

            if ( $CurrentState ) {
                $script += "server $s
"
                foreach ( $a in $o.Addresses ) {
                    if ( $a.AddressFamily -eq "IPv4" ) {
                        $PTR = $a.Address -replace '^(\d+)\.(\d+)\.\d+\.(\d+)$','$3.$2.$1.in-addr.arpa.'
                    } else {
                        $PTR = (([char[]][BitConverter]::ToString(([IPAddress]$a.Address).GetAddressBytes())-ne'-')[31..0]-join".")+'.ip6.arpa.'
                    }
                    $script += "update delete $env:COMPUTERNAME.$($o.Zone). $(if($a.AddressFamily -eq "IPv4"){"A"}else{"AAAA"})

update add $env:COMPUTERNAME.$($o.Zone). 60 $(if($a.AddressFamily -eq "IPv4"){"A"}else{"AAAA"}) $($a.Address)

update delete $PTR PTR

update add $PTR 60 PTR $env:COMPUTERNAME.$($o.Zone).


"
                }
            }

        }
    }
}

end {
    $script | Out-File -FilePath $NSScriptPath -Encoding "ascii" -Force
    Start-Process -FilePath (Join-Path -Path $NSUpdatePath -ChildPath "nsupdate.exe") -ArgumentList "-d -k `"$KeyPath`" `"$NSScriptPath`"" -Wait -NoNewWindow -RedirectStandardError "$env:TEMP\nsstderr" -RedirectStandardOutput "$env:TEMP\nsstdout" -WorkingDirectory $NSUpdatePath | Out-Null

}