ddclient: Cloudflare - add Cloudflare dns ip check option, merge https://github.com/opnsense/plugins/pull/4184 with minor modifications.

This commit is contained in:
Ad Schellevis 2025-12-17 14:48:52 +01:00
parent b943ea34a7
commit 716e75eec4
4 changed files with 33 additions and 7 deletions

View file

@ -146,6 +146,7 @@
<web_cloudflare>cloudflare</web_cloudflare>
<web_cloudflare_ipv4 value="cloudflare-ipv4">cloudflare-ipv4</web_cloudflare_ipv4>
<web_cloudflare_ipv6 value="cloudflare-ipv6">cloudflare-ipv6</web_cloudflare_ipv6>
<dns_cloudflare value="dns_cloudflare-dns">cloudflare-dns</dns_cloudflare>
<web_dynu_ipv4 value="dynu-ipv4">dynu-ipv4</web_dynu_ipv4>
<web_dynu_ipv6 value="dynu-ipv6">dynu-ipv6</web_dynu_ipv6>
<web_freedns>freedns</web_freedns>

View file

@ -26,13 +26,13 @@
POSSIBILITY OF SUCH DAMAGE.
"""
import argparse
from lib import checkip_service_list, checkip
from lib import registered_services, checkip
if __name__ == '__main__':
# handle parameters
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--service', help='service name', choices=checkip_service_list.keys(), required=True)
parser.add_argument('-s', '--service', help='service name', choices=registered_services(), required=True)
parser.add_argument('-i', '--interface', help='interface', type=str, default='')
parser.add_argument('-t', '--tls', help='enforce tls', choices=['0', '1'], default='1')
parser.add_argument('--timeout', help='timeout', type=str, default='10')

View file

@ -57,5 +57,5 @@
changed (return status of `execute()`) the state is flushed to disk.
"""
from .address import checkip_service_list, checkip
from .address import registered_services, checkip
from .poller import AccountFactory, Poller

View file

@ -26,6 +26,8 @@
import subprocess
import re
import ipaddress
import dns.resolver
import dns.rdataclass
from urllib.parse import urlparse
checkip_service_list = {
@ -51,6 +53,19 @@ checkip_service_list = {
'zoneedit': '%s://dynamic.zoneedit.com/checkip.html'
}
checkip_dns_list = {
'cloudflare-dns': {
'nameservers': ['1.1.1.1','1.0.0.1'],
'resolve_params': {
'qname': 'whoami.cloudflare',
'rdtype': 'TXT',
'rdclass': dns.rdataclass.from_text('CH')
}
}
}
def registered_services():
return list(checkip_service_list.keys()) + list(checkip_dns_list.keys())
def extract_address(host, txt):
""" Extract first IPv4 or IPv6 address from provided string
@ -87,17 +102,17 @@ def transform_ip(ip, ipv6host=None):
def checkip(service, proto='https', timeout='10', interface=None, dynipv6host=None):
""" find ip address using external services defined in checkip_service_list
""" find ip address using external web services defined in checkip_service_list
or dns services defined in checkip_dns_list
:param proto: protocol
:param timeout: timeout in seconds
:param interface: bind to interface
:param dynipv6host: optional partial ipv6 address
:return: str
"""
if service.startswith('web_'):
if service.lstrip('web_') in checkip_service_list:
# configuration name, strip web_ part
service = service[4:]
if service in checkip_service_list:
service = service.lstrip('web_')
params = ['/usr/local/bin/curl', '-m', timeout]
if interface is not None:
params.append("--interface")
@ -124,5 +139,15 @@ def checkip(service, proto='https', timeout='10', interface=None, dynipv6host=No
return str(address)
except ValueError:
continue
elif service.lstrip('dns_') in checkip_dns_list:
svc_info = checkip_dns_list[service.lstrip('dns_')]
resolve_params = svc_info['resolve_params']
dns_resolver = dns.resolver.Resolver()
dns_resolver.nameservers = svc_info['nameservers']
try:
dns_response = dns_resolver.resolve(**resolve_params)
return dns_response[0].to_text().strip('"')
except:
return ""
else:
return ""