Skip to content

Latest commit

 

History

History
145 lines (108 loc) · 4 KB

README.md

File metadata and controls

145 lines (108 loc) · 4 KB

BIND9 API

Travis Build Status License License

This is an attempt to implement an API to create, update or delete DNS records on a BIND9 DNS server.

Building

To compile the code, you first need to install Rust. Then you can run

cargo build --release

in the project root. The server and client binary will be located in ./target/release/bind9-api and ./target/release/bind9-api-client respectively.

Server

The server will wait for incoming requests and uses the nsupdate command to perform operations on the BIND9 nameserver. For the server to work, a DNS key is needed to perform the updates.

$ dnssec-keygen -r /dev/urandom -a HMAC-SHA256 -b 256 -n HOST dnskey

Copy the Key section of the resulting Kdnskey*.private file into a file that looks like this:

key "dns-key" {
    algorithm hmac-sha256;
    secret "<your secret>";
}

And extend the zone section of the zones you'd like to modify in your named.conf.local

zone "example.com" {
    type master;
    file "/var/lib/bind/db.example.com";
    ...
    allow-update { key "dns-key"; };
    ...
}

Now you can start the server:

$ ./bind9-api -k <path to dnskey> -t <your api token>

By default, the server will bind to 0.0.0.0:8000. The host and port to bind to, can be changed using the -h and -p flags respectively. For production use, you should bind to a private IP address (LAN or VLAN) or to 127.0.0.1 and put the server behind a reverse proxy that offers TLS.

Client

The client is used to perform changes to the DNS zone from any server. My use case is to perform LetsEncrypt DNS challenges. The client will look for a configuration file in /etc/bind9apiclient.toml which looks like this:

# API server host
host = "http://127.0.0.1:8080"
# API secret
secret = "topsecret"

The client can perform two operations: Creating/updating and deleting DNS records. The client is invoked like this

$ ./bind9-api-client -d foo.example.com -r TXT update -v foobar
$ ./bind9-api-client -d foo.example.com -r TXT delete

API Description

POST /record
X-Api-Token: <api-token>

{
    "name": "foo.example.com",
    "value": "127.0.0.1",
    "record": "A",
    "ttl": 1337
}
DELETE /record
X-Api-Token: <api-token>

{
    "name": "foo.example.com",
    "record": "A"
}

The API token is a SHA256 HMAC over the request body using a pre-shared secret.

Security Considerations

The current API design does not migrate replay attacks. An attacker that is able to intercept a request to the API can resend the same request again to execute the same operation. To prevent these kinds of attacks, you should use a reverse proxy and encrypt the connections using TLS. Future versions of the server might provide TLS functionality by itself.

Usage with LetsEncrypt

In letsencrypt/, two example scripts can be found to use the client as a certbot hook for DNS challenges. It assumes that the client is located somewhere in $PATH and that the configurations file exists.

To obtain a new certificate, certbot can be invoked as followed:

certbot certonly -n --agree-tos --server https://acme-v02.api.letsencrypt.org/directory --preferred-challenges=dns-01
--manual --manual-auth-hook /usr/lib/letsencrypt-bind9/certbot-bind9-auth --manual-cleanup-hook
/usr/lib/letsencrypt-bind9/certbot-bind9-cleanup --manual-public-ip-logging-ok -d example.com -d '*.example.com'

License

This project is licensed under either of

at your option.