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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for check TLSA records (DANE) #38

Open
dragoangel opened this issue Jul 5, 2020 · 8 comments
Open

Add support for check TLSA records (DANE) #38

dragoangel opened this issue Jul 5, 2020 · 8 comments

Comments

@dragoangel
Copy link
Contributor

dragoangel commented Jul 5, 2020

I doesn't find any Prometheus exporter which allow this functionality, so this will be unique future.
TLSA records works on DNSSEC signed zones and allow to authenticate host even with certificate issued via not publicly trusted CA, or add pinning of existing trusted certificate to DNS layer to provide more security.
At current state enabling TLSA for SSL connections gives most of profit for Mail servers. F.e.: Postfix start to work with mandatory encryption when it detect TLSA record for MX record and not allow to downgrade to plain text.
Monitoring of TLSA is important as incorrect value in TLSA record mean untrusted SSL connection from client side which support DANE validation.
Here is short description:
https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities
And some other opensource tools description, maybe it can help with ideas:
https://www.internetsociety.org/blog/2017/12/monitoring-your-dane-deployment/
https://github.com/siccegge/dane-monitoring-plugins

@ribbybibby
Copy link
Owner

Interesting. I see there's this library: https://github.com/shuque/dane. Perhaps I could integrate that. I'll have to study it a bit more.

@dragoangel
Copy link
Contributor Author

Cool! Thanks

@tykling
Copy link

tykling commented Dec 14, 2020

TLSA record checking would be a very nice feature! 👍

@ribbybibby
Copy link
Owner

I've started implementing TLSA checking on this branch: https://github.com/ribbybibby/ssl_exporter/tree/dane-verification. If anyone following this issue has some examples of DANE/TLSA in their org then I'd appreciate them trying to run it and probe their targets. I've only found a couple of publicly available targets to validate against.

I think I've captured the basic usages as laid out in the RFCs but I know I'm missing some edge cases (there's some special logic to do with smtp). If anyone has deep knowledge of the spec I'd appreciate any comments on the logic here: https://github.com/ribbybibby/ssl_exporter/blob/dane-verification/prober/tls.go#L126-L169

@dragoangel
Copy link
Contributor Author

dragoangel commented Dec 15, 2020

Wow, I will check when have time, it good news. I can install test branchand and I have smtp targets to do testing.

Thank you

Update: I wrote you in linkedin 😊

@tykling
Copy link

tykling commented Dec 15, 2020

Hello,

I am acually more interested in the resulting metrics than the result of the check as such. Well, both. Let me describe my usecase so you know where I am coming from.

Background
In my project UncensoredDNS I run DNS servers with DoT and DoH enabled, and I've published public key fingerprints on https://blog.uncensoreddns.org/dns-servers/ for both RSA and ECDSA keys (both are supported on the services).

Usecase
I've published TLSA records for the public keys of each server, and it would be great to have ssl_exporter help verify that:

  1. The TLSA records I expect to be there are actually there
  2. The certificate and public key the server is offering actually matches one of the TLSA records in the DNS

The TLSA records I use have the following properties:

  • I use the TLSA Certificate Usage "Domain-issued certificate" which is number 3, because I want to verify the presented leaf certificate.
  • I use TLSA Selector "SubjectPublicKeyInfo" which is number 1, because I want to verify the public key rather than the full certificate, because with LetsEncrypt the cert changes very often, but my public keys stay the same.
  • I use three different TLSA Matching Types, 0, 1 and 2, which correspond to "no hash", sha256 and sha512 respectively.

With three "matching types" I have 3 TLSA records per keytype per service, meaning 6 all in all because I have both RSA and ECDSA keys:

  • 3 1 0 full RSA spki
  • 3 1 1 RSA sha256
  • 3 1 2 RSA sha512
  • 3 1 0 full ECDSA spki
  • 3 1 1 ECDSA sha256
  • 3 1 2 ECDSA sha512

Proposal
I would love to be able to tell ssl_exporter to connect first with an RSA cipher and then with ECDSA (two seperate checks), and look at the presented certificate and public key, lookup any TLSA records, and verify whether the presented key matches one of them.

This could produce the following TLSA specific metrics, one for each combination of keytype, usage, selector and matchingtype found in DNS:

ssl_exporter_tlsa_success{instance="unicast.uncensoreddns.org:443", keytype="rsa", usage="3", selector="1", matching="0"} 1
ssl_exporter_tlsa_success{instance="unicast.uncensoreddns.org:443", keytype="rsa", usage="3", selector="1", matching="1"} 1
ssl_exporter_tlsa_success{instance="unicast.uncensoreddns.org:443", keytype="rsa", usage="3", selector="1", matching="2"} 1

Let's say I forgot to add a 3 1 2 TLSA record for the ECDSA key for unicast.censurfridns.dk, that metric would be missing:

ssl_exporter_tlsa_success{instance="unicast.uncensoreddns.org:443", keytype="ecdsa", usage="3", selector="1", matching="0"} 1
ssl_exporter_tlsa_success{instance="unicast.uncensoreddns.org:443", keytype="ecdsa", usage="3", selector="1", matching="1"} 1

or if it didn't match the presented key it would return a 0:

ssl_exporter_tlsa_success{instance="unicast.uncensoreddns.org:443", keytype="rsa", usage="3", selector="1", matching="2"} 0

My usecase with anycast servers means I have some names with many TLSA records because many servers have the same name but different keys. This means I am happy if my key matches one of the TLSA records (of each type) but I don't care that more TLSA records exist which do not match the servers key.

Other usecases will be opposite, so adding a metric which counts matching and not-matching TLSA records (of each type) would be a good idea, most people will want non-matching to stay at 0 unless they have something complex or anycast-ish going:

ssl_exporter_tlsa_records_total{match="1", usage="3", selector="1", matching="1"} 6
ssl_exporter_tlsa_records_total{match="0", usage="3", selector="1", matching="1"} 30

Sorry this became so long. I am available on IRC as tykling on the major networks, HMU if you do IRC. :)

ps. Since the servers (all mentioned on the blogpost) are public and reachable from everywhere you are welcome to prod them on ports 443 and 853 and look at their TLSA records in the DNS!

@ribbybibby
Copy link
Owner

Thank you so much for the detailed proposal @tykling.

So essentially, there are two things the exporter could be doing here:

  1. Ensuring that the target can be validated by at least one of the available TLSA records. This is what I've been working on implementing so far.
  2. Exporting information about the TLSA records, so that operators can monitor the state of their records and alert on any discrepencies.

Perhaps in addition to the validation we could do something like:

ssl_tlsa_record_match{usage="3",selector="1",matching="0",data="<data>"} 0
ssl_tlsa_record_match{usage="3",selector="1",matching="1",data="<data>"} 1
ssl_tlsa_record_match{usage="3",selector="1",matching="2",data="<data>"} 0

Where a value of 1 indicates a record that matches.

Then you could do something like this to identify non-matching results:

count(ssl_tlsa_record_match == 0) by (instance) > 0

I think the key type is a separate concern from TLSA and should probably form part of a separate issue in GH. You may want to monitor the key type in contexts other than TLSA.

Thinking off the top of my head, perhaps we could support an option to provide a list of preferred cipher suites and then also export the key info in a new metric or possibly as another label on our ssl_cert_not_(after|before) metrics. That should enable what you want?

@ribbybibby
Copy link
Owner

Responded to the feedback from @dragoangel here: 4a18f54#commitcomment-45185968

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

No branches or pull requests

3 participants