Resource icon

Tutorial DDNS with AWS Lambda and Route53

Currently reading
Tutorial DDNS with AWS Lambda and Route53

Richard submitted a new resource:

DDNS with AWS Lambda and Route53 - Steps and sample code to setup DDNS with AWS Lambda and Route53

Step 1: Create a new Lambda function
Login to AWS
Go to: Services > Lambda
Click “Create function”
Select “Author from scratch”
Fill in the “Function name” field with whatever name you like
Select Node.js 10.x from “Runtime”
View attachment 351
Click “Create function”.

Step 1.1: Add a Trigger
In the “Designer” component, select “Add trigger”
Under “Select a trigger”, select “API Gateway” (it should be the first in the list).
Under...

Read more about this resource...
 
Is the free tier sufficient? I am sure Lambdas are covered up to millions of calls, but is Route53 going to cost?
I am running a VPS with my own dyndns services - which bases on a simple container that applies the changes to the DNS-API of my provider. Though, the lamda version is way more sexy :)
 
but is Route53 going to cost?
It currently costs $0.50 per "Hosted Zone" per month. In other words, per domain per month, but you can sub-domain until your heart's content at no extra cost. I don't think Lambda is even worth trying to calculate, but that said, the only unknown here is how Synology's DDNS service actually works, and how many requests it's going to make (can't imagine it's more than one per hour, max).

Though, the lamda version is way more sexy :)
I really like it because I already use AWS, but it might be more hassle than it's worth for most people. The tutorial makes it look harder than it is though, because I wanted to detail every single step, just to make it fool-poof. It should only take 10 minutes once you get started.
 
This is fantastic, but I can't get it to work... I've been thinking about this for ages!
DS says
1572633108051.png

If I call the API endpoint in a browser I get:

1572633297878.png

Is there a way I can easily/successfully test or troubleshoot the API?


Thanks,

Declan
 
Hi,

Where you say "“Failed to connect to the server. Please check the network connection of the server.”, this is a misleading error and a known bug", I've worked out what's wrong.

Referring to Interpret Response - No-IP which has the response values.

If you change

JavaScript:
            const response = {
                statusCode: 200,
                body: 'Record Set!',
            };

to be

JavaScript:
            const response = {
                statusCode: 200,
                body: 'good',
            };

You should get a success. You can also change

JavaScript:
        const response = {
            statusCode: 401,
            body: 'Say who now?',
        };

to be


JavaScript:
        const response = {
            statusCode: 200,
            body: 'badauth',
        };

if you like.

Hope these help with the errors!

Regards.
 
Good question, never tested. I couldn't find any documentation which discussed what the statusCode should be so I made the assumption that whoever wrote the original spec was of the "it was a successful request (so 200), but bad data (so 'error' in the body).
 
I think 401 (Unauthorized) is accurate then, pending an official line on what they've written as a handler - some APIs follow HTTP spec more pedantically than others.

I'll test the 200 'good' solution after work some evening.

What version DSM are you using, btw? The original error I mention was introduced quite recently.

Thanks.
 
Checked.

Invalidated my password and ran a test.

With a 200 response and 'badauth' body DSM reports 'Authentication failed'. So I'm happy with keeping a 200 response.

The other thing I've done is added a replacement for the word 'wildcard' with '*'

JavaScript:
event.queryStringParameters.hostname.replace('wildcard', '*')

Which lets me setup a wildcard route (I'm never going to have a machine called wildcard!).

All this might be coming across as faults with your original code. Please don't take it that way. I couldn't/wouldn't have got this far without your initial tutorial! So, since I don't think I ever said it; thanks :)
 
The other thing I've done is added a replacement for the word 'wildcard' with '*'

That's a useful comment, certainly some people will want to create sub-domains, but for simplicity I think I'll leave it out from the original tutorial.

All this might be coming across as faults with your original code. Please don't take it that way. I couldn't/wouldn't have got this far without your initial tutorial! So, since I don't think I ever said it; thanks :)

