|
| 1 | +# dns01proxy package for Caddy |
| 2 | + |
| 3 | +[**dns01proxy**](https://github.com/liujed/dns01proxy) is a server for using |
| 4 | +DNS-01 challenges to get TLS/SSL certificates from Let's Encrypt, or any |
| 5 | +ACME-compatible certificate authority, without exposing your DNS credentials to |
| 6 | +every host that needs a certificate. |
| 7 | + |
| 8 | +This repository hosts and documents the dns01proxy Caddy package. If you want |
| 9 | +to use dns01proxy as part of [Caddy](https://caddyserver.com/), then you're in |
| 10 | +the right place! Otherwise, the [dns01proxy |
| 11 | +project](https://github.com/liujed/dns01proxy) distributes a standalone |
| 12 | +dns01proxy server as a precompiled binary, which is recommended for most users. |
| 13 | + |
| 14 | +## Installing |
| 15 | + |
| 16 | +This dns01proxy Caddy package provides: |
| 17 | +* a `dns01proxy` command for running Caddy as a standalone dns01proxy server, |
| 18 | +* an `http.handlers` module that implements the dns01proxy API, and |
| 19 | +* a Caddy application module that implements the dns01proxy server. |
| 20 | + |
| 21 | +To use this package, it needs to be compiled into your Caddy binary, along with |
| 22 | +the [`dns.provider.*` modules](https://caddyserver.com/docs/modules/) for your |
| 23 | +DNS providers. You can build your custom Caddy binary by using |
| 24 | +[`xcaddy`](https://caddyserver.com/docs/build#xcaddy) or by using [Caddy's |
| 25 | +download page](https://caddyserver.com/download). |
| 26 | + |
| 27 | + |
| 28 | +## Using the command line |
| 29 | + |
| 30 | +This package adds a `dns01proxy` command to Caddy, making it convenient to run |
| 31 | +a standalone dns01proxy server. Naturally, because dns01proxy runs on Caddy, |
| 32 | +TLS/SSL certificates for the dns01proxy server itself are automatically |
| 33 | +obtained and renewed using the configured DNS credentials. |
| 34 | + |
| 35 | +To run dns01proxy, just provide a config file: |
| 36 | +``` |
| 37 | +caddy dns01proxy --config dns01proxy.json |
| 38 | +``` |
| 39 | + |
| 40 | +Here is an example configuration for running at `https://dns01proxy.example.com` |
| 41 | +with Cloudflare as a DNS provider. The user's password is hashed using `caddy |
| 42 | +hash-password` with the bcrypt algorithm. |
| 43 | +```json |
| 44 | +{ |
| 45 | + "hostnames": ["dns01proxy.example.com"], |
| 46 | + "listen": [":443"], |
| 47 | + "dns": { |
| 48 | + "provider": { |
| 49 | + "name": "cloudflare", |
| 50 | + "api_token": "{env.CF_API_TOKEN}" |
| 51 | + } |
| 52 | + }, |
| 53 | + "accounts": [ |
| 54 | + { |
| 55 | + "username": "AzureDiamond", |
| 56 | + "password": "$2a$14$N5bGBXf7zwAW9Ym7IQ/mxOHTGsvFNOTEAiN4/r1LnvfzYCpiWcHOa", |
| 57 | + "allow_domains": ["private.example.com"] |
| 58 | + } |
| 59 | + ] |
| 60 | +} |
| 61 | +``` |
| 62 | + |
| 63 | +<details> |
| 64 | +<summary>Full JSON structure</summary> |
| 65 | + |
| 66 | +```jsonc |
| 67 | +{ |
| 68 | + // The server's hostnames. Used for obtaining TLS/SSL certificates. |
| 69 | + "hostnames": ["<hostname>"], |
| 70 | + |
| 71 | + // The sockets on which to listen. |
| 72 | + "listen": ["<ip_addr:port>"], |
| 73 | + |
| 74 | + // Configures the set of trusted proxies, for accurate logging of client IP |
| 75 | + // addresses. |
| 76 | + "trusted_proxies": { |
| 77 | + // an http.ip_sources module |
| 78 | + "source": "<module_name>", |
| 79 | + // ••• |
| 80 | + }, |
| 81 | + |
| 82 | + "dns": { |
| 83 | + // The DNS provider for publishing DNS-01 responses. |
| 84 | + "provider": { |
| 85 | + // A `dns.providers` module. |
| 86 | + "name": "<provider_name>", |
| 87 | + // ••• |
| 88 | + }, |
| 89 | + |
| 90 | + // The TTL to use in DNS TXT records. Optional. Not usually needed. |
| 91 | + "ttl": "<ttl>", // e.g., "2m" |
| 92 | + |
| 93 | + // Custom DNS resolvers to prefer over system or built-in defaults. Set |
| 94 | + // this to a public resolver if you are using split-horizon DNS. |
| 95 | + "resolvers": ["<resolver>"] |
| 96 | + }, |
| 97 | + |
| 98 | + // Configures HTTP basic authentication and the domains for which each user |
| 99 | + // can get TLS/SSL certificates. |
| 100 | + "accounts": [ |
| 101 | + { |
| 102 | + "user_id": "<userID>", |
| 103 | + |
| 104 | + // To hash passwords, use `caddy hash-password`. |
| 105 | + "password": "<hashed_password>", |
| 106 | + |
| 107 | + // These largely follow Smallstep's domain name rules: |
| 108 | + // |
| 109 | + // https://smallstep.com/docs/step-ca/policies/#domain-names |
| 110 | + // |
| 111 | + // Due to a limitation in ACME and DNS-01, allowing a domain also allows |
| 112 | + // wildcard certificates for that domain. |
| 113 | + "allow_domains": ["<domain>"], |
| 114 | + "deny_domains": ["<domain>"] |
| 115 | + } |
| 116 | + ] |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +</details> |
| 121 | + |
| 122 | +## Integrating into a Caddyfile |
| 123 | + |
| 124 | +This package provides the following Caddyfile handler directive. |
| 125 | +``` |
| 126 | +dns01proxy { |
| 127 | + # The DNS provider for publishing DNS-01 responses. Optional. If this is |
| 128 | + # omitted, then the global `acme_dns` and `dns` options are used as |
| 129 | + # fallbacks, but at least one of the three must be configured. |
| 130 | + dns <provider_name> [<params...>] |
| 131 | +
|
| 132 | + # The TTL to use in DNS TXT records. Optional. Not usually needed. |
| 133 | + dns_ttl <ttl> |
| 134 | +
|
| 135 | + # Custom DNS resolvers to prefer over system or built-in defaults. Set this |
| 136 | + # to a public resolver if you are using split-horizon DNS. |
| 137 | + resolvers <resolvers...> |
| 138 | +
|
| 139 | + # Configures a single user. Can be given multiple times. |
| 140 | + user <userID> { |
| 141 | + # Configures HTTP basic authentication for the user. This is optional. If |
| 142 | + # this is omitted, then an authentication handler must come before this one |
| 143 | + # in the handler chain. To hash passwords, use `caddy hash-password` with |
| 144 | + # the bcrypt algorithm. |
| 145 | + password <hashed_password> |
| 146 | +
|
| 147 | + # Determines the domains for which the user can get TLS/SSL certificates. |
| 148 | + # This largely follows Smallstep's domain name rules: |
| 149 | + # |
| 150 | + # https://smallstep.com/docs/step-ca/policies/#domain-names |
| 151 | + # |
| 152 | + # Due to a limitation in ACME and DNS-01, allowing a domain also allows |
| 153 | + # wildcard certificates for that domain. |
| 154 | + allow_domains <domains...> |
| 155 | + deny_domains <domains...> |
| 156 | + } |
| 157 | +} |
| 158 | +``` |
| 159 | + |
| 160 | +Here is an example Caddyfile for running dns01proxy as a standalone server that |
| 161 | +automatically obtains and renews its own TLS/SSL certificate: |
| 162 | +``` |
| 163 | +{ |
| 164 | + acme_dns cloudflare {env.CF_API_TOKEN} |
| 165 | + cert_issuer acme { |
| 166 | + disable_http_challenge |
| 167 | + disable_tlsalpn_challenge |
| 168 | + } |
| 169 | +} |
| 170 | +
|
| 171 | +dns01proxy.example.com { |
| 172 | + log |
| 173 | + @endpoints { |
| 174 | + path /present /cleanup |
| 175 | + } |
| 176 | + handle @endpoints { |
| 177 | + dns01proxy { |
| 178 | + user AzureDiamond { |
| 179 | + password $2a$14$N5bGBXf7zwAW9Ym7IQ/mxOHTGsvFNOTEAiN4/r1LnvfzYCpiWcHOa |
| 180 | + allow_domains private.example.com |
| 181 | + } |
| 182 | + } |
| 183 | + } |
| 184 | + respond 404 |
| 185 | +} |
| 186 | +``` |
| 187 | + |
| 188 | +## Configuring a dns01proxy handler in JSON |
| 189 | + |
| 190 | +The package also provides a `dns01proxy` HTTP handler. This example configures |
| 191 | +a handler similar to the one in the Caddyfile example above. |
| 192 | +```json |
| 193 | +{ |
| 194 | + "dns": { |
| 195 | + "provider": { |
| 196 | + "name": "cloudflare", |
| 197 | + "api_token": "{env.CF_API_TOKEN}" |
| 198 | + } |
| 199 | + }, |
| 200 | + "accounts": [ |
| 201 | + { |
| 202 | + "user_id": "AzureDiamond", |
| 203 | + "password": "$2a$14$N5bGBXf7zwAW9Ym7IQ/mxOHTGsvFNOTEAiN4/r1LnvfzYCpiWcHOa", |
| 204 | + "allow_domains": ["private.example.com"], |
| 205 | + } |
| 206 | + ] |
| 207 | +} |
| 208 | +``` |
| 209 | + |
| 210 | +<details> |
| 211 | +<summary>Full JSON structure</summary> |
| 212 | + |
| 213 | +```jsonc |
| 214 | +{ |
| 215 | + "dns": { |
| 216 | + // The DNS provider for publishing DNS-01 responses. |
| 217 | + "provider": { |
| 218 | + // a dns.providers module |
| 219 | + "name": "<provider_name>", |
| 220 | + // ••• |
| 221 | + }, |
| 222 | + |
| 223 | + // The TTL to use in DNS TXT records. Optional. Not usually needed. |
| 224 | + "ttl": "<ttl>", // e.g., "2m" |
| 225 | + |
| 226 | + // Custom DNS resolvers to prefer over system or built-in defaults. Set |
| 227 | + // this to a public resolver if you are using split-horizon DNS. |
| 228 | + "resolvers": ["<resolver>"] |
| 229 | + }, |
| 230 | + |
| 231 | + // Configures HTTP basic authentication (optional) and the domains for which |
| 232 | + // each user can get TLS/SSL certificates. |
| 233 | + // |
| 234 | + // Passwords are optional here. If they are omitted, then an authentication |
| 235 | + // handler must come before this one in the handler chain. To hash passwords, |
| 236 | + // use `caddy hash-password` with the bcrypt algorithm. |
| 237 | + "accounts": [ |
| 238 | + { |
| 239 | + "user_id": "<userID>", |
| 240 | + "password": "<hashed_password>", |
| 241 | + "allow_domains": ["<domain>"], |
| 242 | + "deny_domains": ["<domain>"] |
| 243 | + } |
| 244 | + ] |
| 245 | +} |
| 246 | +``` |
| 247 | + |
| 248 | +</details> |
| 249 | + |
| 250 | +## Configuring a dns01proxy app in JSON |
| 251 | + |
| 252 | +To configure dns01proxy as a Caddy app, use the same JSON structure as the |
| 253 | +configuration file for the [`dns01proxy` command](#using-the-command-line). |
| 254 | + |
| 255 | +## Acknowledgements |
| 256 | + |
| 257 | +dns01proxy is a reimplementation of |
| 258 | +[acmeproxy](https://github.com/mdbraber/acmeproxy/), which is no longer being |
| 259 | +developed. Whereas acmeproxy was built on top of lego, dns01proxy uses |
| 260 | +[libdns](https://github.com/libdns/libdns) under the hood, which allows for |
| 261 | +better compatibility with acme.sh. |
| 262 | + |
| 263 | +[acmeproxy.pl](https://github.com/madcamel/acmeproxy.pl) is another |
| 264 | +reimplementation of acmeproxy, written in Perl. |
0 commit comments