Crates.io | clouddns-nat-helper |
lib.rs | clouddns-nat-helper |
version | 0.2.13 |
source | src |
created_at | 2022-10-10 22:20:31.790032 |
updated_at | 2024-06-09 23:11:30.83959 |
description | Autogenerate A records for NAT setups from AAAA records in cloud providers |
homepage | |
repository | https://github.com/spacebird-dev/clouddns-nat-helper |
max_upload_size | |
id | 684911 |
size | 193,184 |
A utility to automatically generate Ipv4 A
DNS records for hosts based on existing AAAA records in a DNS zone.
This tool was written with a the following scenario in mind:
So, when would this scenario ever pop up? Well, when you are hosting a dual-stack Kubernetes cluster from a residential ISP connection for example! Most ISPs hand out a single dynamic public IPv4 address, as well as a public IPv6 prefix.
Routing the Ipv6 traffic is "easy" enough:
Diagram of the above setup:
(Prefixes and config have been simplified slightly)
However, this falls apart with IPv4 addresses, as we don't have a public IPv4 network to assign to the k8s cluster. We can use an internal Ipv4 network to get service behind our NAT and then configure our NAT Router to port forward to those addresses, but external-dns has no idea how to handle this situation. It will just push the internal Ipv4 addresses into public DNS, which is of course complete nonsense.
One approach to solve this would be to write a script that gets the public IP address, then injects that into the external-dns config as a hardcoded value1.
Another approach (which is what this tool does) is to configure external-dns to only publish AAAA records, then look for AAAA records without an associated A record and generate them.
This tool operates in 3 basic steps:
nat-helper also keeps track of domain ownership using TXT records (or potentially another registry in the future), meaning that it knows which domains A records were created by it, and which ones weren't. This also allows us to track changes, update records when they become outdated and delete A records for a owned domain when there are no more AAAA records.
This project is intended for experimental, hobbyist and other non-production uses. That said, it is built it with reliability, safety and extensibility in mind. Still, use it at your own risk. Breaking changes may occur in future releases if needed.
Providers, Registries and Ipv4Sources use pluggable interfaces, so adding new ones in the future should be simple.
You can download linux binaries from the releases page.
If you have cargo
installed, simply run
cargo install clouddns-nat-helper
Docker images are automatically built and pushed to the following registries:
Notes:
:0.2
) to ensure that no breaking changes occurlatest
tag points to this repositories master branch and may break at any time.amd64
,arm64
. The images are multi-arch images, so there is no need to specify a arch tagTo pass arguments to the image, use environment variables or an environment file:
$ docker run --env-file ./.env maxhoesel/clouddns-nat-helper:0.1
$ cat .env
# there are more configuration options available, run with --help, check the README and see src/bin/cli/mod.rs for more details
CLOUDDNS_NAT_PROVIDER=cloudflare
CLOUDDNS_NAT_CLOUDFLARE_API_TOKEN=abc123456789
CLOUDDNS_NAT_SOURCE=hostname
CLOUDDNS_NAT_IPV4_HOSTNAME=maxhoesel.de
You can also create your own container by running: docker build
in the root of this project.
The officially recommanded way to install clouddns-nat-helper
is through Helm.
First, install the repository like so:
helm repo add spacebird https://charts.spacebird.dev
Then, install the chart:
helm install clouddns-nat-helper spacebird/clouddns-nat-helper \
--create-namespace
--namespace clouddns-nat-helper
--values values.yml
(Almost) all flags can be passed via a command-line or as an environment variable.
See clouddns-nat-helper --help
for a list of all flags
clouddns-nat-helper -s hostname -p cloudflare --ipv4-hostname <yourdomain.invalid> --cloudflare-api-token <your_cf_api_token>
-s
specifies the IPv4 source to use. Here, hostname is used to resolve a hostname to an IP address
--ipv4-hostname
specifies the hostname that you want to resolve to its IP address-p
specifies the DNS provider to use
--cloudflare-api-token
is your API token. You may want to pass this via an environment variable (CLOUDDNS_NAT_CLOUDFLARE_API_TOKEN
) for increased securitySome other useful options:
--dry-run/-d
: Preview what changes will be made--run-once
: Set this if you just want to run the tool once--interval/-i
: Set a different interval between runs from the default of 60 secondsAs mentioned above, this tool will NOT touch any records that it did not create/does not own. On its own, this should prevent any conflicts with manually entered IPv4 addresses or other DNS automation.
However, if you want to be extra careful or are running into a situation where this is not the case, you can limit the allowed actions even further.
NOTE
If you want to manually change an A record that was previously managed by this tool, you need to remove its ownership information first.
For the TXT registry (default), delete the ownership TXT record associated with that domain (look for a TXT record for the affected domain with clouddns
in it).
Deleting this record will remove ownership of the domain and the tool will no longer messs with your manual entry
The --policy
flag can be used to limit the actions that this tool may perform on records. Options are:
createonly
: Don't modify any records, only create new ones. This breaks record updates and will not work with a dynamic IPv4 addressupsert
: Create records and update existing ones, but don't delete A records if their corresponding AAAA records get removedsync
(default): Perform create, update and delete actions as neededTo begin development on this project, follow the steps below:
cargo install cargo-make --locked
This project uses an up-to-date version of Rust and cargo-make
for builds.
Most common actions can be performed by running cargo make <command>
.
See cargo make --list-all-steps
for a list of available actions.
cargo make lint
cargo make build
cargo make -p release build
This project uses cross
to cross-compile binaries for different target platforms.
You can create a binary for a different target like so:
cargo make build-aarch64-unknown-linux-gnu
cargo make -p release build-aarch64-unknown-linux-gnu
To see which targets are available, run cargo make --list-category-steps build
cargo make test
cargo make test-aarch64-unknown-linux-gnu
cargo make coverage
cargo make docs
cargo make docker
cargo make docker-arm64
cargo-make
will automatically generate an appropriate builder.cargo make -e DOCKER_TAG=registry.invalid/user/project:0.1.2 docker
Draft Releases are automatically managed through the version-maintenance
workflow.
Follow the instructions in those drafts to publish a new release.
Note that this requires running two versions of external-dns, one for IPv4 with the hardcoded value, and one for IPv6. It might get messy ↩