Skip to content

Instantly share code, notes, and snippets.

@Shonke
Last active October 15, 2020 11:23
Show Gist options
  • Save Shonke/0d332e5fda0a57aef9b0b356187b87d5 to your computer and use it in GitHub Desktop.
Save Shonke/0d332e5fda0a57aef9b0b356187b87d5 to your computer and use it in GitHub Desktop.
cloudflareDDNS-PowerShell
Param(
[Parameter(Mandatory = $true)] [string] $Token,
[Parameter(Mandatory = $true)] [string] $Zone,
[Parameter(Mandatory = $false)] [string] $RecordNameV4,
[Parameter(Mandatory = $false)] [string] $RecordNameV6
)
# add Scheduled Task
# At computer startup
# Every 2 hours
# When connecting to the network
# Program/script:
# C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command "& 'C:\srv\ddns_cf.ps1' -Token 9U.... -Zone 019... -RecordNameV4 xxx.xxx.com -RecordNameV6 xxx.xxx.com"
# TTL in seconds (1=auto)
$RECORD_TTL="1"
$DATE=Get-Date -Format g
$CF_URI = 'https://api.cloudflare.com/client/v4/zones'
$CF_HEADER = @{"Content-Type" = "application/json"; "Authorization" = "Bearer $Token"}
# [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
function Write-Log {
Param ($Text)
Write-Host ($DATE + ", " + $Text)
}
function Get-CF-Record {
Param (
[Parameter(Mandatory = $true)] [string] $RecordType,
[Parameter(Mandatory = $true)] [string] $RecordName
)
$Uri = "${CF_URI}/${Zone}/dns_records?name=${RecordName}&type=${RecordType}"
try {
$Response = Invoke-RestMethod -Uri $Uri -Headers $CF_HEADER
return $Response.result
} catch {
$Message = "ERROR on " + $RecordName + " Response: " + $_
Write-Log $Message
}
}
function Invoke-CF-Record {
Param (
[Parameter(Mandatory = $true)] [string] $Zone,
[Parameter(Mandatory = $true)] [string] $RecordName,
[Parameter(Mandatory = $true)] [string] $RecordType,
[Parameter(Mandatory = $false)] [string] $RecordId,
[Parameter(Mandatory = $true)] [string] $IP
)
$Uri = "${CF_URI}/${Zone}/dns_records"
$Method = "POST"
if ($RecordId) {
$Uri = "${CF_URI}/${Zone}/dns_records/${RecordId}"
$Method = "PUT"
}
$Body = @{"id" = $Zone; "type" = $RecordType; "name" = $RecordName; "content" = $IP; "ttl" = $RECORD_TTL; "proxied" = $FALSE} | ConvertTo-Json
try {
$Response = Invoke-RestMethod -Method $Method -Uri $Uri -Headers $CF_HEADER -Body $Body
} catch {
$Message = "ERROR on " + $RecordName + " Response: " + $_
Write-Log $Message
}
}
function Invoke-CF-IP {
Param (
[Parameter(Mandatory = $true)] [string] $Zone,
[Parameter(Mandatory = $true)] [string] $RecordType,
[Parameter(Mandatory = $true)] [string] $RecordName,
[Parameter(Mandatory = $true)] [string] $IP
)
$record = Get-CF-Record -RecordType A -RecordName $RecordName
if ($record) {
if (-Not ($IP -eq $record.content)) {
try {
Invoke-CF-Record -Zone $Zone -RecordName $RecordName -RecordType $RecordType -RecordId $record.id -IP $IP
} catch {
Write-Log "Update Record ${RecordType} fail"
}
}
} else {
try {
Invoke-CF-Record -Zone $Zone -RecordName $RecordName -RecordType $RecordType -IP $IP
} catch {
Write-Log "Update Record ${RecordType} fail"
}
}
}
function Get-Public-IP {
Write-Log "Check IP Address"
$linkIpList = Get-NetIPAddress -AddressState Preferred -PrefixOrigin Dhcp,RouterAdvertisement
$linkIpv4List = $linkIpList |? -m AddressFamily IPv4
$linkIpv6List = $linkIpList |? -m AddressFamily IPv6 |? -m SuffixOrigin Link
if ($linkIpv4List) { $linkIpv4 = $linkIpv4List.IPAddress }
if ($linkIpv6List) { $linkIpv6 = $linkIpv6List.IPAddress }
Write-Log ("Device Link IPv4 Address: " + $linkIpv4)
Write-Log ("Device Link IPv6 Address: " + $linkIpv6)
try {
$ip = Invoke-RestMethod "https://api.ipify.org"
$publicIpv4 = $ip.Trim()
Write-Log ("Device Public IPv4 Address: " + $publicIpv4)
} catch {
Write-Log "Get Public Ipv4 fail"
}
return { "v4" = $publicIpv4; "v6" = $linkIpv6 }
}
$ip = Get-Public-IP
# update
if ($RecordNameV4) { Invoke-CF-IP -Zone $Zone -RecordType A -RecordName $RecordNameV4 -IP $ip.v4 }
if ($RecordNameV6) { Invoke-CF-IP -Zone $Zone -RecordType AAAA -RecordName $RecordNameV6 -IP $ip.v6 }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment