Dynamic DNS updates with Azure function app

Recently my dyn.com account run out and I was looking for a new solution. Well there are many Dynamic DNS services, but I wanted a to build something myself with my own domain.

My firewall is pfSense which supports many Dynamic DNS services, but can also use a custom service. This custom service just calls an URL with options.

This brought me the idea that I could use an Azure Function App with a webhook that updates my Azure DNS record.

For this to work you need:

  • A firewall (or something else) which supports custom dns updates
  • Azure Active Directory
  • Azure DNS

Here is how I built it:

Create a user for the DNS updates

In Azure Active Directory add a new user with the dirctory role "user".
Then go to your subscription and add a new permission with the role "DNS Zone Contributor" and select your newly created user.

Create Azure Function App

Go to the Azure Marketplace and create a new Function App.

Choose an unique App name, your subscription, a new or existing Resource Group, Consumption Plan as Hosting Plan, the location you prefer and a new or existing storage account.

When the function app has been deployed, add a new function and choose to create your custom function. Change the language to PowerShell, choose "HttpTrigger-Powershell" and set a name for your function.

Add Variables

Go to the platform features of your function app and open application settings. Scroll down to the variables and add the credentials of your DNS update user as variables.

Add Code

Add the following code to your function app.

if ($req_query_ipaddr)  
{
    $newIpAddress = $req_query_ipaddr 
}

if ($newIpAddress)  
{

    $user = $env:AzureDns_AccountName
    $password = ($env:AzureDns_AccountPassword) | ConvertTo-SecureString -AsPlainText -Force
    $Credentials = New-Object -typeName System.Management.Automation.PSCredential($user, $password)

    $recordName = "<record name>"
    $zoneName = "<dns zone name>"
    $resourceGroupName = "<resource group name>"

    Login-AzureRmAccount -Credential $Credentials
    $recordSet = Get-AzureRmDnsRecordSet -name $recordName -RecordType A -ZoneName $zoneName -ResourceGroupName $resourceGroupName
    $recordSet.Records[0].Ipv4Address = $newIpAddress
    Set-AzureRmDnsRecordSet -RecordSet $recordSet

    Out-File -Encoding Ascii -FilePath $res -inputObject "Changed IP to $newIpAddress"
}

Replace the values in <>:

  • record name
  • dns zone name
  • resource group name

Test the function app

You can test your function app when you click on Test on the right side. Add the query ipaddr and a test address.

Get the function URL

Click on "Get function URL" and copy the URL for the key "default(Function key)".

Cofigure pfSense

Now that we have a working function app, you can implement it in pfSense or any other firewall that allows custom dns updates.
Open the Dynamic DNS settings and add a new service. Choose the Service type custom. Add "&ipaddr=%IP%" to your function app URL, so you have something like this:
https://xyz.azurewebsites.net/api/updateDns?code=a0IR2B1PKe9noRTFXMBdlljcWeZ4vel8heRRa0fa/Dbhd4FDebferW==&ipaddr=%IP%

Insert this url in the field Update URL and click on Save&Force Update.

Your DNS record should now be set to your IP address.