ssl_exporter icon indicating copy to clipboard operation
ssl_exporter copied to clipboard

Add support for check TLSA records (DANE)

Open dragoangel opened this issue 4 years ago • 8 comments

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

dragoangel avatar Jul 05 '20 10:07 dragoangel

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.

ribbybibby avatar Aug 19 '20 22:08 ribbybibby

Cool! Thanks

dragoangel avatar Aug 20 '20 04:08 dragoangel

TLSA record checking would be a very nice feature! :+1:

tykling avatar Dec 14 '20 15:12 tykling

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

ribbybibby avatar Dec 15 '20 08:12 ribbybibby

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 😊

dragoangel avatar Dec 15 '20 08:12 dragoangel

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!

tykling avatar Dec 15 '20 14:12 tykling

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 avatar Dec 16 '20 20:12 ribbybibby

Responded to the feedback from @dragoangel here: https://github.com/ribbybibby/ssl_exporter/commit/4a18f54c817035b5a632dce71b7997848a3b06e4#commitcomment-45185968

ribbybibby avatar Dec 16 '20 21:12 ribbybibby