diff --git a/README.md b/README.md index 3218b9f..7fba2bd 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,68 @@ -# dns-keeper +# DNS Keeper -A security-hardened dynamic DNS updater with self-verification and multi-API IP consensus. \ No newline at end of file +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 with +> 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. \ No newline at end of file