Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checking DNS records before issuing a certificate #25

Open
discobean opened this issue Sep 27, 2016 · 5 comments
Open

Checking DNS records before issuing a certificate #25

discobean opened this issue Sep 27, 2016 · 5 comments

Comments

@discobean
Copy link

First thanks for the great work in building this 馃憤

It would be great if auto-ssl would check that the DNS would resolve to a certain set of IPs before issuing a request to LetsEncrypt.

For example a new auto_ssl:set function could return that list of IPs, and if DNS resolves to any of those the certificate request goes ahead.

@GUI
Copy link
Collaborator

GUI commented Oct 22, 2016

It should be possible to implement something like this with a custom allow_domain method and integrating it with lua-resty-dns (lua-resty-dns-cache may also be useful in this case). I can definitely see the use-cases behind this, but I'm not sure integrating this functionality directly into lua-resty-auto-ssl would be the best fit. But if anyone comes up with an example allow_domain using one of the resty-dns libraries, we could definitely provide that as an example.

@waynerobinson
Copy link

waynerobinson commented Jan 7, 2017

I'm not sure if this is the best code (I'm completely unfamiliar with Lua), but I have implemented this using lua-resty-dns-cache largely from the example on the two library's sites:

In the server section of Ngxin:

lua_shared_dict dns_cache 1m;

In the init_by_lua_block

require("resty.dns.cache").init_cache(200)

And then the allow_domain function:

      auto_ssl:set("allow_domain", function(domain)
        if domain == "whitelisted-domain.com" then
            return true
        end

        local DNS_Cache = require("resty.dns.cache")
        local dns = DNS_Cache.new({
                dict = "dns_cache",
                negative_ttl = 5,
                max_stale = 300,
                resolver  = {
                    nameservers = {"8.8.8.8"}
                }
            })
        local answers, err, stale = dns:query(domain)
        if err then
            if stale then
                ngx.header["Warning"] = "110: Response is stale"
                answer = stale
                ngx.log(ngx.ERR, err)
            else
                ngx.status = 500
                ngx.say(err)
                return ngx.exit(ngx.status)
            end
        end
        if not answers then
            ngx.say("failed to query the DNS server: ", err)
            return false
        end

        if answers.errcode then
            ngx.say("server returned error code: ", answers.errcode,
                    ": ", answers.errstr)
            return false
        end

        for i, ans in ipairs(answers) do
           -- If this CNAME exists at all in the result, generate an SSL certificate.
            if ans.cname == "destination.example.com" then
                return true
            end
        end
        return false
      end)

@GUI
Copy link
Collaborator

GUI commented Jan 13, 2017

@waynerobinson: Thanks for contributing this example! I'll try to give this a spin at some point and add in the README. Or if anyone else gets a chance to test this, it would be great to know if it works for you.

@andrewhamon
Copy link

Depending on your use case, using DNS may not produce the expected results. If a domain is using, e.g. Cloudflare CDN, the DNS records will point to a different IP than your server.

Probably not a huge deal, especially since Cloudflare can be configured to accept untrusted certs from the origin server, but worth considering.

@mauriciogior
Copy link

Up. I think this has great value since there could be an exploit and end up flooding Let's Encrypt API with wrong or invalid DNS information (eg. set up a local DNS for random-non-existent-domain.xyz that points to your IP and it would try to generate a certificate for an invalid domain).

The workaround we found is to setup a redis and verify if the domain is whitelisted on allow_domain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants