willswire / unifi-ddns Goto Github PK
View Code? Open in Web Editor NEWCloudflare DDNS (Dynamic DNS) support for UniFi OS
Cloudflare DDNS (Dynamic DNS) support for UniFi OS
Hi and thanks for this great guide, but I'm wondering which of the available services Unify supports on the latest version of the controller software I should use?
Choices are:
Thanks!
Some ISPs only assign an IPv6 and no IPv4 IP to their customers. As a result this utility will fail to update anything at all when trying to assign a domain to it. This utility is useful beyond the realms of the Unifi gateways. I'm able to plug in the same update URLs into FritzBox's and those with IPv4 pass the updated record to CloudFlare successfully.
I have to routers that currently do not have IPv4, and their records are not being updated subsequently.
Would it be possible to implement AAAA support?
I can't seem to get it to recognize my zone.
(error) CloudflareApiException Error: Failed to find zone '**snip**.net'
I see this is just a generic error message from the findZone function. I haven't really dug any deeper to see why it's failing to find a match. Running the API call from the shell manually using the same API token works fine, however. So, I am ruling out any sort of auth issue.
Before I waste a bunch of time on this, I thought I'd see if you've run into this and what viable solutions you may have found.
Thank you for the useful script and instructions. I'm wondering if we could use a similar approach for UDM Pro's VPN? My goal is to use the Cloudflare proxied DNS, instead of a public address.
I have a USG 4, it's getting a bit long in the teeth but it's what I have.
Have managed to deploy the worker to cloudflare, no problems there. However it seems ddclient is sending the wrong GET request, and results in an error with the zone.
DDClient version is 3.9.1
Have tried both dyndns & custom
I see the get request within Cloudflare.
Contents of ddclient.config
# Service : dyndns
server=unifi-cloudflare-ddns.xxxxxxx.workers.dev/update?ip=%i&hostname=%h, protocol=dyndns2 max-interval=28d login=xxxyyy.com password='<apikey>' hostname.xxxyyy.com
Debug Logs:
From CF:
"logs": [
{
"message": [
"CloudflareApiException",
"Error: Failed to find zone '%h/nic/update?system=dyndns'"
],
"level": "error",
"timestamp": 1716450843143
}
From CLI
DEBUG: get_ip: using if, eth2 reports 12.12.12.12
DEBUG:
DEBUG: nic_dyndns2_update -------------------
INFO: setting IP address to 12.12.12.12 for hostname.xxxyyy.com
UPDATE: updating hostname.xxxyyy.com
DEBUG: proxy =
DEBUG: protocol = https
DEBUG: server = unifi-cloudflare-ddns.xxxxxx.dev
DEBUG: url = update?ip=%i&hostname=%h/nic/update?system=dyndns&hostname=hostname.xxxyyy.com&myip=12.12.12.12
CONNECT: unifi-cloudflare-ddns.xxxxxxx.workers.dev
CONNECTED: using SSL
SENDING: GET /update?ip=%i&hostname=%h/nic/update?system=dyndns&hostname=hostname.xxxyyy.com&myip=12.12.12.12 HTTP/1.0
SENDING: Host: unifi-cloudflare-ddns.xxxxxxx.workers.dev
SENDING: Authorization: Basic am12345456778
SENDING: User-Agent: ddclient/3.9.1
SENDING: Connection: close
SENDING:
SENDING:
RECEIVE: HTTP/1.1 500 Internal Server Error
RECEIVE: Date: Thu, 23 May 2024 07:48:54 GMT
RECEIVE: Content-Type: text/plain;charset=UTF-8
RECEIVE: Content-Length: 185
RECEIVE: Connection: close
RECEIVE: Cache-Control: no-store
RECEIVE: Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=llaOyamuJxVpKfThHGOPD%2FZBEpPmKjhVXUnKqTqfSHQ5S2FV5OE%2F2zx7qm5kxohEemAB3XcQJsT%2FaRhyY%2BSDXXerPs8tsplhEO0aQ%2BgU1vKnabT3422clYjpPO2Ljsf"}],"group":"cf-nel","max_age":604800}
RECEIVE: NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
RECEIVE: Server: cloudflare
RECEIVE: CF-RAY: 888372431c3da968-SYD
RECEIVE: alt-svc: h3=":443"; ma=86400
RECEIVE:
RECEIVE: Error: Failed to find zone '%h/nic/update?system=dyndns'
RECEIVE: at Cloudflare.findZone (index.js:25:13)
RECEIVE: at async informAPI (index.js:126:29)
RECEIVE: at async handleRequest (index.js:109:5)
I'm guessing it's something within the USG that's appending the extra "/nic/update?system=dyndns&hostname=hostname.xxxyyy.com&myip=12.12.12.12"
Any thoughts on how to address this?
I am leveraging the index.js script which is reporting no hostname when the script is being sent to a cloudflareworker. Getting the following:
You must specify a hostname
inadyn[13240]: Fatal error in DDNS server response:
inadyn[13240]: [400 Bad Request] You must specify a hostname
inadyn[13240]: Error response from DDNS server, exiting!
inadyn[13240]: Error code 48: DDNS server response not OK
Command being sent from debug:
inadyn[13240]: Sending alias table update to DDNS server: GET /update?ip=47.185.98.12&hostname= HTTP/1.0
Host: dyndns.cowtownbells.workers.dev
Here is the snippit from the config:
iface = eth8
custom dyndns.cowtownbells.workers.dev:1 {
hostname = "ha.cowtownbells.com"
username = "cowtownbells.com"
password = ""
ddns-server = "dyndns.cowtownbells.workers.dev"
ddns-path = "/update?ip=%i&hostname="
}
Is it possible to implement a working solution for AAAA records?
Hi there,
Having issue with updating the DNS records in Cloudflare.
Here's the response code from Cloudflare.
{
"outcome": "ok",
"scriptVersion": {
"id": "2d65bde6-eaf4-4c60-ac78-90eb79744c3d"
},
"scriptName": "unifi-cloudflare-ddns",
"diagnosticsChannelEvents": [],
"exceptions": [],
"logs": [
{
"message": [
"CloudflareApiException",
"Error: Failed to update dns record"
],
"level": "error",
"timestamp": 1715157944087
}
],
"eventTimestamp": 1715157942883,
"event": {
"request": {
"url": "",
"method": "GET",
"headers": {
"accept-encoding": "gzip, br",
"authorization": "REDACTED",
"cf-connecting-ip": "",
"cf-ipcountry": "AU",
"cf-ray": "88082cd6fe7b5c0f",
"cf-visitor": "{"scheme":"https"}",
"connection": "Keep-Alive",
"host": "",
"user-agent": "inadyn/2.12.0 https://github.com/troglobit/inadyn/issues",
"x-forwarded-proto": "https",
"x-real-ip": ""
},
"cf": {
"clientTcpRtt": 20,
"longitude": "145.05460",
"httpProtocol": "HTTP/1.0",
"tlsCipher": "AEAD-AES256-GCM-SHA384",
"continent": "OC",
"asn": 38195,
"country": "AU",
"tlsClientExtensionsSha1": "NRKhbDZKs+zPlf1Pm5T18FiD2+I=",
"verifiedBotCategory": "",
"tlsClientAuth": {
"certIssuerDNLegacy": "",
"certIssuerSKI": "",
"certSubjectDNRFC2253": "",
"certSubjectDNLegacy": "",
"certFingerprintSHA256": "",
"certNotBefore": "",
"certSKI": "",
"certSerial": "",
"certIssuerDN": "",
"certVerified": "NONE",
"certNotAfter": "",
"certSubjectDN": "",
"certPresented": "0",
"certRevoked": "0",
"certIssuerSerial": "",
"certIssuerDNRFC2253": "",
"certFingerprintSHA1": ""
},
"tlsExportedAuthenticator": {
"clientFinished": "*************************************",
"clientHandshake": "",
"serverHandshake": "",
"serverFinished": ""
},
"tlsVersion": "TLSv1.3",
"city": "",
"timezone": "",
"colo": "",
"tlsClientHelloLength": "",
"edgeRequestKeepAliveStatus": 1,
"postalCode": "",
"region": "",
"latitude": "-",
"requestPriority": "",
"regionCode": "****8",
"asOrganization": "***",
"tlsClientRandom": "********8"
}
},
"response": {
"status": 500
}
},
"id": 0
}
This is the error i get from SSH from Dream Machine SE side.
Temporary error in DDNS Server Reponse: DDNS Server busy, try later.
Hey Guys,
Here is a tip that can save you hours when using the USG-3P device.
The problem you may encounter:
WARNING: cannot connect to unifi-cloudflare-ddns.<worker-subdomain>.workers.dev:443
WARNING: file /var/cache/ddclient/ddclient_pppoe0.cache, line 3: Invalid Value for keyword 'ip' = ''
Solution to connect USG-3P to unifi-cloudflare-ddns error:
ddns.<your-domain>
unifi-cloudflare-ddns.<worker-subdomain>.workers.dev
. Adding a custom domain name can fix this issue.If this is helpful, please upvote to make it more visible. It's recommended the author adds this content to the README.
Getting this going with the existing instructions was a bit of a pain. It's not that I needed my hand held... but I kinda needed my hand held. I don't normally need or use nodejs, let alone trying to figure out wrangler, so getting those two working took longer than it needed to.
Here is a suggestion for some slightly more inclusive instructions that might help cut down time for someone like me:
Note #10. I'm not sure if the Read permission is necessary. I've read some places that say it is, but the original instructions don't mention it.
npm --version
If you get errors, your path variables might be wrong.npm -g install wrangler --safe-dev
(-g installs it to a global profile)wrangler version
wrangler login
which will open a browser and ask you to login to cloudflare if you aren't already, then allow wrangler as a trusted app.wrangler deploy
Note: By default the worker name is: unifi-cloudflare-ddns
You can change this on the Cloudflare website Overview -> Workers & Pages before adding the info into the Unifi console.
Configured and setup worker / when updating from Unifi I get the following:
Host and IP obscured.
root@WCDream-Wall:~# inadyn -n -1 --force -f /run/ddns-eth18-inadyn.conf
inadyn[489163]: In-a-dyn version 2.9.1 -- Dynamic DNS update client.
inadyn[489163]: Update forced for alias dynamic.fakedomain.net, new IP# 4#.19#.13#.2##
inadyn[489163]: OpenSSL error: 548520930960:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:../ssl/record/rec_layer_s3.c:1562:SSL alert number 40
root@WCDream-Wall:~#
Could it please be added to the script to update the Zero Trust Gateway DNS Location DNS IP?
I followed the steps in the readme to configure Cloudflare for my Dream Machine. When I go to my worker url, I see 'not found'. Is that the expected behavior?
Working through this configuration for the first time / fresh setup:
Ubuntu 20.04..6
Wrangler 2.17.0
nodejs v16.20.0
Cloned repo 30 Apr and ensure the updated wrangler.toml
name = "unifi-cloudflare-ddns"
main = "src/index.js"
compatibility_date = "2023-04-23"
compatibility_flags = [ "nodejs_compat" ]
azureadmin@vm-linux-001:~/unifi-cloudflare-ddns$
getting error:
✘ [ERROR] Could not resolve "buffer"
src/index.js:1:23:
1 │ import { Buffer } from "buffer";
╵ ~~~~~~~~
The package "buffer" wasn't found on the file system but is built into node.
Add "node_compat = true" to your wrangler.toml file to enable Node compatibility.
✘ [ERROR] Build failed with 1 error:
src/index.js:1:23: ERROR: Could not resolve "buffer"
Leaving this in case anyone else is stuck where I'm at.
Set everything up, verified it was sending requests to worker, failed to update IP.
After putting a crap ton of logs throughout the code I found two issues with Ubiquiti's software:
I believe the first one is a straight up bug, if you just send a request without the query this sometimes gets appended.
The second was a bit of a doozy. The only feedback the logs were giving was a 500 and the message wasn't visible (only current real issue I have with this script). Threw logs in all the exceptions to narrow it down and came out with the duplicate bug and a failure in the actual PUT. A lot more logs added later and the exact failure was the PUT was being rejected with a 9004 exception, quick google said whatever IP I was supplying was not eligible for proxy.
Couple logs later I grabbed the IP Ubiquiti was pushing, 100.x.x.x. Sure enough it was rejected with a 9004. Confused I quickly looked up my IP and got a 204.x.x.x, CF did not reject that IP.
The hell.
Network 7.2.95
Hi guys,
just tried to setup my UDMB (UnifiOS 1.12.15, Network 7.1.59) to directly update its public ip to cloudflare.
Currently I am using affraid for that and this is working.
I created a new A record with my root domain, which I will call "example.de".
My config in the UDMB looks like this:
But when the UDMB tries to update the ip, I just get this:
[400 Bad Request] <html> <head><title>400 Bad Request</title></head> <body> <center><h1>400 Bad Request</h1></center> <hr><center>cloudflare</center> </body> </html>
I tried to access the worker url with the cloudflare dev tools and I can access at least the url till https://ddnsapi.example.workers.dev/nic/update and get the
400 Bad Request
cache-control:
no-store
content-length:
33
content-type:
text/plain;charset=UTF-8
Please provide valid credentials.
What I am doing wrong?
Thanks in advance!
I found that the instructions provided here work as expected for the USG. However, when I replicated the steps for the UDM Pro SE (UnifFi OS 2.4.8, which is EA), DNS was not updating. To resolve it, I SSH'd into it and ran this command:
/usr/sbin/inadyn -n -C -f /run/ddns-eth8-inadyn.conf --no-pidfile -l debug
I found that the HTTP request it was making to Cloudflare was malformed because it was missing a leading folder path:
inadyn[20183]: Sending alias table update to DDNS server:
GET foobar.workers.dev HTTP/1.0
Host: foobar.workers.dev
Authorization: Basic foobar
User-Agent: inadyn/2.8.1 https://github.com/troglobit/inadyn/issues
inadyn[20183]: Successfully sent HTTPS request!
inadyn[20183]: Successfully received HTTPS response (316/8191 bytes)!
inadyn[20183]: DDNS server response: HTTP/1.1 400 Bad Request
Server: cloudflare
Date: Thu, 28 Apr 2022 16:22:43 GMT
Content-Type: text/html
Content-Length: 155
Connection: close
CF-RAY: -
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare</center>
</body>
</html>
Notice the malformed GET subdomain.domain.com HTTP/1.0
Long story short, thanks to this blog post, I found i needed to append /nic/update?hostname=%h&myip=%i
at the end of the Server entry in the DDNS configuration. So, if your Server entry is subdomain.workers.dev
, make it this: workers.dev/nic/update?hostname=%h&myip=%i
.
Getting this error:
Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: actions/checkout@v3. For more information see: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/.
Hi,
just found this nice solution and tried to deploy it for my domain. I choose the "click to deploy" method but ended up with an error while the project should be created. Tried it several times, deleted the github fork, recreated the api token.
I created a token from template "Edit Cloudflare Workers".
Any ideas? The cloudflare worker dashboard is still empty
In case it helps others, these options worked for me in EdgeOS:
set service dns dynamic interface eth0 service custom-cloudflare host-name <SUBDOMAIN>
set service dns dynamic interface eth0 service custom-cloudflare login <ZONE DOMAIN>
set service dns dynamic interface eth0 service custom-cloudflare password <API TOKEN>
set service dns dynamic interface eth0 service custom-cloudflare protocol dyndns2
set service dns dynamic interface eth0 service custom-cloudflare server <WORKER>.workers.dev/update
The string in the readme file is missing the %h in the ..workers.dev/update?ip=%i&hostname= server section of the udm config
Hi,
I followed all the steps but somehow its not updating. Do i need to create specific kind of worker? i selected default "HTTP Handler" worker and not the "HTTP Router" kind.
Beyond that i have reched everything still no update. Only thing is that earlier i had dyndns configured to update my google domain. Which i removed and added new one. Might be its not triggering dyndns in unifi?
I do have a Unifi system, but given the flakiness of its dyndns updating (you can’t even force an update) I want to use this via my Synology.
I did the full setup, and in the DDNS service provider setup, I made a new provider called “Cloudflare” with the URL: https://xxx.xxx.workers.dev/update?hostname=__HOSTNAME__&ip=__MYIP__
I filled in the hostname, username, and password fields. I clicked the “Test Connection” button, which spun for a few seconds and said that it failed.
All that shows up in the logs is “System failed to register [IP] to [domain] in DDNS server [USER_Cloudflare] because of [service_ddns_error_unknown].”
However, if I go to the Cloudflare DNS page, it worked! The DNS IP is set successfully.
So it seems like the script isn’t correctly returning a success value that the Synology client likes.
As the title says - I have set it up according to instructions. However I am getting IP that is configured on the WAN port which is private IP. I was expecting to see the public IP instead. Is this behavior by design or does require some modifications?
The Dyn DNS service on the UDM is not updating my IP Address automatically. If I trigger the update manually with a command via ssh everything works fine. (The first-time registration was successful even without the command)
Command:"/usr/sbin/inadyn --foreground --config /run/ddns-ppp0-inadyn.conf --once --loglevel debug --force"
If you try and use this before creating a record, it returns an error:
$ curl -u "example.com:redacted" "https://ddns.example.workers.dev/update?ip=192.168.0.1&hostname=ddns.example.com"
TypeError: Cannot set properties of undefined (setting 'content')
at Cloudflare.updateRecord (worker.js:183:22)
at informAPI (worker.js:65:35)
at async handleRequest (worker.js:30:26)
May just want to update the README.md to indicate the dns record you are using must be created or already exist with a previous value.
Other than that, this worked great. Thanks!
I'm not sure if the USG 3P is different from the UDM in protocol version, and if this is related/caused by #6 or #1.
From a bit of troubleshooting, it appears configuring the Server entry as in the docs that the request to the worker has the following:
"event": {
"request": {
"url": "https://ddns-updater.example.workers.dev/update?ip=%i&hostname=/nic/update?system=dyndns&hostname=mydomain.example.com&myip=111.111.111.111",
(Domain & IP replaced)
From a guess it looks like the USG doesn't support using a custom path on the URL.
Have I setup something wrong or is there a version difference somewhere?
I am following your guide exactly but the DNS record on Cloudflare never updates.
Model: USG-Pro-4
Version: 4.4.56.5449062
relevant log in /var/log/messages:
WARNING: file /var/cache/ddclient/ddclient_eth2.cache, line 3: Invalid Value for keyword 'ip' = '
Hi All,
First of all thanks for this great work!
I got it working with one of my domains via the UDM Pro after a bit of trouble deploying the walker (one of the issues here solved it though).
I got though 2 domains to update (i.e. xjh.net and xhh.com) but the UDM Pro somehow seems to only allow one entry for dyndns.
Is there any workaround that I could deploy?
Cheers
No Issue
DynDNS is no longer a service listed in UDM PRO
2024-01-21T23:43:08-05:00 Dream-Machine-Pro inadyn[41309]: [500 Internal Server Error] Error: Failed to update dns record
at Cloudflare.updateRecord (index.js:50:13)
at async informAPI (index.js:121:5)
at async handleRequest (index.js:108:20)
2024-01-21T23:43:08-05:00 Dream-Machine-Pro inadyn[41309]: Will retry again in 600 sec ...
Not really sure where it's going wrong, aside from where in the JS it's throwing the error. I've setup an API token exactly as described in the docs and copied that into the password field on my UDM, specified the host record to be updated and set the username as the root domain name.
Hey all, this is excellent and I really appreciate the work done on this!
I'm attempting to add a second domain to Unifi for another domain, can't see there is any other configuration I need to do with Cloudflare. Because Unifi doesn't allow using the same ddns service twice (dyndns
), using custom doesn't work when using custom
.
Anything you can think of to be able to get around this, whether it be the CLI or otherwise (without introducing another third-party service)?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.