From d08fbe37e442ed3090eb8a94faef1afbd7b54d32 Mon Sep 17 00:00:00 2001 From: Greg Glockner Date: Thu, 17 Aug 2023 23:02:01 -0700 Subject: [PATCH] dns/ddclient: DuckDNS (#3552) --- dns/ddclient/pkg-descr | 2 +- .../scripts/ddclient/lib/account/aws.py | 26 +++++- .../scripts/ddclient/lib/account/duckdns.py | 80 +++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100755 dns/ddclient/src/opnsense/scripts/ddclient/lib/account/duckdns.py diff --git a/dns/ddclient/pkg-descr b/dns/ddclient/pkg-descr index daada4836..3cfff7a53 100644 --- a/dns/ddclient/pkg-descr +++ b/dns/ddclient/pkg-descr @@ -8,7 +8,7 @@ Plugin Changelog 1.15 -* Add AWS Route53 to OPNsense backend (contributed by Greg Glockner) +* Add AWS Route53 and DuckDNS to OPNsense backend (contributed by Greg Glockner) 1.14 diff --git a/dns/ddclient/src/opnsense/scripts/ddclient/lib/account/aws.py b/dns/ddclient/src/opnsense/scripts/ddclient/lib/account/aws.py index 7d66b0d19..e80e4e037 100755 --- a/dns/ddclient/src/opnsense/scripts/ddclient/lib/account/aws.py +++ b/dns/ddclient/src/opnsense/scripts/ddclient/lib/account/aws.py @@ -1,9 +1,33 @@ """ + Copyright (c) 2023 Greg Glockner + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------------------------------- AWS Route53 DNS provider Usage: AWS access key: username AWS secret key: password - Route53 Hosted Zone ID: resource ID (use advanced settings) + Route53 Hosted Zone ID: zone """ import syslog import boto3 diff --git a/dns/ddclient/src/opnsense/scripts/ddclient/lib/account/duckdns.py b/dns/ddclient/src/opnsense/scripts/ddclient/lib/account/duckdns.py new file mode 100755 index 000000000..185daa112 --- /dev/null +++ b/dns/ddclient/src/opnsense/scripts/ddclient/lib/account/duckdns.py @@ -0,0 +1,80 @@ +""" + Copyright (c) 2023 Greg Glockner + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------------------------------- + DuckDNS updater + Token should be set via the password field +""" +import syslog +import requests +from . import BaseAccount + + +class duckdns(BaseAccount): + _services = ['duckdns'] + + def __init__(self, account: dict): + super().__init__(account) + + @staticmethod + def known_services(): + return duckdns._services + + @staticmethod + def match(account): + return account.get('service') in duckdns._services + + def execute(self): + """ Duck DNS update + """ + + if super().execute(): + data = { + 'domains': self.settings.get('hostnames'), + 'token': self.settings.get('password') + } + + ip = str(self.current_address) + if ':' in ip: + data['ipv6'] = ip + else: + data['ip'] = ip + + proto = 'https' if self.settings.get('force_ssl', False) else 'http' + + try: + response = requests.get(proto+'://www.duckdns.org/update', data) + if response.text.startswith('KO'): + raise RuntimeError( + f"DuckDNS update failed for {self.description} with ip {self.current_address} for domains {data['domains']}, response: {response.text}") + except Exception as e: + syslog.syslog(syslog.LOG_ERR, str(e)) + return False + + syslog.syslog( + syslog.LOG_NOTICE, + f"Account {self.description} set new ip {self.current_address} for domains {data['domains']}") + + self.update_state(address=self.current_address) + return True