No at all. Glad someone is using it. Two things I love are DSM and AWS so the more these worlds collide, the better. Keep the comments coming. Might stick it into a CloudFormation or TerraForm script in future - it'd be nice to integrate a bunch of other services, too. Writing out manual steps in a tutorial is a bit tedious...
 
That's great, thanks for sharing. I'll update the tutorial later.

Can I just check, you suggest returning a code 200 with text 'badauth' for an error, does the DSM DDNS app handle this gracefully?



Thanks,
Rich
Hi,

Where you say "“Failed to connect to the server. Please check the network connection of the server.”, this is a misleading error and a known bug", I've worked out what's wrong.

Referring to Interpret Response - No-IP which has the response values.

If you change

JavaScript:
            const response = {
                statusCode: 200,
                body: 'Record Set!',
            };

to be

JavaScript:
            const response = {
                statusCode: 200,
                body: 'good',
            };

You should get a success. You can also change

JavaScript:
        const response = {
            statusCode: 401,
            body: 'Say who now?',
        };

to be


JavaScript:
        const response = {
            statusCode: 200,
            body: 'badauth',
        };

if you like.

Hope these help with the errors!

Regards.
I am not sure what I am doing wrong but I have 3 sub-domains and I'd like to update them all using this but I am not familiar with code enough to know what I should do to enable me to do this?
 
I just updated the source code, so it runs on the latest NodeJs 18x, suggested by AWS. and here is the index.mjs:

Code:
import { Route53 } from "@aws-sdk/client-route-53"

const route53 = new Route53();

const USERNAME = 'YOUR_USERNAME';
const PASSWORD = 'YOUR_PASSWORD';
const ROUTE53_COMMENT = 'My Synology Sub-Domain';
const HOSTED_ZONE_ID = 'YOUR_ZONE_ID';

export async function handler(event) {

    if (event.queryStringParameters.username === USERNAME &&
    event.queryStringParameters.password === PASSWORD){

        var params = {
            ChangeBatch: {
                Changes: [
                    {
                    Action: "UPSERT",
                    ResourceRecordSet: {
                    Name: event.queryStringParameters.hostname,
                    ResourceRecords: [
                        {
                        Value: event.queryStringParameters.ip
                        }
                    ],
                    TTL: 60,
                    Type: "A"
                    }
                }
                ],
                Comment: ROUTE53_COMMENT
            },
            HostedZoneId: HOSTED_ZONE_ID
        };

        return route53.changeResourceRecordSets(params)
        .then(res =>{
            console.log('Record Set!');
            const response = {
                statusCode: 200,
                body: 'Record Set!',
            };
            return response;
        });

    } else {
        console.log('Say who now?');
        const response = {
            statusCode: 401,
            body: 'Say who now?',
        };
        return response;
    }
};
 
Hello, I understand this was an old thread, but wondering if someone can respond. I have followed this setup to connect my AWS registered domain to my synology NAS but still I am not able to make it work.
 
I am not sure what you mean by " have followed this setup to connect my AWS registered domain to my synology NAS but still I am not able to make it work."

You setup a domain and hosted zone in route53, and a lambda to update an entry in the r53 hosted zone. The lambda exposes an api endpoint, which your Synology dndns client just calls to update the entry.

I am afraid you will need to be way more specific that "but still IAM not able to make it work", unless of course you just want to share that it's not working for you, without actually looking for help.

Have you checked the Lamba logs in CloudWatch?
 
I am not sure what you mean by " have followed this setup to connect my AWS registered domain to my synology NAS but still I am not able to make it work."

You setup a domain and hosted zone in route53, and a lambda to update an entry in the r53 hosted zone. The lambda exposes an api endpoint, which your Synology dndns client just calls to update the entry.

I am afraid you will need to be way more specific that "but still IAM not able to make it work", unless of course you just want to share that it's not working for you, without actually looking for help.

