Code Monkey home page Code Monkey logo

zoneupdated's Introduction

zoneupdated

NOTE: zoneupdated is new software, in early release, and has not been thoroughly tested. Use at your own risk.

zoneupdated (pronounced Zone Update Dee), the DNS Zone File Update Daemon, updates a DNS Zone file when requested via an HTTP API. The API is designed to be compatible with the HTTP Request DNS Provider API from Lego. Lego is a library for obtaining SSL Certificates via ACME, such as from Let's Encrypt. Lego is used in many popular programs such as Traefik.

zoneupdated also extends the API slightly so it can be used for other kinds of updates, like updating an IP address when a DHCP lease is renewed.

API

zoneupdated's API is the same as the HTTP Request Api from Lego in default mode. It expects a POST at /zone-update/present to update or re-enable a disabled entry, or at /zone-update/cleanup to disable an entry.

NOTE: the URL prefix /zone-update can be changed by configuration if desired.

The body of the POST requst should be JSON containing two fields, fqdn and value as follows:

{
   "fqdn": "_acme-challenge.domain.",
   "value": "LHDhK3oGRvkiefQnx7OOczTY5Tic_xZ6HcMOc_gmtoM"
}

fqdn specifies the entry to update, value specifies the value to give the TXT record.

When the POST request is received, zoneupdated will search the zone file for a TXT record for that FQDN and update its value if found. The record may be commented out, in which case zoneupdated will also uncomment it (for the present call). In the case of a cleanup call, zoneupdated will comment out the entry.

zoneupdate will not add a new entry that doesn't already exist in the file. You must manually add it first. You can add it commented out with a dummy value if you don't want any initial value.

When updating the file, zoneupdated also updates the serial number. It also writes the new file to a temporary file and then moves it into place, so the program reading the file will not see a partially written file.

NOTE: zoneupdated currently doesn't offer any way to signal another program when the file has been changed. I use it with CoreDNS which automatically detects changes zone files and reloads them. Pull requests that add signaling another process or running a program on change will be considered.

CNAME Support

It is often desirable to keep the dynamic DNS entries in a separate zone with a shorter TTL, and to limit access to update the main zone. Let's Encrypt for example supports CNAMEs from the domain for which a certificate is being requested to a second zone. This could be set up as follows:

; Zone example.com
_acme-challenge IN CNAME MKW4X6GK7F3M2IKUUZX7X6LMYJB4HOZY.dyn.example.com 
; Zone dyn.example.com
MKW4X6GK7F3M2IKUUZX7X6LMYJB4HOZY IN TXT "LHDhK3oGRvkiefQnx7OOczTY5Tic_xZ6HcMOc_gmtoM"

To support this case, in addition to looking for fqdn in the zone file, zoneupdated will also look for an entry with the base32 encoded SHA-1 of the fqdn that was passed in.
An easy way to find this value, when adding a new domain, is to make a request to zoneupdate with, eg, cURL. If neither the fqdn nor its hash are found, both will be included in the HTTP response:

Did not find record for _acme-challenge.example.com or MKW4X6GK7F3M2IKUUZX7X6LMYJB4HOZY with RRTYPE TXT

This information will also be included in the log.

Note that the dynamic zone containing the targets of the CNAME doesn't need to be a subdomain of the zone containing the CNAME. You can have CNAMEs from many different domains pointing to the same dynamic domain and use a single instance of zoneupdated to update it for all of them.

NOTE: SHA-1, now considered cryptographically week, is only being used as a hash to create a realtively short unique identifier for the FQDN. The correspondence between the fqdn and its hash is public, so the hash does not need to be generated by a strong one-way hash function.

Address and other updates

To support other use cases like updating an A or AAAA record, zoneupdated extends the Lego API with an optional field rrtype in the request JSON. This defaults to TXT if not given, for compatibility with Lego.

You can set up A and or AAAA (or any other kind) of entries in the zone file and update them with a script invoked by the DHCP client when a new address is obtained. The script could POST data such as:

{
   "fqdn": "my-home-ip",
   "rrtype" : "A",
   "value": "192.0.2.1"
}

Note that to support this kind of use, zonedupdated does not require that fqdn actually be a fully qualified domain name. You may also still use the CNAME approach with a hash if you like. In this case the hash looked for in the zone file will be the hash of whatever is passed, not the actual full FQDN.

Zone Serial Updates

zoneupdated will not replace the zone file if an API call results in no actual change, eg present of an entry where the value has not changed, cleanup of an entry that is already commented out, etc.

However, whenever it does modify the file, it will update the serial number. zoneupdated looks for a line consisting of a number, followed by a comment that says "serial". For example:

                        2020053001      ; serial

This is compatible with the common format of SOA records at the top of a zone file, eg:

@                       IN SOA          ns01.example.com.       hostmaster.example.com. (
                        2020053001      ; serial
                        3H              ; refresh
                        1H              ; retry
                        7D              ; expire
                        1M)             ; negcache TTL

By default zoneupdate generates date-based serials (eg the one above shows the first update on May 30th, 2020). Subsequent updates on the same day increment the last two digits. If more than 100 updates happen onthe same day, the serial number will start to roll into the next day, but this causes no issues other than it perhaps lookig a little confusing if the serial is "in the future")

The first update on a subsequent day will start with a serial based on that day's date with "01" as the last two digits, unless the previous day has rolled over, in which case it will simpy carry on incrementing from where it left off.

If you find that you are often doing more than 100 updates in a day, or simpy prefer not to use date-based serials, the option --sequential-serial (or ZUPD_SEQUENTIAL_SERIAL=true in the environment) and zoneupdate will only ever increment the serial and not jump to a new date-based serial for the first update of a day.

