GithubHelp home page GithubHelp logo

joohoi / acme-dns Goto Github PK

View Code? Open in Web Editor NEW
2.0K 47.0 228.0 25.86 MB

Limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely.

License: MIT License

Go 98.55% Shell 0.71% Dockerfile 0.74%
acme-challenge acme-dns dns-server tls-certificate letsencrypt

acme-dns's Issues

How do I add the CNAME record to the server?

I can see in the video how to get the CNAME using dig, but how do I actually ADD the record? I think, this is missing in the video.

Sorry for asking such a dumb question. I am a developer :)

Bad Subdomain

Im getting a bad subdomain currently , Ill take down this instance once i get it resolved but :

## Acme-DNS Register
curl -X "POST" "http://159.65.179.47/register"
## Acme-DNS Update
curl -X "POST" "http://159.65.179.47/update" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -H 'X-Api-Key: n8o2nd7E4JtqWlTEbyEZAjs5mZr1wc8Ehju2SNhG' \
     -H 'X-Api-User: 105f0386-6d4b-41ca-9c17-d5a0481e7e36' \
     -d $'{
  "txt": "test",
  "subdomain": "cc3ddadd-0c05-4e5e-8d3f-2d2b72e9c083"
}'

Response :

{ error : 'bad_subdomain'}

Is there something im doing wrong?

Restrict registration

Given that this DNS server is going to be used to authorise requests for SSL infrastructure, it would be nice to be able to restrict registration requests being sent to the server.

The ability to set a password in the configuration, then have this checked when registration requests are made to the server then deny them if incorrect/not provided would be pretty great.

If it would be possible to add an option to disable registration, it'd be appreciated.

Thanks in advance for your consideration.

What is the purpose of having both username and password?

In the current acme-dns design, each subdomain registration generates a random username and password to authenticate with when updating records. But why have both a username and password when a single password or api token value would do?

In most authentication setups, you have both because the username can be exposed on user facing UI and is considered more or less public info. But in this architecture, the username is kept secret for the duration of its lifetime. So it's really just like you have two passwords that have to be used together. So why not combine them into one value and reduce the complexity a bit?

systemd socket activation

systemd provides socket activation as an option for listening services, and is particularly handy for services that listen on privileged ports. It would be useful to be able to operate a very infrequently-accessed service like this via on-demand activation.

It looks like miekg/dns already supports socket activation via ActivateAndServe (analogous to ListenAndServe), and coreos/go-systemd provides a handy activation abstraction.

(And because you can configure multiple listeners, it would be easy to also grab the listener for HTTP from systemd as well.)

TCP or UDP? Why not both?

acme-dns has a config option that lets you choose whether to serve DNS requests over UDP or over TCP.

However, RFC7766 requires that:

All general-purpose DNS implementations MUST support both UDP and TCP transport.

And unfortunately, "both" doesn't seem to be an option.

Allow more than two records?

In my scenario acme-dns is hosted on the same machine as the http server that requests certificate, so it can renew certificates automatically forever (with acme credentials stored on local disk).

However, whenever the whole server is migrated to another machine, subdomain changes unless I migrate the local auth data that those two services established between each other on old machine.

Since subdomain changes, I need to manually update _acme-challenge to newly generated subdomain so that acme-dns on new machine can receive DNS requests. Since I don't want to update many records, I reuse the same acme-dns subdomain for multuple domains in a certificate. I.e. I point _acme-challenge of multiple domains (i.e. foo.example.com, bar.example.com, example.com, *.example.com) to a single acme-challenge.example.com, and then acme-challenge.example.com to long-acme-generated-domain.acme-dns.example.com. In that case when a machine migrated and generated subdomain changed, I only need to update one mapping (from acme-challenge.example.com to long-acme-generated-domain.acme-dns.example.com, but not each individual subdomain that the certficates are generated for).

However, it appears in that case ACME challenge does not succeed reliably, as new records override old ones, and when I want to verify say 5 domains, only two get valid records.

