mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-03-11 09:04:54 +00:00
dynamicdns: Use only IPv4 for GnuDIP protocol
- The following messages was seen on the ddns.freedombox.org server:
"Unserviceable IP address from <ipv6_address>: user <username>.fbx.one - IP:
<ipv6_address>". This is due to code that checks for validity of incoming IP
address and fails. The current configuration only handles IPv4 address. Even if
this restriction is lifted, GnuDIP code does not contain code to add/remove AAAA
records.
- Fix this by forcing GnuDIP HTTP update requests to go on IPv4.
Tests:
- Copy the code for _request_get_ipv4() into a python3 console and run
_request_get_ipv4('https://ddns.freedombox.org/ip'). Do this on a dual stack
machine with both public IPv4 and IPv6 addresses. Only IPv4 address returned.
Changing the AF to AF_INET6 returns only the IPv6 address.
- Take a test DDNS account offline. Configure it in FreedomBox stable VM. The IP
address is properly updated.
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
7b93932868
commit
a10ba40001
@ -5,6 +5,7 @@ GnuDIP client for updating Dynamic DNS records.
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import socket
|
||||
from html.parser import HTMLParser
|
||||
|
||||
import requests
|
||||
@ -45,18 +46,43 @@ def _check_required_keys(dictionary: dict[str, str], keys: list[str]) -> None:
|
||||
f"Missing required keys in response: {', '.join(missing_keys)}")
|
||||
|
||||
|
||||
def _request_get_ipv4(*args, **kwargs):
|
||||
"""Make a IPv4-only request.
|
||||
|
||||
XXX: This monkey-patches socket.getaddrinfo which may causes issues when
|
||||
running multiple threads. With urllib3 >= 2.4 (Trixie has 2.3), it is
|
||||
possible to implement more cleanly. Use a session for requests library. In
|
||||
the session add custom adapter for https:. In the adapter, override
|
||||
creation of pool manager, and pass socket_family parameter.
|
||||
"""
|
||||
original = socket.getaddrinfo
|
||||
|
||||
def getaddrinfo_ipv4(*args, **kwargs):
|
||||
return original(args[0], args[1], socket.AF_INET, *args[3:], **kwargs)
|
||||
|
||||
socket.getaddrinfo = getaddrinfo_ipv4
|
||||
try:
|
||||
return requests.get(*args, **kwargs)
|
||||
finally:
|
||||
socket.getaddrinfo = original
|
||||
|
||||
|
||||
def update(server: str, domain: str, username: str,
|
||||
password: str) -> tuple[bool, str | None]:
|
||||
"""Update Dynamic DNS record using GnuDIP protocol.
|
||||
|
||||
Protocol documentation:
|
||||
https://gnudip2.sourceforge.net/gnudip-www/latest/gnudip/html/protocol.html
|
||||
|
||||
GnuDIP at least as deployed on the FreedomBox foundation servers does not
|
||||
support IPv6 (it does have any code to update AAAA records). So, make a
|
||||
request only using IPv4 stack.
|
||||
"""
|
||||
domain = domain.removeprefix(username + '.')
|
||||
password_digest = hashlib.md5(password.encode()).hexdigest()
|
||||
|
||||
http_server = f'https://{server}/gnudip/cgi-bin/gdipupdt.cgi'
|
||||
response = requests.get(http_server)
|
||||
response = _request_get_ipv4(http_server)
|
||||
|
||||
salt_response = _extract_content_from_meta_tags(response.text)
|
||||
_check_required_keys(salt_response, ['salt', 'time', 'sign'])
|
||||
@ -74,7 +100,7 @@ def update(server: str, domain: str, username: str,
|
||||
'pass': password_digest,
|
||||
'reqc': '2'
|
||||
}
|
||||
update_response = requests.get(http_server, params=query_params)
|
||||
update_response = _request_get_ipv4(http_server, params=query_params)
|
||||
|
||||
update_result = _extract_content_from_meta_tags(update_response.text)
|
||||
_check_required_keys(update_result, ['retc'])
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user