Locking

zoneupdate uses a lock file to prevent concurrent update attempts from corrupting the file. This applies both to multple requests to the same zoneupdated process, or to multiple instances of zoneupdate, eg multple processes run for redundancy.

To support this, it is important that the filesystem where the zone file resides support POSIX file locking.

Example Zone File

This may be useful as the starting point for your dynamic zone file. It demonstrates fqdn, hashed, and non-TXT records that can be updated. The hash-based entry demonstrates a commented-out entry that zoneupdate would be able to uncomment and update on a present call.

$TTL 1M
;1D
@                       IN SOA          ns01.example.com.       hostmaster.example.com. (
                        2020053001      ; serial
                        3H              ; refresh
                        1H              ; retry
                        7D              ; expire
                        1M)             ; negcache TTL
                        IN NS           ns01.example.com.
                        IN NS           ns02.example.com.

_acme-challenge.dyn.example.com IN TXT  "JDG7FDdhb..."
test                    IN A            192.0.2.1
;VFFI7ZOMWGN2MHCMBBZ5HEPJQ6MC7O6T       IN TXT "H6bFD7Ghj8bh..."

Configuration

zoneupdated offers a variety of configuration options to fine-tune its behavior. Each command line option shown below could also be provided as an environment variable. To find the correstponding environment variable name, replace the initial dashes with ZUPD_, uppecase the remainder and replace dashes with underscores. For example, instead of --http-timeout=60 you could use ZUPD_HTTP_TIMEOUT=60 in the environment. For boolean flags that don't take a value, use true as the value, eg ZUPD_TEST=true.

HTTP options

These options controll the HTTP API service provided by zoneupdated.

  • --listen specifies the port and optionally IP where zoneupdated will provide HTTP(S) service. the value should be a optional hostname or IP followed by a colon folowed by the port number. If no address/IP is provided, zoneupdated listens on all interfaces.

  • --http-timeout specifies for how long zoneupdated should wait trying to service a request before aborting.

  • --trust-proxy Set this if running behind a trusted reverse proxy such as Traefik or nginx so that logging can refer to the IP of the originating client and not that of the proxy. Do not enable this if zoneupdate is directly exposed to callers as it will allow them forge a different IP as the requester.

  • --url-prefix Normally the endpoints supported by zoneupdated are /zone-update/present and /zone-update/cleanup. With this option a different initial prefix may be configured, replacing the /zone-update portion that is expected by default.

  • --tls-cert Together with --tls-key enables zoneupdated to speak HTTPS instead of HTTP. The value should be a filename of a file containing the complete certificate chain (root CA, any intermediaries, and finally the certificate zoneupdated should use) in PEM format. Obviously attempting to use zoneupdated with a certificate obtained from an ACME provider authenticated by updates to a zone that zoneupdated is managing can create a chicken and egg problem, but it may be useful in cases where zoneupdated is run using certificates signed by a private CA that the client trusts.

  • --tls-key the filename of a file containing the PEM format key corresponding to the configured certificate.

  • --robots-txt serve GET requests for /robots.txt. Useful if zoneupdated is running behind a reverse proxy like Traefik and you want to disable web crawlers from trying to access APIs, without having to set up a static file server just for that one file. Note that the file is always served from the root and is unaffected by --url-prefix, since robots would not look for it anywhere else.

NOTE: zoneupdated will reload the certificate on receiving a SIGHUP, so that certificates can be rotated without restarting.

Authentication Options

By default zoneupdated does no authentication of incoming requests. This can be provided by a reverse proxy, or zoneupdated can be configured to use HTTP Basic Authentication, which is the mechanism Lego supports. The following options control the allowable users and passwords.

The --http-user and --http-password options, or especially there encironment variable equivalents, may be more conventient in the case where zoneupdated has only a single client accessing it.

The file-based option is useful if more than one client will access zoneupdated and to update the password without restarting. The file consists of allowable logins, one per line, with the user name and then password delimited by whitespace. The passwords are in plaintext, so make sure the file is well secured. This option may be more convenient when using something like Vault Agent to render a template containing multiple users.

It is not possible to use both options for authentication.

If configured, /robots.txt is not protected by basic auth.

These options control authentication:

  • --http-auth-realm the authentication realm zoneupdate will use. Generally you shouldn't need to set this for Lego-based clients.
  • --http-user the username of a user that will be allowd access
  • --http-password the password to use for the --http-user.
  • --http-auth-file the name of a file containing one or more users. See above for the format.

Zone Update Options

  • --sequential-serial See the discussion above under "Zone Serial Updates"
  • --test in this mode, the zone file will not be updated, regrdless of the success or failure of the API call, and the temporary file will be left in place instead of deleted. This feature is intended for testing.

Docker

Docker images are provided on Docker Hub.

The docker image is very compact and lightweight. It consists only of the statically linked binary, and is FROM scratch (meaning it has no base image).

Docker images are currently built for amd64 and arm64. Use the generic tag name instead of the architecture-specific ones (eg latest instead of latest-amd64) and the correct version should be used automatically. Use the latest tag at your own risk as an update to a newer version with incomatible changes might break your setup. It's better to reference a specific version and upgrade to new versions only after consulting the CHANGELOG, testing in your environment, etc.

When used with Docker, environment variables are preferred for configuration. Only the zone file name needs to be provided as a command line argument. A volume should be mapped in that is sharred with your DNS server software. Ideally for security the DNS server could have read-only access to all zone files, while zoneupdated could be given read-write access only to a subdirectory containing the zone file to be updated.

zoneupdated's People

Contributors

tsarna avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.