FRITZ!Box and netcup DynDNS
Polls a FRITZ!Box's external IPv4-address and on change, updates a netcup DNS entry using the netcup DNS API. Can easily be adapted to use another source for the DNS-entry value, and to update various types of DNS entries, including AAAA.
Depends on node-red-contrib-fritz.
netcup API key and password can be created in the customer control panel.
[{"id":"1f73a5d7.e3db6a","type":"tab","label":"FRITZ!Box and netcup DynDNS","disabled":false,"info":""},{"id":"7702c44a.c888bc","type":"http request","z":"1f73a5d7.e3db6a","name":"send login request","method":"POST","ret":"obj","paytoqs":"ignore","url":"https://ccp.netcup.net/run/webservice/servers/endpoint.php?JSON","tls":"30a69635.622642","persist":false,"proxy":"","authType":"","x":430,"y":460,"wires":[["2b3e84a6.3a497c"]]},{"id":"c7f51cb.af9796","type":"inject","z":"1f73a5d7.e3db6a","name":"run at start and every minute","props":[],"repeat":"60","crontab":"","once":true,"onceDelay":"5","topic":"","x":150,"y":100,"wires":[["6f0de282.d3a8ac"]]},{"id":"6f0de282.d3a8ac","type":"fritzbox-in","z":"1f73a5d7.e3db6a","device":"bd2c7b29.a934a","name":"get external IPv4 address from FRITZ!Box","service":"urn:schemas-upnp-org:service:WANIPConnection:1","action":"GetExternalIPAddress","arguments":"{}","x":240,"y":160,"wires":[["b8a09678.fec5c"]]},{"id":"aeaea103.71ba1","type":"rbe","z":"1f73a5d7.e3db6a","name":"msg.payload.NewExternalIPAddress has changed","func":"rbe","gap":"","start":"","inout":"out","property":"payload.NewExternalIPAddress","x":270,"y":340,"wires":[["6a7e2610.73a738"]]},{"id":"6a7e2610.73a738","type":"change","z":"1f73a5d7.e3db6a","name":"store msg.payload.NewExternalIPAddress in msg.external_ipv4","rules":[{"t":"set","p":"external_ipv4","pt":"msg","to":"payload.NewExternalIPAddress","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":400,"wires":[["d1968848.fb2a58"]]},{"id":"2b3e84a6.3a497c","type":"switch","z":"1f73a5d7.e3db6a","name":"msg.payload.status == success","property":"payload.status","propertyType":"msg","rules":[{"t":"eq","v":"success","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":210,"y":520,"wires":[["f5ea7c7.85fa78"]]},{"id":"261617dc.1bc","type":"change","z":"1f73a5d7.e3db6a","name":"configuration","rules":[{"t":"set","p":"netcup_apikey","pt":"flow","to":"netcup-api-key","tot":"str"},{"t":"set","p":"netcup_apipassword","pt":"flow","to":"netcup-api-password","tot":"str"},{"t":"set","p":"netcup_customernumber","pt":"flow","to":"12345","tot":"str"},{"t":"set","p":"dnsrecord_domainname","pt":"flow","to":"domain.tld","tot":"str"},{"t":"set","p":"dnsrecord_hostname","pt":"flow","to":"subdomain","tot":"str"},{"t":"set","p":"dnsrecord_type","pt":"flow","to":"A","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":250,"y":40,"wires":[[]]},{"id":"79351b8b.0283f4","type":"inject","z":"1f73a5d7.e3db6a","name":"run once","props":[],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","x":80,"y":40,"wires":[["261617dc.1bc"]]},{"id":"f5ea7c7.85fa78","type":"change","z":"1f73a5d7.e3db6a","name":"store msg.payload.responsedata.apisessionid in msg.apisessionid","rules":[{"t":"set","p":"apisessionid","pt":"msg","to":"payload.responsedata.apisessionid","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":580,"wires":[["fa2d5518.45f7b"]]},{"id":"6c8cd140.a486a8","type":"http request","z":"1f73a5d7.e3db6a","name":"send infoDnsRecords request","method":"POST","ret":"obj","paytoqs":"ignore","url":"https://ccp.netcup.net/run/webservice/servers/endpoint.php?JSON","tls":"30a69635.622642","persist":false,"proxy":"","authType":"","x":530,"y":640,"wires":[["b3671332.6e2d5"]]},{"id":"cd75e7b8.523ff8","type":"function","z":"1f73a5d7.e3db6a","name":"get id of DNS record from response","func":"const dnsrecords = msg.payload.responsedata.dnsrecords;\nconst dnsrecord_hostname = flow.get(\"dnsrecord_hostname\");\nconst dnsrecord_type = flow.get(\"dnsrecord_type\");\n\nfor (let i = 0; i < dnsrecords.length; ++i) {\n const record = dnsrecords[i];\n if (record.hostname === dnsrecord_hostname && record.type === dnsrecord_type) {\n msg.dnsrecordid = record.id;\n break;\n }\n}\n\nif (!msg.dnsrecordid) {\n node.error(`No DNS record found with hostname ${flow.dnsrecord_hostname} and type ${flow.dnsrecord_type}.`, msg);\n} else {\n return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":220,"y":760,"wires":[["5432b1ff.6348a"]]},{"id":"5432b1ff.6348a","type":"change","z":"1f73a5d7.e3db6a","name":"create updateDnsRecords POST data","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"action\": \"updateDnsRecords\",\t \"param\": {\t \"domainname\": $flowContext(\"dnsrecord_domainname\"),\t \"customernumber\": $flowContext(\"netcup_customernumber\"),\t \"apikey\": $flowContext(\"netcup_apikey\"),\t \"apisessionid\": apisessionid,\t \"dnsrecordset\": {\t \"dnsrecords\": [{\t \"id\": dnsrecordid,\t \"hostname\": $flowContext(\"dnsrecord_hostname\"),\t \"type\": $flowContext(\"dnsrecord_type\"),\t \"destination\": external_ipv4\t }]\t }\t }\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":820,"wires":[["eb7d4920.dfa26"]]},{"id":"eb7d4920.dfa26","type":"http request","z":"1f73a5d7.e3db6a","name":"send updateDnsRecords request","method":"POST","ret":"obj","paytoqs":"ignore","url":"https://ccp.netcup.net/run/webservice/servers/endpoint.php?JSON","tls":"30a69635.622642","persist":false,"proxy":"","authType":"","x":560,"y":820,"wires":[["1f38f24c.459326"]]},{"id":"3aa01976.7b821e","type":"change","z":"1f73a5d7.e3db6a","name":"create logout POST data","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"action\": \"logout\",\t \"param\": {\t \"customernumber\": $flowContext(\"netcup_customernumber\"),\t \"apikey\": $flowContext(\"netcup_apikey\"),\t \"apisessionid\": apisessionid\t }\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":940,"wires":[["5d8e283d.6d1bf8"]]},{"id":"5d8e283d.6d1bf8","type":"http request","z":"1f73a5d7.e3db6a","name":"send logout request","method":"POST","ret":"obj","paytoqs":"ignore","url":"https://ccp.netcup.net/run/webservice/servers/endpoint.php?JSON","tls":"30a69635.622642","persist":false,"proxy":"","authType":"","x":440,"y":940,"wires":[[]]},{"id":"b8a09678.fec5c","type":"switch","z":"1f73a5d7.e3db6a","name":"msg.payload has key NewExternalIPAddress","property":"payload","propertyType":"msg","rules":[{"t":"hask","v":"NewExternalIPAddress","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":250,"y":220,"wires":[["838a9b4c.8eed08"]]},{"id":"838a9b4c.8eed08","type":"switch","z":"1f73a5d7.e3db6a","name":"msg.payload.NewExternalIPAddress is IPv4 address","property":"payload.NewExternalIPAddress","propertyType":"msg","rules":[{"t":"regex","v":"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","vt":"str","case":false}],"checkall":"true","repair":false,"outputs":1,"x":280,"y":280,"wires":[["aeaea103.71ba1"]]},{"id":"d1968848.fb2a58","type":"change","z":"1f73a5d7.e3db6a","name":"create login POST data","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"action\": \"login\",\t \"param\": {\t \"apikey\": $flowContext(\"netcup_apikey\"),\t \"apipassword\": $flowContext(\"netcup_apipassword\"),\t \"customernumber\": $flowContext(\"netcup_customernumber\")\t \t }\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":460,"wires":[["7702c44a.c888bc"]]},{"id":"fa2d5518.45f7b","type":"change","z":"1f73a5d7.e3db6a","name":"create infoDnsRecords POST data","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"action\": \"infoDnsRecords\",\t \"param\": {\t \"domainname\": $flowContext(\"dnsrecord_domainname\"),\t \"customernumber\": $flowContext(\"netcup_customernumber\"),\t \"apikey\": $flowContext(\"netcup_apikey\"),\t \"apisessionid\": apisessionid\t }\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":220,"y":640,"wires":[["6c8cd140.a486a8"]]},{"id":"b3671332.6e2d5","type":"switch","z":"1f73a5d7.e3db6a","name":"msg.payload.status == success","property":"payload.status","propertyType":"msg","rules":[{"t":"eq","v":"success","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":210,"y":700,"wires":[["cd75e7b8.523ff8"]]},{"id":"1f38f24c.459326","type":"function","z":"1f73a5d7.e3db6a","name":"log error if msg.payload.status != success","func":"if (msg.payload.status != \"success\") {\n node.error(\"Update of DNS entry failed.\", msg);\n} else {\n return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":240,"y":880,"wires":[["3aa01976.7b821e"]]},{"id":"30a69635.622642","type":"tls-config","z":"","name":"","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","servername":"","verifyservercert":true},{"id":"bd2c7b29.a934a","type":"fritzbox-config","z":"","name":"","host":"fritz.box","port":"49000","ssl":false}]