dyndnshelper/README.md
2023-07-09 19:12:41 +02:00

6.0 KiB

DynDNS Helper

Self-hosted python web application based on FastAPI to update DNS records via API.

Vendor backends are easily extensible and include currently:

Current use-cases for this application:

  • Updating DNS records based on data received via DynDNS compatible requests from e.g. routers such as AVM Fritzbox
    • Support for IPv4, IPv6 and IPv6 LAN Prefix
    • IPv4 will result in updated A record
    • IPv6 will result in updated AAAA record
    • IPv6 LAN Prefix will update all AAAA records defined in an config mapping of FQDN to IPv6 Interface IDs

Limitations:

  • No support for DNS round robin or the like
  • No updating a single FQDN across multiple vendors
  • No cleanup of DNS records
  • No updating data other than values of DNS records

TODO

  • docs
  • tests

Router DynDNS Examples

AVM Fritzbox

Fritzbox DynDNS Settings:

Update-URL: https://192.168.178.10/fqdns/<domain>/dyndns?ip=<ipaddr>&ip=<ip6addr>&ipv6lanprefix=<ip6lanprefix>
Domainname: test1.domain.tld
Username:   testuser
Password:   testpassword

App config:

{
  "fqdns": {
    "test1.domain.tld": {
      "vendor": "hetzner",
      "dyndns_credentials": {
        "testuser": "9f735e0df9a1ddc702bf0a1a7b83033f9f7153a00c29de82cedadc9957289b05"
      }
    }
  }
}

IPv6 LAN Prefix & Interface ID (IID)

Providers will assign an publicly routed IPv6 Prefix for a client. Normally a /48 or /64.

Depending on the clients router configuration, devices behind it will use this prefix to assign themselves a public IPv6.

These devices append an Interface ID (or: host part) to the prefix. How this IID is generated depends on the device configuration.

It may be generated by using its MAC Address, it may be generated randomly for privacy reasons.

This helper supports updating DNS records for IIDs when the IPv6 LAN Prefix changes:

If a DynDNS API call contains an ipv6lanprefix, the FQDN settings of the given fqdn will be used to find other FQDNs to update, e.g.:

{
  "fqdns": {
    "test1.domain.tld": {
      "vendor": "hetzner",
      "dyndns_credentials": {
        "testuser": "9f735e0df9a1ddc702bf0a1a7b83033f9f7153a00c29de82cedadc9957289b05"
      },
      "ipv6_lan_prefix_iid_map": {
        "test2.domain.tld": "::2a0:00ff:111c:1234"
      }
    },
    "test2.domain.tld": {
      "vendor": "..."
    }
  }
}

If for this configuration a DynDNS API call for test1.domain.tld is received, that contains ipv6lanprefix, an AAAA DNS record for test2.domain.tld is ensured.

For the above example: An ipv6lanprefix of 2001:db8:85a3::/48 will result in:

test2.domaintld    AAAA    2001:db8:85a3::2a0:00ff:111c:1234

Caveats

  • Larger IIDs than a prefix allows will be shortened
    • e.g.: An ipv6lanprefix of 2001:db8:85a3:1234::/64 with an IID ::9876:2a0:00ff:111c:1234 will result in an IPv6 address 2001:db8:85a3:1234:2a0:00ff:111c:1234

Configuration

All configuration options should be supplied as JSON files in /etc/dyndnshelper/.

Files are merged by their top level key. With multiple files with the same top level key (e.g. server) only the last read will be used.

Example structure:

/etc/dyndnshelper/
                  fqdns.json
                  server.json
                  vendors.json

Server

All server config is defined under a key server, e.g.:

{
  "server": {
    "host": "0.0.0.0"
  }
}

The following options are available:

Option Default Required Description Example
host '127.0.0.1' false host to listen on '0.0.0.0'
port 8000 false port to listen on 8080
app_log_level 'INFO' false log level for the application 'DEBUG'
root_log_level 'WARNING' false log level for all other applications 'INFO'

Vendors

All vendor config is defined under a key vendors and the lowercase name of the vendor, e.g.:

{
  "vendors": {
    "hetzner": {
      "enabled": true,
      ...
    }
  }
}

The following common options are available for every vendor:

Option Default Required Description Example
enabled false false if this vendor is enabled true
create_zone_if_missing false false if a zone is created for a FQDN if its missing - otherwise raises an error true
default_zone_ttl 86400 false default TTL to set for created zones 7200
default_record_ttl 600 false default TTL to set for created records - if not defined in individual FQDN settings 300

Hetzner

Additional options for Hetzner:

Option Default Required Description Example
api_url 'https://dns.hetzner.com/api/v1' false Hetzner DNS API URL
api_token true default TTL to set for created records - if not defined in individual FQDN settings 'secretapitoken'

FQDNs

All FQDN config is defined under a key fqdns and the FQDN as a key, e.g.:

{
  "fqdns": {
    "test1.domain.tld": {
      "vendor": "hetzner",
      ...
    }
  }
}

The following options are available for each FQDN:

Option Default Required Description Example
vendor true vendor to use for the FQDN 'hetzner'
zone the root zone of the FQDN false DNS zone to handle DNS records in 'myservers.domain.tld'
record_ttl false DNS record TTL to use, when creating records. Overrides vendor default_record_ttl 600
dyndns_credentials false Users and their SHA256 hashed passwords that are allowed to send DynDNS updates for this FQDN {"testuser": "9f735e0df9a1ddc702bf0a1a7b83033f9f7153a00c29de82cedadc9957289b05"}
ipv6_lan_prefix_iid_map false FQDNs and their IIDs to be updates if a DynDNS update for this FQDN contains an IPv6 LAN Prefix {"test2.domain.tld": "::2a0:00ff:111c:1234"}