auto-ssl / lua-resty-auto-ssl

On the fly (and free) SSL registration and renewal inside OpenResty/nginx with Let's Encrypt.
MIT License
1.93k stars 182 forks source link

How to determine if self signed cert is being used #268

Closed MemoryLeak55 closed 2 years ago

MemoryLeak55 commented 2 years ago

Hi,

I've got a setup where we are doing some custom whitelabling of our service via detection of hostname. I've already setup the allow_domain function to query a database to determine if I want to issue a cert of the hostname of the incoming request, and it works wonderfully.

Now, I'd like to add some functionality if possible. I would like for a way to "catch" when auto ssl isn't being used. This would be in the circumstance where there is no stored cert in the storage adapter, and that we won't issue a lets encrypt cert because it's not in the whitelist (so allow_domain has returned false)

In this circumstance, instead of defaulting back to certs defined by ssl_certificate and ssl_certificate_key in openresty and continuing with processing, I would like to return a static page that says, "domain not authorized" and stop any further processing.

I hope this makes sense, any help is appreciated! I've been looking through docs but I've not seen a clear way to implement such a functionality.

EDIT: I think has_certificate might do exactly what I need. I'm not sure how I missed that

EDIT2:

I've tried the following implementation in a server block

access_by_lua_block {
    print("accessblock")
    print("host: " .. ngx.var.host)
    local has_cert = auto_ssl:has_certificate(ngx.var.host)
    if not has_cert then
        print("denying access to :" .. ngx.var.host)
        ngx.say("hostname not whitelisted, please contact support for assistance")
        ngx.exit(403)
    end
    print("resuming handler")
}

And get the following error in my errror.log

lua entry thread aborted: runtime error: access_by_lua(auto_ssl:37):4: attempt to call method 'has_certificate' (a nil value)
stack traceback:
coroutine 0:
        access_by_lua(auto_ssl:37): in main chunk, client: xxx.xxx.xxx.xxx, server: _, request: "GET / HTTP/1.1", host: "host.name.here"

Any idea why the call to has_certificate is failing?

waynegemmell commented 2 years ago

This is a great feature. We need it too.

nickpearson commented 2 years ago

If the request comes in over SSL, then the only way to respond to it (without causing the browser to show a certificate error) is using a cert that matches the request host. If the server's response uses a cert that doesn't match, then the browser will show a certificate error.

waynegemmell commented 2 years ago

Is there any way to run a script so that we can get alerted via another channel like Telegram or Slack?

nickpearson commented 2 years ago

Yes, you'd just place your notification code in the if not has_cert then block in your sample code above. You can do whatever you want there on the server side — you just won't be able to successfully respond to the client's https request without a valid cert.

waynegemmell commented 2 years ago

Thanks. In the query above the OP says the call failed. Any idea why that would the case?

nickpearson commented 2 years ago

I don't know the internals well enough to know why that would fail, but you could put your notification functionality in the allow_domain function just before you return false. e.g.:

auto_ssl:set("allow_domain", function(domain, auto_ssl, ssl_options, renewal)
  local domain_not_allowed = ...
  if domain_not_allowed
    notify_us_on_slack(domain)
    return false
  end
end
waynegemmell commented 2 years ago

ok, thanks

aviatrix commented 2 years ago

You can use lua redis package (reuse one provided with resty-auto-ssl) or other db provider, and check there, i've done similar things, it's not a lot of work, but seem to have lost the config i used 2-3 years ago