So I guess several things could be done to make it better:

  • Support rolling update of 10 records rather than 2. This seems like a one-line change, but I wonder if the certificate issuers will be confused by seeing 10 records.
  • Add local mode that does not have authentication, and instead lets client choose subdomains and records for them. In that case I could set up mapping from my domains to acme-dns subdomains once, and it would remain the same whatever migration between machines happen.
  • I could store auth data and database of acme-dns when moving between machines. This sounds strange, as it really feels that such data doesn't need to be persistently stored. It is also inconvenient if apart from those credentials, the server is stateless.
  • For multi-domain certificate do updates and verification one-by-one, rather than current behaviour (of acme.sh) to update all txt records, and then verify all domains.
  • Even without local mode (even though keeping track of login/password in local mode feels silly), how about we allow client to choose subdomain name? That way clients could have some deterministic mapping from their domain names to acme-dns domain names (i.e. hash with salt) and register accordingly. However when acme-dns is deployed locally, it would get advantage that if it gets redeployed (i.e. due to the whole stack being migrated to another machine), even though registration records would get lost, client process could re-do registration, and preserve the same acme-dns subdomains, hence no need to manually update CNAME records.

I guess in my case (again, local mode), I'd be happy with even simpler case:

  • A tiny DNS server
  • That can receive unauthenticated instructions like "for domain foo.bar.example.com" set TXT records to ['abc', 'xyz'].
  • ...and then keep track of those mappings and respond to DNS requests accordinlgy.

It seems in my case the complexity of acme-dns (which was designed to be deployed publicly and used by many clients) gets in the way.

dynamic dns

The acme-dns server seems to be responding to dynamic-dns requests in a way that makes it looks like it has accepted an update request. It doesn't seem to actually do so, but it confuses some security scanners into stating falsely that the server is honouring dynamic-dns requests. In the case of a dynamic-dns request, acme-dns should respond with RCODE REFUSED(5)

$ nsupdate
> server xxx.xxx.xxx.xxx 53
> update add foo.letsencrypt.example.com 86400 A 127.0.0.1
>  send
> quit
$ dig @xxx.xxx.xxx.xxx foo.letsencrypt.example.com

; <<>> DiG 9.4.2-P2 <<>> @xxx.xxx.xxx.xxx foo.letsencrypt.example.com
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id:
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;foo.letsencrypt.example.com.      IN      A

;; Query time: 77 msec
;; SERVER: xxx.xxx.xxx.xxx#53(xxx.xxx.xxx.xxx)
;; WHEN: Tue Sep 18 18:40:01 2018
;; MSG SIZE  rcvd: 42

raise an error if acme-dns can't listen/bind to a specified port.

while doing some debugging of firewall rules, I realized that acme-dns will start up fine as an unprivileged user who can't bind to port 53 (if that is the configured port). I think it should probably raise an error OR print a warning line in these situations.

Option to drop privileges after binding to port 53?

From the readme:

Please note that acme-dns needs to open a privileged port (53, domain), so it needs to be run with elevated privileges

Is it possible to add a config option to drop privileges after starting the app? A daemon running as root scares me :)

Add Option to Use staging Let'sEncryptServer during setup

Hi!

Thanks for the great piece of software. During setup, I was trying to figure out my firewall for allowing DNS through properly, and I hit the production requests/hr limit accidentally on Let'sEncrypt servers. It would be nice to be able to change to their staging servers during setup and validation of firewall/ethernet settings. Maybe a config option?

Run Dockerized server process as unprivileged user by default

Would be nice from a security perspective if the Dockerized version of acme-dns automatically started as an unprivileged user (instead of as root).

The container does provide some level of isolation from the host system already (though as I understand it that isolation isn't perfect, especially against root), but no sense in giving the public-facing server any more permissions than necessary.

Handling registration requests with broken/incomplete JSON payload

To continue from discussion started here:
#20 (comment)

ping @koesie10

Which approach would be the intuitive and appropriate if broken or incomplete JSON object (or whatever payload) is sent to registration endpoint:

  1. acme-dns should return error, like 400 Bad Request with descriptive error message.
  2. Registration should complete with default values, and return these to the user.

Previously I felt that the second one would be the correct approach, but now I'm starting to lean towards the first one.

Registration with allowfrom set does not work?

Unless I'm doing something really stupid here, I don't seem to be able to be able to update domains when allowfrom has been set during registration.

I use ip addr to retrieve all the CIDR ranges assigned to my server, then register as follows:

root@london ~ curl -s -X POST http://auth.mydnsdomain.co.uk:8080/register \
--data '{"allowfrom": ["127.0.0.1/8", "::1/128", "139.XXX.XXX.153/24", "192.XXX.XXX.197/17", "2a01:XXXX::XXXX:XXXX:XXXX:923d/64", "fe80::XXXX:XXXX:XXXX:923d/64"]}' | python -m json.tool
{
    "allowfrom": [
        "127.0.0.1/8",
        "::1/128",
        "139.XXX.XXX.153/24",
        "192.XXX.XXX.197/17",
        "2a01:XXXX::XXXX:XXXX:XXXX:923d/64",
        "fe80::XXXX:XXXX:XXXX:923d/64"
    ],
    "fulldomain": "1937e870-d239-4cb2-99b2-d1979c2608e3.auth.mydnsdomain.co.uk",
    "password": "54mt4yLIRJZIXiK161jZghvuIxFz09Tj1sZY_vpZ",
    "subdomain": "1937d870-d239-4cb2-99b2-d1979q2608a3",
    "username": "p0624f07-b4a7-4d61-8d28-4f7e63621952"
}

Note: IP addresses have been partially replaced with XXX/XXXX, the real values however are used for the commands.

I then attempt to update that sub-domain:

root@london ~ curl -s -X POST http://auth.mydnsdomain.co.uk:8080/update \
-H "X-Api-User: p0624f07-b4a7-4d61-8d28-4f7e63621952" \
-H "X-Api-Key: 54mt4yLIRJZIXiK161jZghvuIxFz09Tj1sZY_vpZ" \
--data '{"subdomain": "1937d870-d239-4cb2-99b2-d1979q2608a3", "txt": "___validation_token_recieved_from_the_ca___"}' | python -m json.tool
{
    "error": "forbidden"
}

However the update fails. acme-dns displays the following:

DEBU[1269] Created new user                              user=p0624f07-b4a7-4d61-8d28-4f7e63621952
ERRO[1542] Update not allowed from IP                    error=ip_unauthorized

If I register without seting allowfrom, everything works fine:

curl -s -X POST http://auth.mydnsdomain.co.uk:8080/register | python -m json.tool
{
    "allowfrom": [],
    "fulldomain": "ad53ddb7-38ad-42fd-9d65-854769764df0.auth.mydnsdomain.co.uk",
    "password": "rqSI-YHVf12jfw-FgkQzJrhyUJ_rU9E4_37WP_6h",
    "subdomain": "ab53ddb7-38ad-42fd-9d65-854769764da0",
    "username": "945b3pf0-cc24-4008-9c99-270b13534d4q"
}

curl -s -X POST http://auth.mydnsdomain.co.uk:8080/update \
-H "X-Api-User: 945b3pf0-cc24-4008-9c99-270b13534d4q" \
-H "X-Api-Key: rqSI-YHVf12jfw-FgkQzJrhyUJ_rU9E4_37WP_6h" \
--data '{"subdomain": "ab53ddb7-38ad-42fd-9d65-854769764da0", "txt": "___validation_token_recieved_from_the_ca___"}' | python -m json.tool
{
    "txt": "___validation_token_recieved_from_the_ca___"
}

Am I missing something here, or is it broken?

No JSON object could be decoded

I have put acme-dns into a Docker container with exposed ports 53 and 443. I get response for requests on 53/UDP but I get no response on 443/TCP. All I get is "No JSON object could be decoded"

I have the following (DEFAULT) settings in the api section of config.cfg

 [api]
 # domain name to listen requests for, mandatory if using tls = "letsencrypt"
 api_domain = ""
 # listen port, eg. 443 for default HTTPS
 port = "443"
 # possible values: "letsencrypt", "cert", "none"
 tls = "none"

Any hint, where to look into?

Make DNS server listen on one IPv6 address

I want to run acme-dns and have it listen on just a single IPv6 address, since I already have another DNS server listening on some other IPs on the same server. I've edited the configuration like this:

[general]
# dns interface
listen = "[2605:6400:20:92e::eff]:53"
# protocol, "udp", "udp4", "udp6" or "tcp", "tcp4", "tcp6"
protocol = "udp6"

...

[api]
# listen ip, default "" listens on all interfaces/addresses
#ip = "127.0.0.1"
ip = ""
# listen port, eg. 443 for default HTTPS
port = "8496"

However, when I run it, it seems like it's only listening on the API port and not on the DNS one:

13:28 daniel@vps03 /home/daniel
% sudo netstat -tulnp | grep acme-dns
tcp6       0      0 :::8496                 :::*                    LISTEN      28247/acme-dns

Am I using the correct syntax? It's a bit confusing because the API section has separate "ip" and "port" options, but I just see a single "listen" option for the DNS server, so I just tried to guess the syntax.

Client implementations

Acme-dns needs client implementations for clients in order to be useful. If you have written a client implementation, please let me know, and I'll add a link to it to the README.md for people to find and use.

Currently the only publicly available client implementation that I know of is a Certbot authentication hook that can be found at: https://github.com/joohoi/acme-dns-certbot . This can be used as a reference for ways to handle the credential storage and communication towards acme-dns instance.

registration with invalid `allowfrom` fails open

I didn't read the documentation very carefully and thought I could POST /registration with an allowfrom entry for a single host address instead of a CIDR range, e.g.:

{
    "allowfrom": [
        "127.0.0.1"
    ]
}

acme-dns filters this invalid allowfrom in acmedb.Register using cidrslice.ValidEntries. The registration is created successfully with no errors, but the returned allowfrom is empty and so is the field in the database for this user:

{
  "username": "<rand>",
  "password": "<rand>",
  "fulldomain": "<rand>.example.com",
  "subdomain": "<rand>",
  "allowfrom": []
}

The documentation specifically says to use a CIDR range but I think there might be a case to be made for rejecting the registration with an error when the allowfrom contains invalid entries. Since allowfrom is a security control I think acme-dns should be conservative and fail fast when it can't fulfill the request as received.

@joohoi What do you think?

Problem start acme-dns in installation

After install and config. exec acme-dns
this error not start the service.
INFO[0000] Using config file file=/etc/acme-dns/config.cfg
ERRO[0000] Could not open database [sql: unknown driver "" (forgotten import?)]

Raise the cap for TXT records per subdomain

I recently released a new PowerShell based ACMEv2 client, Posh-ACME. It supports a DNS challenge plugin system and I was all ready to write a plugin for acme-dns after reading a bit about it. But after digging deeper into how it works, I realized that its usage model isn't really compatible with how my client's DNS challenge processing works.

My client currently tries to publish all required TXT records for a given certificate before sending the validation requests to the ACME server. And if I understand how the 2 record cap in acme-dns works, it means that a SAN cert with more than two names will never be properly validated. As soon as the 3rd record gets added, the oldest one is overwritten and its validation will ultimately fail.

Let's Encrypt's current rate limits enforce a maximum of 100 names per certificate. So raising the acme-dns cap to 100 before rolling over seems like the simplest way to successfully validate a single cert with the maximum 100 names.

Also, since acme-dns seems to be more of a fire-and-forget publishing model rather than add-and-remove, it might also make sense to add what is basically a TTL on the records that get published. Not an actual DNS TTL, but like a database TTL. When the records "expire", they're automatically removed.

I haven't had a chance to look at acme-dns's code yet. So I have no idea what a suggestion like this might take to implement. But does it seem doable?

Document Feature #28 (multiple TXT) in README

I see 2 TXT records saved when I update the records:

4ebb3343-e8f7-454f-aea6-86994592eb8d.auth.my.tld. 0 IN TXT "BqLhqbbdhb7wkdG45c86ZtnMW7PesxsJsIdHMG0WGMg"
4ebb3343-e8f7-454f-aea6-86994592eb8d.auth.my.tld. 0 IN TXT "M3HUkG12CG5VN2uE2DKgVaYI5rYpBqb7rSy8JNhCVsk"

Thought it was a bug until I saw #28. Could we add documentation for this feature in the README that it isn't a bug? TYVM!

acme-dns needs directory permissions in systemd (documentation)

I updated my install to control acme-dns via systemd, with an acme-dns user.

I changed the ownership of items in /etc/acme-dns to acme-dns.

If the /etc/acme-dns directory is owned by root, there are errors in accessing the existing database /etc/acme-dns/acme-dns.db. If the directory is owned by acme-dns, the db is read fine.

Stated differently,

# this results in db errors
chown acme-dns:acme-dns /etc/acme-dns/* 

# this works
chown -R acme-dns:acme-dns /etc/acme-dns

I'm not sure how/why this is happing, but I think it is due to sqlite not being able to make lock files.

Clarification of a Few Points

I'm using acme-dns for my wildcard domain and I was hoping to get a few points clarified for using it

  1. In my config I added the following extra records (changed here for anonymity):
records = [
    # default A
    "auth.example.org. A 192.168.1.100",
    # A
    "ns.auth.example.org. A 192.168.1.100",
    # NS
    "auth.example.org. NS ns.auth.example.org.",
]

Are all these records necessary? Following the readme, I also added the same NS record and A record for ns.auth to my primary DNS, so at least the bottom two seem potentially redundant to me but I may be misunderstanding something about how DNS resolves the names.

  1. Since I use this in a home setup, I am at my ISPs mercy for an IP address. For my primary DNS provider I use dynamic dns records to keep the records updated. Is there any advice for updating acme-dns configuration automatically when the external IPs change?

  2. I'm going to try to add support for acme-dns to cert-manager as part of a larger system, and I won't be able to forward port 53 during development to make the challenges work, is there a recommended way to develop under such circumstances?

  3. Finally, I think this has come up before, but is this safe to keep exposed outside my LAN? I suspect that disabling the registration endpoint solves most security concerns, but just to make sure I am understanding the process: lets say I set up my primary DNS to point to acme-dns as described in the readme, and the register an account to update it. Assuming I left the registration endpoint turned on, couldnt anyone overwrite the/add a registration for my domain and create a certificate for it?

How to add other types of records through the API?

The documentations shows how to add TXT records(assuming that you defer the verification from your main DNS server using a CNAME) but I wonder if it supports other record types and if it can be used as the main DNS server(i.e. point the NS records to it). Using a different server just for ACME verifications doesn't seem right.

SQLite database is world-readable by default

The acme-dns database contains sensitive information such as API keys, and should not be readable by other Linux users by default. However, when I run acme-dns it creates the acme-dns.db file with its permission bits set to 644.

letsencrypt HTTP-01 challenge possible?

Just noticed my certificate cannot renew, I think it's only since LetsEncrypt dropped support for TLS-SNI.

01/02/2018 12:14:43 pmINFO[0029] http: TLS handshake error from 10.42.176.26:51538: acme/autocert: unable to authorize "xxxxxxx.net"; tried ["tls-sni-02" "tls-sni-01"]

is there any way I can continue to use autocert for the API but with HTTP-01 challenge?

Add two TXT records for the same subdomain

Hello,

Due the upcoming Let's Encrypt wildcard certificates, if we want a certificate covering domain.tld and *.domain.tld we need to create two _acme-challenge.domain.tld TXT records, one for the token of domain.tld and another one for *.domain.tld

_acme-challenge.domain.tld TXT tokenfordomain
_acme-challenge.domain.tld TXT tokenforwildcard

Using acme-dns we only need to create an _acme-challenge.domain.tld CNAME record pointing to our fulldomain aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee.auth.whatever.tld but as far as I know, using acme-dns api we can only set 1 TXT record for our subdomain so it shouldn't be possible to issue a cert covering domain.tld and *.domain.tld.

Is there an option/workaround to accomplish this task?. If not, it should be great to add the possibility to add an additional TXT record for a subdomain.

Thank you very much for your work.

Cheers,
sahsanu

Restructure README installation & configuration instructions.

Readme should get restructured:

  • The DNS configuration and Testing it out - sections should follow the Install section.
  • Troubleshooting section should get added after Testing it out - section.
  • Different sections should be linked to from the top of the README for easier access.

Mention in README that IPv6-only is OK?

I was considering adding this to add this to the README, but I'm not quite sure where it would fit.

Let's Encrypt fully supports IPv6-only servers, both for http-01 challenges as well as dns-01 challenges. Commonly, IPv4 addresses are very limited in number while IPv6 addresses are abundant. As an example, I've got a VPS that just has a single IPv4 address and an entire /64 IPv6 range (2^64 addresses)!

This can lead to cases where someone might only have IPv6 addresses available for use. A common example is where a server only has one IPv4 address that's already being used by some other DNS service. In cases like this, binding acme-dns just to an IPv6 address is totally fine.

My configuration looks like:

[general]
# dns interface
listen = "[2605:6400:20:92e::eff]:53"
# protocol, "udp", "udp4", "udp6" or "tcp", "tcp4", "tcp6"
protocol = "udp6"
...

[api]
...
# listen ip, default "" listens on all interfaces/addresses
ip = "[2605:6400:20:92e::eff]"

Note that ip under api needs to be in square brackets when listening to an IPv6 address.

config location

I'd like to run two instances with different configs. can a command line flag be added to specify which config to launch with?

K8S: Create wildcard SSL using acmedns provider

I have tried to create wildcard SSL certificate using k8s certmanager and issuer. I have created the credentials by POST requesting to /register URL and tested the acmedns successfully. However I am unable to create new wildcard SSL certificate using the k8s issuer. I am adding my issuer YAML file below

apiVersion: certmanager.k8s.io/v1alpha1
kind: Issuer
metadata:
  annotations:
  name: letsencrypt-wildcard-prod
  namespace: default
spec:
  acme:
    dns01:
      providers:
        acmedns:
          accountSecretRef:
            key: acmedns.json
            name: acme-dns
          host: http://auth.mydomain.com
    email: [email protected]
    privateKeySecretRef:
      name: letsencrypt-prod
    server: https://acme-v02.api.letsencrypt.org/directory

I have created the secret acme-dns using the json output got from the /register output.
Also, adding the k8s certificate YAML here

apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: wildcard-mydomain.com
  namespace: default
spec:
  acme:
    config:
    - dns01:
        provider: acmedns
      domains:
      - '*.mydomain.com'
  commonName: '*.mydomain.com'
  dnsNames:
  - '*.mydomain.com'
  issuerRef:
    kind: Issuer
    name: letsencrypt-wildcard-prod
  secretName: wildcard-mydomain.com-tls

I am getting the following error from the cert-manager:
###############################################################################
E1129 16:30:31.881025 1 reflector.go:205] github.com/jetstack/cert-manager/pkg/client/informers/externalversions/factory.go:71: Failed to list *v1alpha1.Issuer: v1alpha1.IssuerList: Items: []v1alpha1.Issuer: v1alpha1.Issuer: Spec: v1alpha1.IssuerSpec: IssuerConfig: ACME: v1alpha1.ACMEIssuer: DNS01: v1alpha1.ACMEIssuerDNS01Config: Providers: []v1alpha1.ACMEIssuerDNS01Provider: ReadArrayCB: expect [ or n, but found {, error found in #10 byte of ...|oviders":{"acmedns":|..., bigger context ...|81551da95"},"spec":{"acme":{"dns01":{"providers":{"acmedns":{"accountSecretRef":{"key":"acmedns.json|...
E1129 16:30:32.887374 1 reflector.go:205] github.com/jetstack/cert-manager/pkg/client/informers/externalversions/factory.go:71: Failed to list *v1alpha1.Issuer: v1alpha1.IssuerList: Items: []v1alpha1.Issuer: v1alpha1.Issuer: Spec: v1alpha1.IssuerSpec: IssuerConfig: ACME: v1alpha1.ACMEIssuer: DNS01: v1alpha1.ACMEIssuerDNS01Config: Providers: []v1alpha1.ACMEIssuerDNS01Provider: ReadArrayCB: expect [ or n, but found {, error found in #10 byte of ...|oviders":{"acmedns":|..., bigger context ...|81551da95"},"spec":{"acme":{"dns01":{"providers":{"acmedns":{"accountSecretRef":{"key":"acmedns.json|...
########################################################################

Status 401 (Unauthorized) when trying to post update request

I am trying to update a DNS record using Java.
I always get an 401 status response, but I cannot see anything wrong in my code.

` private void contactAcmeDnsServer(String digest) {
Console.out("Digest: " + digest);

	try {
		Content content = Request.Post("http://localhost:9443/register").execute().returnContent();

		JSONParser parser = new JSONParser();
		JSONObject json = (JSONObject) parser.parse(content.asString());

		String fulldomain = (String) json.get("fulldomain");
		String subdomain = (String) json.get("subdomain");
		String username = (String) json.get("username");
		String password = (String) json.get("password");
		
		String url = "http://localhost:9443/update";

		@SuppressWarnings("resource")
		HttpClient client = new DefaultHttpClient();
		HttpPost request = new HttpPost(url);
		request.addHeader("X-Api-Key", password);
		request.addHeader("X-Api-User", username);

		String JSON_STRING = "{\r\n" + "\"subdomain\": \"_acme-challenge." + subdomain + "\",\r\n" + "\"txt\": \""
				+ digest + "\"\r\n" + "}";

		StringEntity stringEntity = new StringEntity(JSON_STRING, "UTF-8");

		request.setEntity(stringEntity);

		HttpResponse response = client.execute(request);

		Console.out("rc: " + String.valueOf(response.getStatusLine().getStatusCode()));

		BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

		StringBuffer result = new StringBuffer();
		String line = "";
		while ((line = rd.readLine()) != null) {
			result.append(line);
		}

		Console.out(result.toString());

	} catch (IOException e) {
		e.printStackTrace();
	} catch (ParseException e) {
		e.printStackTrace();
	}`

Aside from this, am I supposed to do the POST /register every time before the POST /update?
Is the "_acme-challenge." part automatically added in the POST /update or is my JSON_STRING object correct?

Rewrite HTTP API to get rid of Iris

The very light usage of HTTP API features can be done using something a lot more lightweight than Iris. The framework also has hard time keeping a stable API, so it causes a lot of unnecessary work.

Create certificates for multiple hosts without adding a CNAME record for each?

First off, thanks for building acme-dns - it's just what I was looking for! I'm trying to do the following: I want to generate certificates for the servers foo.example.org, bar.example.org etc. This works fine. However I have to manually add the following in my providers DNS config:

_acme-challenge CNAME 3882beda-a862-4de8-b3ab-4f528fe88845.auth.example.org
_acme-challenge.foo CNAME _acme-challenge
_acme-challenge.bar CNAME _acme-challenge

As the hosts (foo, bar etc.) are being created rather dynamic I would prefer to prevent creating them by hand if possible (also I would prefer to keep the names of the hosts out of my providers DNS. Wildcards obviously won't work and I don't want to generate a wildcard certificate on each hosts as that seems more of a workaround than a real solution.

The only solution so far that I could think of would be to use my providers API to somehow dynamically create the _acme-challenge.foo record. I would have need to have the client (e.g. lego) to do this before requesting the _acme-challenge record. But unfortunately this implies a 'race' condition because to do that I would put my API keys on each host (which is exactly what I'm trying to prevent with acme-dns).

Would there be any (other) ideas to do this smarter / more dynamic?

Arm docker image

Could you add a arm docker build and tag. I'm attempting to run on raspi 3b+
latest tag will crash immediately due to arm proc

CNAME records are returned as NXDOMAIN

I'm using <uid>.acme-dns.mydomain.org for the letsencrypt TXT records and would like to use acme-dns.mydomain.org as API endpoint.

These are the records I've configured in config.cfg:

records = [ 
    "acme-dns.mydomain.org. CNAME hostname.mydomain.org",
    "acme-dns.mydomain.org. NS hostname.mydomain.org",
]

In the mydomain.org zone I have configured acme-dns.mydomain.org NS hostname.mydomain.org accordingly.

Unfortunately, querying acme-dns.mydomain.org results in NXDOMAIN:
time="2018-03-02T11:45:27Z" level=debug msg="Answering question for domain" domain=acme-dns.mydomain.org. qtype=A rcode=NXDOMAIN

Is it possible to get CNAMEs to resolve correctly? I'd really prefer this over hardcoding an A-record.

PostgreSQL go driver

I set up acme-dns as a service with an unprivileged acme-dns user. I edited the config file to use PostgreSQL and downloaded the pq driver for go. However, being new to go, I am at a lost about where to place the pq package. The command "go get githup/com/lib/pq" installs the river in ~/go by default but since acme-dns is shell-less, where does the package should be installed. The recommendation is to set the $GOPATH variable but I believe that this would not work for acme-dns.

The messages log file (on CENTOS) shows:
acme-dns: time="2018-06-27T22:36:18-04:00" level=error msg="Could not open database [sql: unknown driver "" (forgotten import?)]"

For go neophytes, an addition to the documentation would be greatly appreciated.

How do I make the subdomain.auth.domain.tld available from the outside

Hi I created a docker container for acme-dns, I registered there and I can update the token via post request. I am using the jwilder nginx proxy.
I installed a CNAME entry for _acme-challenge.jotunheim.de to subdomain.auth.jotunheim.de
This entry points to my IP adress.
What I don't understand is, what I need to do now, to make the TXT entry available from the outside. Do I need to portforward port 53 to the inside acme-dns, right? What else?

sync README with config, perhaps better docs about ips

The readme and config differ a bit

For example, the README shows

# listen ip, default "" listens on all interfaces/addresses
ip = "127.0.0.1"

But the config was changed to be:

listen ip eg. 127.0.0.1

ip = "0.0.0.0"

i'm sure multiple default elements were changed - that's the only one I noticed from my limited knowledge of the library. the content of the README installation guide should reflect the current config options/defaults and docstrings.

In terms of docs about ips... defaulting to 127.0.0.1 is probably safest, as as it will only work from the same machine (or require a proxy on the machine) since there are not access controls in place- but many people will likely want to use 0.0.0.0 for testing. was there a reason this was changed to 0.0.0.0?

https://raw.githubusercontent.com/joohoi/acme-dns/3343d943d604be8bc0ab0830bccfb6459d1ae95c/README.md#L230-L240

https://github.com/joohoi/acme-dns/blob/master/config.cfg#L34-L39

Port Binding Errors

Does this currently give any sort of visible error or warning if it can't bind the DNS port? I'll admit straight out that this largely is pebkac/rtfm error on my part, but I spent longer than I'd care to admit today troubleshooting today because systemd-resolved was hogging the port on Ubuntu server, putting this in a state where everything looked green everywhere I checked, no more config errors, register and update work fine, but nothing will resolve for obvious(in retrospect) reasons. It would be nice to have something a bit more in your face, like when you have config errors and it straight up spits out an error and refuses to start.

Possible missing DNS settings for the server (Auth Failures)

I am still having some failed authorizations and feel like I am missing something , here are some details

Config

[general]
# dns interface
listen = ":53"
# protocol, "udp", "udp4", "udp6" or "tcp", "tcp4", "tcp6"
protocol = "udp"
# domain name to serve the requests off of 
domain = "dns.codepier.io"
# zone name server 
nsname = "ns1.codepier.io"
# admin email address, where @ is substituted with .
nsadmin = "codepier.io"
# predefined records served in addition to the TXT
records = [
    # default A
    "dns.codepier.io. A 45.77.100.41",
    # A 
    "ns1.dns.codepier.io. A 45.77.100.41",
    # NS
    "dns.codepier.io. NS ns1.dns.codepier.io.",
]

DNS Records

A :dns.codepier.io
NS : ns1.dns.codepier.io

Is there anything else that i need to setup?

More Info

I've setup a script to automatically get the token and update it via the API , and that seems to be working

Output from 8-set-token.sh:
{"txt": "1HQjYS6NlSne1RCeCxfTisFAwr8-9fEbGEQ4jWtzBnQ"}

But the actual authorization fails

Failed authorization procedure. evanpolicinski.com (dns-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.evanpolicinski.com

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.