DynDNS53 is an implementation for AWS of the dyndns2 protocol used by many DDNS providers such as Dyn and Google Domains. It runs as a AWS Lambda function, via an API Gateway endpoint, and updates records in Route 53 zones. When setup properly, the only service you need to run locally is your favourite DDNS update client. This implementation was tested with ddclient
.
A
record for your host's FQDN in the hosted zone.The Lambda function will require an execution role, and that role needs permission to both read and modify Route 53 records. The included iam_policy
file will create a security policy allowing your Lambda function to get/set resource record sets in your hosted zone, as well as to create log groups and streams and to put log events to CloudWatch.
iam_policy
file, replacing <MY_ZONE_ID>
with your Route 53 zone ID.dyndns53_policy
) and paste the contents of iam_policy
. Ensure that you have replaced <MY_ZONE_ID>
with your Route 53 zone ID.dyndns53_execution
).The Lambda function parses the client update request and performs the update in Route 53.
conf
dictionary in dyndns53.py
with your desired configuration, replacing <username>
, <password>
, <host.example.com.>
, and <MY_ZONE_ID>
. You can also optionally modify the TTL value used when updating the host's record.
conf = {
'<username>:<password>': {
'hosts': {
'<host.example.com.>': { # FQDN (don't forget trailing `.`)
'aws_region': 'us-west-2', # not actually important
'zone_id': '<MY_ZONE_ID>', # same zone ID as in `iam_polcy`
'record': {
'ttl': 60, # TTL in seconds; should be low for DDNS
'type': 'A', # only `A` records supported right now
},
'last_update': None, # not currently used
}
}
}
}
You can have multiple <username>:<password>
combinations, and multiple <host.example.com>
entries per user. The dyndns2
protocol uses HTTP basic authentication, so I recommend using randomly generated username/password strings. Note that API Gateway will only respond to HTTPS, so this information is never sent over the internet in the clear.
dyndns53_lambda
) and set the runtime to Python 2.7.dyndns53.py
into the "Lambda function code" box, making sure you have updated your conf
appropriately.lambda_function.lambda_handler
.You can configure a test event to do trial runs of your Lambda function. Modify the included sample_lambda_event.json
file, replacing <host.example.com>
with your DDNS host name, <MY_HOST_IP>
with the IPv4 address you wish to set, <MY_SOURCE_IP>
with the IPv4 of the client (if you don't specify myip
in the request, the source IP is used to set the record), and <MY_BASE64_USER:PASS>
with the Base-64 encoding of <username>:<password>
.
If it works, you should see the following result:
{
"status": 200,
"response": "good <MY_HOST_IP>"
}
The JSON event structure above is the way API Gateway interfaces with AWS Lambda. Now you will configure API Gateway to deliver HTTP requests to the Lambda function as events in this format. Likewise, JSON responses like the above will be converted by API Gateway into HTTP responses to the client. This interface is where the bulk of the frustration lies when working with Lambda and API Gateway.
This also happens to be the most tedious part of setting up DynDNS53.
DynDNS53
) and click "Create API".dyndns2
-compatible resource:
/
in the resource list.nic
for the resource name, which should auto-populate the path./nic
in the resource list and repeat the above steps, using update
for the resource name./nic/update
resource.GET
method for the /nic/update
resource:
/nic/update
in the resource list.dyndns53_lambda
).GET
method under /nic/update
in the resource list and click on "Method Request".hostname
, myip
, and offline
.Authorization
.GET
method under /nic/update
in the resource list and click on "Integration Request".application/json
(note: you have to explicitly type it in, even though it is already pre-populated in grey).api_mapping_template
file in the template box and click "Save".GET
method under /nic/update
in the resource list and click on "Method Response".200
row and change the content type to text/plain
.500
, and click the grey checkmark to create a method response type for generic server errors.500
row and click "Add Response Model".text/plain
and select "Empty" from the drop-down, then click the grey check mark.400
, 401
, 403
, and 404
.GET
method under /nic/update
in the resource list and click on "Integration Response".application/json
and populate the template with:
$input.path('$.response')
.*"status"\s*:\s*500.*
500
from the "Method response status" drop-down list.application/json
.$util.parseJson($input.path('$.errorMessage')).response
400
, 401
, 403
, and 404
.POST
method on the /nic/update
resource and repeat all of the above steps so that it behaves identically to the GET
method. This is only required for DDNS clients that use the POST
method with the dyndns2
protocol.Now that we have configured the API, we need to deploy it to get an access URL.
/
from the resource list.v1
; note that this will be part of your URL).Your API should now be deployed and accessible at the invoke URL you recorded above. You can now configure your client.
If you have a Ubiquiti EdgeRouter, you can use the built-in dynamic DNS functionality, which uses ddclient
to perform the actual updates. Use the following commands in configure
mode, replacing fields between <
and >
with appropriate values for your configuration.
edit service dns dynamic
set service dyndns host-name <host.example.com>
set service dyndns login <username>
set service dyndns password <password>
set service dyndns server <endpoint>.execute-api.<region>.amazonaws.com/<stage>
commit
top
The version of ddclient
shipped with EdgeMax 1.8.0 firmware does not include support for the googledomains
protocol, which is a subset of the dyndns2
protocol. The DynDNS53 API more closely resembles the googledomains
protocol than the full dyndns2
protocol.
See the LICENSE file for license rights and limitations (MIT).