mirror of
https://github.com/opnsense/plugins.git
synced 2026-02-03 20:40:37 -05:00
dns/ddclient: wrap up new version
This commit is contained in:
parent
b18c2660e7
commit
fe467364cb
4 changed files with 35 additions and 29 deletions
|
|
@ -1,5 +1,5 @@
|
|||
PLUGIN_NAME= ddclient
|
||||
PLUGIN_VERSION= 1.28
|
||||
PLUGIN_VERSION= 1.29
|
||||
PLUGIN_DEPENDS= ddclient py${PLUGIN_PYTHON}-boto3
|
||||
PLUGIN_COMMENT= Dynamic DNS client
|
||||
PLUGIN_MAINTAINER= ad@opnsense.org
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
This plugin offers dynamic DNS capabilities using a native backend
|
||||
or ddclient. The native backend is the default implementation.
|
||||
ddclient is a Perl client used to update dynamic DNS entries for
|
||||
accounts on many dynamic DNS services.
|
||||
|
||||
WWW: https://github.com/ddclient/ddclient
|
||||
|
||||
Plugin Changelog
|
||||
================
|
||||
|
||||
1.29
|
||||
|
||||
* Add native backend support for Hetzner DNS (contributed by Michael J. Arcan)
|
||||
* Add native backend support for dnspod.cn (contributed by Ansen)
|
||||
* Add Cloudflare DNS IP check option (contributed by GTechAlpha)
|
||||
|
||||
1.28
|
||||
|
||||
* Add native backend support for PowerDNS API (contributed by Oliver Traber)
|
||||
|
|
|
|||
52
dns/ddclient/src/opnsense/scripts/ddclient/lib/account/dnspod_cn.py
Normal file → Executable file
52
dns/ddclient/src/opnsense/scripts/ddclient/lib/account/dnspod_cn.py
Normal file → Executable file
|
|
@ -61,11 +61,11 @@ class DNSPod_CN(BaseAccount):
|
|||
def _sign(key, msg):
|
||||
"""
|
||||
Generate HMAC-SHA256 signature.
|
||||
|
||||
|
||||
Args:
|
||||
key (bytes): Signing key
|
||||
msg (str): Message to sign
|
||||
|
||||
|
||||
Returns:
|
||||
bytes: Signature digest
|
||||
"""
|
||||
|
|
@ -74,21 +74,21 @@ class DNSPod_CN(BaseAccount):
|
|||
def generate_signature(self, action, payload="{}"):
|
||||
"""
|
||||
Generate signature and headers for a Tencent Cloud API request.
|
||||
|
||||
|
||||
Args:
|
||||
action (str): API action name
|
||||
payload (str or dict, optional): Request payload. Defaults to "{}".
|
||||
|
||||
|
||||
Returns:
|
||||
tuple: Request headers and canonical request
|
||||
"""
|
||||
# Ensure payload is a string
|
||||
payload = json.dumps(payload) if isinstance(payload, dict) else payload
|
||||
|
||||
|
||||
# Get current timestamp
|
||||
timestamp = int(time.time())
|
||||
date = datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
# Step 1: Create Canonical Request
|
||||
http_request_method = "POST"
|
||||
canonical_uri = "/"
|
||||
|
|
@ -97,7 +97,7 @@ class DNSPod_CN(BaseAccount):
|
|||
canonical_headers = f"content-type:{ct}\nhost:{self._services[self.settings.get('service')]}\nx-tc-action:{action.lower()}\n"
|
||||
signed_headers = "content-type;host;x-tc-action"
|
||||
hashed_request_payload = hashlib.sha256(payload.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
canonical_request = (
|
||||
f"{http_request_method}\n"
|
||||
f"{canonical_uri}\n"
|
||||
|
|
@ -106,25 +106,25 @@ class DNSPod_CN(BaseAccount):
|
|||
f"{signed_headers}\n"
|
||||
f"{hashed_request_payload}"
|
||||
)
|
||||
|
||||
|
||||
# Step 2: Create String to Sign
|
||||
algorithm = "TC3-HMAC-SHA256"
|
||||
credential_scope = f"{date}/{self.service}/tc3_request"
|
||||
hashed_canonical_request = hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
string_to_sign = (
|
||||
f"{algorithm}\n"
|
||||
f"{timestamp}\n"
|
||||
f"{credential_scope}\n"
|
||||
f"{hashed_canonical_request}"
|
||||
)
|
||||
|
||||
|
||||
# Step 3: Calculate Signature
|
||||
secret_date = self._sign(("TC3" + self.settings.get('password')).encode("utf-8"), date)
|
||||
secret_service = self._sign(secret_date, self.service)
|
||||
secret_signing = self._sign(secret_service, "tc3_request")
|
||||
signature = hmac.new(secret_signing, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
|
||||
|
||||
|
||||
# Step 4: Create Authorization Header
|
||||
authorization = (
|
||||
f"{algorithm} "
|
||||
|
|
@ -132,7 +132,7 @@ class DNSPod_CN(BaseAccount):
|
|||
f"SignedHeaders={signed_headers}, "
|
||||
f"Signature={signature}"
|
||||
)
|
||||
|
||||
|
||||
# Prepare headers
|
||||
headers = {
|
||||
"Authorization": authorization,
|
||||
|
|
@ -143,53 +143,53 @@ class DNSPod_CN(BaseAccount):
|
|||
"X-TC-Version": "2021-03-23",
|
||||
'User-Agent': 'OPNsense-dyndns',
|
||||
}
|
||||
|
||||
|
||||
return headers, payload
|
||||
|
||||
def send_request(self, action, payload="{}", region="", token=""):
|
||||
"""
|
||||
Send a request to the Tencent Cloud API.
|
||||
|
||||
|
||||
Args:
|
||||
action (str): API action name
|
||||
payload (str or dict, optional): Request payload. Defaults to "{}".
|
||||
region (str, optional): Optional region parameter
|
||||
token (str, optional): Optional token parameter
|
||||
|
||||
|
||||
Returns:
|
||||
dict: API response JSON
|
||||
"""
|
||||
# Get headers and prepared payload
|
||||
headers, payload = self.generate_signature(action, payload)
|
||||
|
||||
|
||||
# Add optional headers
|
||||
if region:
|
||||
headers["X-TC-Region"] = region
|
||||
if token:
|
||||
headers["X-TC-Token"] = token
|
||||
|
||||
|
||||
try:
|
||||
# Send request using requests library
|
||||
response = requests.post(
|
||||
url=f"https://{self._services[self.settings.get('service')]}",
|
||||
headers=headers,
|
||||
url=f"https://{self._services[self.settings.get('service')]}",
|
||||
headers=headers,
|
||||
data=payload,
|
||||
timeout=10
|
||||
)
|
||||
|
||||
|
||||
# Raise an exception for bad responses
|
||||
response.raise_for_status()
|
||||
|
||||
|
||||
# Return JSON response
|
||||
return response
|
||||
|
||||
|
||||
except requests.RequestException as err:
|
||||
print(f"Request error: {err}")
|
||||
|
||||
|
||||
# If there's a response, print its content for debugging
|
||||
if hasattr(err, 'response') and err.response is not None:
|
||||
print(f"Response content: {err.response.text}")
|
||||
|
||||
|
||||
return None
|
||||
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ class DNSPod_CN(BaseAccount):
|
|||
subdomains.append('@')
|
||||
else:
|
||||
subdomains.append(_subdomain.replace(f".{self.settings.get('zone')}", ''))
|
||||
|
||||
|
||||
if len(subdomains) < 1:
|
||||
syslog.syslog(
|
||||
syslog.LOG_ERR,
|
||||
|
|
@ -277,7 +277,7 @@ class DNSPod_CN(BaseAccount):
|
|||
"Account %s failed to set new ip %s [%s]" % (self.description, self.current_address, response.text)
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
record_list = payload['Response']['DetailList'][0].get('RecordList', False)
|
||||
if record_list and len(record_list) == len(subdomains):
|
||||
syslog.syslog(
|
||||
|
|
|
|||
0
dns/ddclient/src/opnsense/scripts/ddclient/lib/account/hetzner.py
Normal file → Executable file
0
dns/ddclient/src/opnsense/scripts/ddclient/lib/account/hetzner.py
Normal file → Executable file
Loading…
Reference in a new issue