Have you checked the Lamba logs in CloudWatch?
Hello one-eyed-king, I meant to say I followed the instructions in this forum: Tutorial - DDNS with AWS Lambda and Route53

I am a newbie in this area so please bear with me while I try to explain what is happening - there seem to be multiple issues happening which I will explain here....

I have setup a custom domain and hosted zone in route 53. I made edits to the code in lambda to update entry in the hosted zone, however the synology ddns is not updating anything...and I do not know how to check lambda logs in cloudwatch...i mean I tried it but i do not know what to look for since I have no clue what to look for (I have no software background). However, I was able to verify that the code is working by pasting the URL (https://xxxxxxxxx.execute-api.us-ea..._&username=__USERNAME__&password=__PASSWORD__) and it showed "Record Set!".

First issue seems to be that my sub-domain in route53 is not getting updated with the ip-address that my Synology NAS sends via DDNS.
 
Last edited:
If you followed step1, your IAM role should use the manged policy AWSLambdaBasicExecutionRole, which grants your Lambda to write to CloudWatch Logs. By default, CloudWatch automatically creates a log group named /aws/lambda/<function name> for your function when it's first invoked.

However, I was able to verify that the code is working by pasting the URL (https://xxxxxxxxx.execute-api.us-ea..._&username=__USERNAME__&password=__PASSWORD__) and it showed "Record Set!".
Does it actually update the dns record for the subdomain if you specify a different ip when you call the url?

Just to be sure: the get parameters (after the domain) in your test look like this, right?
Code:
?hostname={r53 subdomain}&ip={your wan/public ip}&username={the username declared in the lamba}&password={
{the password declared in the lambda}

Update: my bad, I just looked at the text, but didn't realize the actual link has all get parameters.

If updating the entry using the url works, then the AWS part should be correct. So what's left must be an issue with the DDNS client itself.
 
Last edited:
If you followed step1, your IAM role should use the manged policy AWSLambdaBasicExecutionRole, which grants your Lambda to write to CloudWatch Logs. By default, CloudWatch automatically creates a log group named /aws/lambda/<function name> for your function when it's first invoked.


Does it actually update the dns record for the subdomain if you specify a different ip when you call the url?

Just to be sure: the get parameters (after the domain) in your test look like this, right?
Code:
?hostname={r53 subdomain}&ip={your wan/public ip}&username={the username declared in the lamba}&password={
{the password declared in the lambda}

Update: my bad, I just looked at the text, but didn't realize the actual link has all get parameters.

If updating the entry using the url works, then the AWS part should be correct. So what's left must be an issue with the DDNS client itself.
Thanks for responding one-eyed king.
1. The DDNS record is not being updated. Because it was not updating, I went to route53 and updated my sub-domain address with the wan/public ip manually instead of leaving it at 0.0.0.0 as mentioned in the guide. And after that, I pasted the link in my browser and it showed "Record Set!".
2. How do I fix with the DDNS client itself?
3. I did go through step1...
4. Also in step 3.1, for Lambda function, I did not see Node.js 10.x for "Runtime", so I selected Node.js 14.x.
 
Last edited:
4. Also in step 3.1, for Lambda function, I did not see Node.js 10.x for "Runtime", so I selected Node.js 14.x.
Seems you didn't notice Tutorial - DDNS with AWS Lambda and Route53

Please choose node.js 18.x with the code from the post.

It is unclear whether requesting the url resulted in an update dns entry or not. My understanding was that when you tested it (in a browser or in curl?), it did update the dns entry. Did it not?

Your DDSN client configuration must be correct. I have no idea what you configured. Since you also hide the name of the lambda function in your link above, it won't be possible to know if you configured things properly.
 

Create an account or login to comment

You must be a member in order to leave a comment

Create account

Create an account on our community. It's easy!

Log in

Already have an account? Log in here.

Welcome to SynoForum.com!

SynoForum.com is an unofficial Synology forum for NAS owners and enthusiasts.

Registration is free, easy and fast!

Back
Top