# DNS Keeper A small but robust program to keep DNS records updated with your public _(external)_ IPv4 address. Mostly like DDNS but using API driven updates. Currently only gandi's liveDNS API is supported. ## How it works Every `POLL_INTERVAL` seconds, DNS Keeper will check if the IPv4 in the domain(s) is still valid by seeing if `DNS_KEEPER_RECORD`.`DNS_KEEPER_DOMAIN` still points to itself. > [!NOTE] > On startup DNS Keeper starts a detached thread with a UDP socket on which it answers > a random set of challenge bytes. > DNS Keeper will send an empty data-frame to its own socket using > the DNS resolved IPv4 address to see if it gets a response with the correct challenge bytes. > The challenge bytes are changed before every self-check. If DNS Keeper fails to get a response from itself for [3](./src/selfcheck.h#6) times it will check it's cached IP against the response of multiple external [services](./src/ipcheck.c#8) that return your public IPv4. If the returned public IP is the same as the cached one, DNS Keepr will see that as drift. If this happens too much it will revalidate its own cache against the self-record. If the returned public IP is different from the cached one, DNS Keeper will check the new IP using its own socket again, this time without DNS. If it proves to be correct it will update all A record of the specified `DOMAINS` who's value match the old IP to the new IP. The chached IP is only updated after the self-record is updated correctly. > [!NOTE] > DNS Keeper enforces a strict majority amongst the services. > If a strict majority cannot be reached or not enough services > were able to respond, it will take no action and reset the failed counter. > This is to prevent any issues should external services be compromised > and to avoid spamming these services in case something else is wrong. ## Environment Variables | Field | Descript | Default | | ------------------- | ---------------------------------------------------------------------------------------- | ------- | | `GANDI_API_TOKEN` | Gandi API Token with permission to "See and renew domain names". | | | `DOMAINS` | The domains _(eg. "example.noreal,demo.notreal")_ to keep the A records up to date of. | | | `DNS_KEEPER_PORT` | The port on which DNS Keepr runs its self-check UDP Socket. | 65535 | | `DNS_KEEPER_DOMAIN` | The domain on which the record pointing to dns-keeper lives. (eg. example.notreal). | | | `DNS_KEEPER_RECORD` | DNS record that points to your public IP/DNS-Keeper (eg. _dnsk). | | | `POLL_INTERVAL` | The interval (in seconds) at which DNS Keeper should check if it can still reach itself. | 5 | ## Setup You can the binary using the dynamically linked or static using make. ```sh # Dynamically linked make # Static: make STATIC=1 ``` The dynamically linked binary is smaller but requires dependencies: libcurl, libcjson and pthread to be on the target machine. The static binary is slightly bigger but is fully self contained. ### Docker Image The [Dockerfile](./Dockerfile) in this repo builds a minimal image with just the static binary and CA certificates. ```sh docker build -t dns-keeper . ``` > [!TIP] > Because the image is just the c binary with ca certs, there is no shell to exec into. > `docker exec` will not work for debugging.