Skip to content

liujed/dns01proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Proxy server for ACME DNS-01 challenges

dns01proxy is a server for using DNS-01 challenges to get TLS/SSL certificates from Let's Encrypt, or any ACME-compatible certificate authority, without exposing your DNS credentials to every host that needs a certificate.

It acts as a proxy for DNS-01 challenge requests, allowing hosts to delegate their DNS record updates during ACME validation. This makes it possible to issue certificates to internal or private hosts that can't (or shouldn't) have direct access to your DNS provider or API keys.

dns01proxy is designed to work with:

Features

  • Privilege separation. Internal or private hosts can complete DNS-01 challenges without having direct access to DNS API keys. In turn, the private keys for issued certificates stay private to the ACME clients.
  • HTTPS built-in, automatic, and always on. dns01proxy uses its configured DNS credentials to automatically get and renew its own TLS/SSL certificate.
  • Mandatory client authentication using HTTP Basic Authentication.
  • Optional per-client policies for limiting which DNS names each client can get a certificate for.

Installing dns01proxy

There are two options for getting dns01proxy.

Pre-compiled binaries

dns01proxy is built using Caddy, and uses DNS provider modules that are written by the Caddy community. dns01proxy ships a number of binaries, each built with a single DNS module. To install, just download a build of the latest release that matches your DNS provider.

Caution

Always check that you trust the author of the DNS module. The release notes has details about the source of the DNS module in each build.

Caddy module

Alternatively, dns01proxy is also available as a Caddy module, which adds dns01proxy to Caddy as a subcommand, app, and HTTP handler. See the caddy-dns01proxy project for more on this second option.

Configuring dns01proxy

dns01proxy is configured through a single TOML file. Below is an example configuration for running at https://dns01proxy.example.com with Cloudflare as a DNS provider.

hostnames = ["dns01proxy.example.com"]
listen = [":443"]

[dns.provider]
name = "cloudflare"
api_token = "{env.CF_API_TOKEN}"  # Reads from an environment variable.

# One for each user. Password is hashed using `dns01proxy hash-password`.
[[accounts]]
username = "AzureDiamond"
password = "$2a$14$N5bGBXf7zwAW9Ym7IQ/mxOHTGsvFNOTEAiN4/r1LnvfzYCpiWcHOa"
allow_domains = ["private.example.com"]

Each DNS provider has a different set of configuration parameters. See the Caddy documentation link for your provider in the release notes. Caddy documents its modules' options in JSON, but remember that you'll need to configure the module in TOML.

Full structure
# The server's hostnames. Used for obtaining TLS/SSL certificates.
hostnames = ["<hostname>"]

# The sockets on which to listen.
listen = ["<ip_addr:port>"]

# Configures the set of trusted proxies, for accurate logging of client IP
# addresses. This must be an `http.ip_sources` Caddy module. See Caddy's module
# documentation at https://caddyserver.com/docs/modules/
#
# Note that Caddy documents its modules' options in JSON. You'll need to
# configure the module in TOML. For example, to configure
# `http.ip_sources.static`:
#
#     [trusted_proxies]
#     source = "static"
#     ranges = ["10.0.0.1", "192.168.0.1"]
#
[trusted_proxies]
source = "<module_name>"
# •••  # Module-specific configuration goes here.

[dns]
# The TTL to use in DNS TXT records. Optional. Not usually needed.
ttl = "<ttl>"  # e.g., "2m"

# Custom DNS resolvers to prefer over system or built-in defaults. Set this to
# a public resolver if you are using split-horizon DNS.
resolvers = ["<resolver>"]

# The DNS provider for publishing DNS-01 responses. This must be a
# `dns.providers` Caddy module that is compiled into your dns01proxy binary.
# See the Caddy documentation link for your provider in the release notes:
# https://github.com/liujed/dns01proxy/releases
#
# Note that Caddy documents its modules' options in JSON. You'll need to
# configure the module in TOML. For example, to configure
# `dns.providers.cloudflare`:
#
#     [dns.provider]
#     name = "cloudflare"
#     api_token = "{env.CF_API_TOKEN}"  # Reads from an environment variable.
#
[dns.provider]
name = "<provider_name>"
# •••  # Module-specific configuration goes here.


# Configures HTTP basic authentication and the domains for which each user can
# get TLS/SSL certificates.
[[accounts]]
user_id = "<userID>"

# To hash passwords, use `dns01proxy hash-password`.
password = "<hashed_password>"

# These largely follow Smallstep's domain name rules:
#
#   https://smallstep.com/docs/step-ca/policies/#domain-names
#
# Due to a limitation in ACME and DNS-01, allowing a domain also allows
# wildcard certificates for that domain.
allow_domains = ["<domain>"]
deny_domains = ["<domain>"]

If you prefer JSON, then just use the same JSON structure as the configuration for the dns01proxy Caddy app.

Running dns01proxy

To run dns01proxy, use the run subcommand. For example,

dns01proxy run --config /usr/local/etc/dns01proxy.toml

Integrating with acme.sh

dns01proxy works with acme.sh's acmeproxy provider:

export ACMEPROXY_ENDPOINT='https://dns01proxy.example.com'
export ACMEPROXY_USERNAME='AzureDiamond'
export ACMEPROXY_PASSWORD='hunter2'
acme.sh --issue --dns dns_acmeproxy -d example.com

Integrating with lego

dns01proxy works with lego's httpreq DNS provider:

export HTTPREQ_ENDPOINT='https://dns01proxy.example.com'
export HTTPREQ_USERNAME='AzureDiamond'
export HTTPREQ_PASSWORD='hunter2'
lego --email [email protected] --dns httpreq -d example.com run

Integrating with Caddy

dns01proxy works with Caddy's acmeproxy DNS provider module:

{
  "endpoint": "https://dns01proxy.example.com",
  "username": "AzureDiamond",
  "password": "hunter2"
}

Acknowledgements

dns01proxy is a reimplementation of acmeproxy, which is no longer being developed. Whereas acmeproxy was built on top of lego, dns01proxy uses libdns under the hood, which allows for better compatibility with acme.sh.

acmeproxy.pl is another reimplementation of acmeproxy, written in Perl.