Subject: [dane] Two additions to draft-york-dane-deployment-observations-00

From: Stephane Bortzmeyer <[email-masked]>
Date: Fri, 7 Nov 2014 15:29:15 -0800

I've just read draft-york-dane-deployment-observations-00 and I would
like to add two things to the list in section 2, "Observations", list
of reasons why people don't deploy DANE. These additions come from my
experience trying to promote the use of DANE.

The first one is that some people distrust the domain name industry
and feel that it is not safe to exchange the CA for the domain name
actors (some of them having bad reputations like G... D...). Now, we
all know it is more complicated than that (usages PKIX-* do not
required that you drop the CA system, but on the other hand, some
people fear that, if DANE is in the browser, the registrar, registry
or the DNS hoster may be able to divert your users to a false site,
something they could not do before). I don't say that I follow this
reasoning but I've heard it several times so it could be documented.

The second one is the lack of monitoring solutions. DANE brings some
new risks of discrepancies (people renewing the certificate and
forgetting to update the TLSA record for the *-EE usages...) since the
people who manage the certs may not be the same who manage the DNS. We
really need Nagios plugins to monitor DANE sites. Unlike the first
reason given above, I strongly buy this one.

---

From: Viktor Dukhovni <[email-masked]>
Date: Sat, 8 Nov 2014 02:40:18 +0000

> reason given above, I strongly buy this one.

Funny you should mention that.  That's something I'm working on,
and at least for SMTP with DANE.

Some of the early adopter domains I've been curating are getting
DNSSEC wrong.  The forget to re-sign, or secondaries fall out of
sync, or nameservers are buggy, ...  I've also seen some validation
failures with BIND 9.10.1 as the validating resolver that I don't
see with unbound.

The monitoring is at the DANE layer, getting detailed diagnostics
from DNSSEC validation errors would also be useful, but I don't
have the tools handy for that, "drill -S" is almost the right tool,
but I'm open for recommendations of validators that describe problems
more simply and concisely than:

    $ drill -S -D -t tlsa _25._tcp.fuhrt.de.
    ;; Number of trusted keys: 1
    ;; Chasing: _25._tcp.fuhrt.de. TLSA

    DNSSEC Trust tree:
    _25._tcp.fuhrt.de. (TLSA)
    |---Error in denial of existence: RR not covered by the given NSEC RRs
    |---cgokmsudli89pi41egv37cvqrq5bfug3.fuhrt.de. (NSEC3)
    |   |---fuhrt.de. (DNSKEY keytag: 22118 alg: 7 flags: 256)
    |       |---fuhrt.de. (DNSKEY keytag: 10069 alg: 7 flags: 257)
    |       |---fuhrt.de. (DS keytag: 10069 digest type: 2)
    |           |---de. (DNSKEY keytag: 56395 alg: 8 flags: 256)
    |               |---de. (DNSKEY keytag: 24220 alg: 8 flags: 257)
    |               |---de. (DS keytag: 24220 digest type: 2)
    |                   |---. (DNSKEY keytag: 22603 alg: 8 flags: 256)
    |                       |---. (DNSKEY keytag: 19036 alg: 8 flags: 257)
    |---Error in denial of existence: RR not covered by the given NSEC RRs
    |---2q3imqr0q2dntoohifcm0a6or78lropv.fuhrt.de. (NSEC3)
	|---fuhrt.de. (DNSKEY keytag: 22118 alg: 7 flags: 256)
	    |---fuhrt.de. (DNSKEY keytag: 10069 alg: 7 flags: 257)
	    |---fuhrt.de. (DS keytag: 10069 digest type: 2)
		|---de. (DNSKEY keytag: 56395 alg: 8 flags: 256)
		    |---de. (DNSKEY keytag: 24220 alg: 8 flags: 257)
		    |---de. (DS keytag: 24220 digest type: 2)
			|---. (DNSKEY keytag: 22603 alg: 8 flags: 256)
			    |---. (DNSKEY keytag: 19036 alg: 8 flags: 257)
    No trusted keys found in tree: first error was: RR not covered by the given NSEC RRs
    ;; Chase failed.

So we've not yet shaken out all the DNSSEC implementation and
operational errors.

On the DANE front, some users are confused about the difference
between the Cert(0) vs SPKI(1) selector, and occasionally forget
to update TLSA RRs when keys are rotated.

The raw scan for ietf.org reads:

    ietf.org. IN MX 0 mail.ietf.org.
    mail.ietf.org. IN A 4.31.198.44
    _25._tcp.mail.ietf.org. IN TLSA 3 1 1 0c72ac70b745ac19998811b131d662c9ac69dbdbe7cb23e5b514b56664c5d3d6
    ;; SSL: protocol = TLSv1.2, cipher = ECDHE-RSA-AES256-GCM-SHA384 (256 bits)
    ;; Passed(depth 0): mail.ietf.org. IN TLSA 3 1 1 0c72ac70b745ac19998811b131d662c9ac69dbdbe7cb23e5b514b56664c5d3d6

-- 
	Viktor.

---

From: "Olle E. Johansson" <[email-masked]>
Date: Sat, 8 Nov 2014 08:17:15 +0100

On 08 Nov 2014, at 00:29, Stephane Bortzmeyer <[email-masked]> wrote:

>  We
> really need Nagios plugins to monitor DANE sites
https://github.com/opendnssec/dnssec-monitor

Nagios scripts to monitor DNSsec zones :-)

/O

---

From: Stephane Bortzmeyer <[email-masked]>
Date: Sat, 8 Nov 2014 17:59:25 -1000

On Sat, Nov 08, 2014 at 08:17:15AM +0100,
 Olle E. Johansson <[email-masked]> wrote 

> Nagios scripts to monitor DNSsec zones :-)

I was not talking about DNSsec monitoring (I already use it, otherwise
I would never have deployed DNSsec in production for serious domains)
but about DANE monitoring: get the TLSA record, open a TLS connection,
get the certificate, check that it is consistent with what the TLSA
record announces.

As far as I know, there is currently no software for that.

---

From: Melinda Shore <[email-masked]>
Date: Sat, 08 Nov 2014 19:07:10 -0900

> get the certificate, check that it is consistent with what the TLSA

Shumon Huque wrote something using the getdns Python bindings that
may be close to what you're asking about:
https://github.com/getdnsapi/getdns-python-bindings/blob/master/examples/checkdanecert.py

Melinda

---

From: Viktor Dukhovni <[email-masked]>
Date: Sun, 9 Nov 2014 04:14:44 +0000

> As far as I know, there is currently no software for that.

I have code for that.  It establishes the TLS connection via SMTP +
STARTTLS, after finding TLSA RRs for a domain's MX hosts.  Delete all the
SMTP logic and you can test pure TLS too, though I'm aware of any real
applications that combine straight TLS with DANE.

What application protocols did you have in mind?

-- 
	Viktor.

---

From: Paul Wouters <[email-masked]>
Date: Sun, 9 Nov 2014 19:55:07 -0500 (EST)

> reasoning but I've heard it several times so it could be documented.

And for that, we bring you CT for DNSSEC. Go look at the presentation
and be ready to give us feedback this monday at TRANS :)

http://www.ietf.org/proceedings/91/slides/slides-91-trans-3.pdf

Paul

---

From: Paul Wouters <[email-masked]>
Date: Mon, 10 Nov 2014 00:36:41 -0500 (EST)

> get the certificate, check that it is consistent with what the TLSA

https://www.dnssec-validator.cz/

DNSSEC/TLSA Validator is a web browser add-on which allows you to check
the existence and validity of DNS Security Extensions (DNSSEC) records
and Transport Layer Security Association (TLSA) records related to
domain names. Results of these checks are displayed by using icons and
information texts in the page’s address-bar or browser tool-bar.
Currently, Internet Explorer (IE), Mozilla Firefox (MF), Google
Chrome/Chromium (GC), Opera (OP), Apple Safari (AS) are supported.

---

From: Stephane Bortzmeyer <[email-masked]>
Date: Sun, 9 Nov 2014 20:00:54 -1000

On Mon, Nov 10, 2014 at 12:36:41AM -0500,
 Paul Wouters <[email-masked]> wrote 
 a message of 17 lines which said:

> DNSSEC/TLSA Validator is a web browser add-on 

Not very practical to run automated and unattended tests, for instance
from Nagios or similar.

---

From: Viktor Dukhovni <[email-masked]>
Date: Mon, 10 Nov 2014 06:28:08 +0000

> Not very practical to run automated and unattended tests, for instance

Are you going to test SMTP servers, HTTPS servers, or something else?

And if HTTPS servers, why?  (Despite lack of evidence of any
substantive support for DANE in browsers, various experimental
plugins notwithstanding).

-- 
	Viktor.

---

From: Viktor Dukhovni <[email-masked]>
Date: Mon, 10 Nov 2014 08:53:03 +0000

On Mon, Nov 10, 2014 at 12:36:41AM -0500, Paul Wouters wrote:

[
  Speaking of deploy360, nobody is regularly testing the listed
  sites at:

    http://www.internetsociety.org/deploy360/resources/dane-test-sites/

  For example, https://www.statdns.net/ no longer matches its
  TLSA record, presumably after key rotation without a TLSA RR
  update, since its certificate digest is different from the
  content of the "3 0 1" associated data.
]

> information texts in the page?s address-bar or browser tool-bar.

Browser plugins are a bit tricky to script.  For scriptable code:

    $ git clone https://github.com/vdukhovni/ssl_dane
    $ git checkout wip-perl-module
    $ : edit Makefile if platform is not Linux
    $ make
    $ sudo make install

    $ cd Danessl
    $ : edit Makefile.PL if platform is not Linux
    $ perl Makefile.PL
    $ make
    $ sudo make install

With the library and Perl module installed, the attached perl code
can be used as shown in the shell fragment below:

    #! /bin/sh

    # At least one of SSL_CERT_FILE or SSL_CERT_DIR
    # must be set to a suitable cert store for PKIX-TA
    # and PKIX-EE to work.  The OpenSSL built-in defaults
    # are disabled by ssldane.pl, you must elect them
    # explicitly.
    #
    export SSL_CERT_FILE=/etc/ssl/...	# multi-cert CAfile
    export SSL_CERT_DIR=/etc/ssl/...	# hashed CApath

    test_site() {
	echo "--- Testing $1..."
	perl ./ssldane.pl "$@"
	echo "--- Exit code: $?"
	echo
    }

    for site in good bad-hash bad-params bad-sig
    do
	test_site $site.dane.verisignlabs.com 443
    done

Note, the code requires a loopback (127.0.0.1) resolver that is a
DNSSEC validating resolver (unbound is a good choice).  Though for
testing you can edit ssldane.pl and specify some other resolver
address near the top of the file.

Sample output:

    --- Testing good.dane.verisignlabs.com...
    ;; Passed(depth 0): good.dane.verisignlabs.com. IN TLSA 3 0 1 0332aa2d58b3e0544b65656438937068ba44ce2f14469c4f50c9cc6933c808d3
    --- Exit code: 0

    --- Testing bad-hash.dane.verisignlabs.com...
    ;; Failed: bad-hash.dane.verisignlabs.com. IN TLSA 3 0 1 9999999999999999999999999999999999999999999999999999999999999999: unable to get local issuer certificate: (20)
    --- Exit code: 1

    --- Testing bad-params.dane.verisignlabs.com...
    ;; Failed: bad-params.dane.verisignlabs.com. IN TLSA 3 0 17 0332aa2d58b3e0544b65656438937068ba44ce2f14469c4f50c9cc6933c808d3: error processing TLSA RR
    ;; Failed: bad-params.dane.verisignlabs.com. IN TLSA 3 119 1 0332aa2d58b3e0544b65656438937068ba44ce2f14469c4f50c9cc6933c808d3: error processing TLSA RR
    ;; Failed: bad-params.dane.verisignlabs.com. IN TLSA 51 0 1 0332aa2d58b3e0544b65656438937068ba44ce2f14469c4f50c9cc6933c808d3: error processing TLSA RR
    --- Exit code: 1

    --- Testing bad-sig.dane.verisignlabs.com...
    DNS Lookup failed: bad-sig.dane.verisignlabs.com IN A ?: SERVFAIL
    --- Exit code: 255

Digest agility support is not yet a feature of the underlying C
library.  So it should be added to the script, until the library
support is in place.  That's a TODO.

-- 
	Viktor.

P.S.  Your Net::SSLeay Perl module needs to be quite recent, get
a newer one from CPAN if it does not understand the get_peer_cert_chain()
method.

The "Danessl.pm" Perl module is still in early development.  Use
at your own risk, no support or documentation beyond RTFS.

The module code assumes (for no particular reason) that Perl is at
least 5.12.5, likely earlier versions work too, adjust as necessary.

---

From: Terry Burton <[email-masked]>
Date: Mon, 10 Nov 2014 13:13:15 +0000

> get the certificate, check that it is consistent with what the TLSA

Also for reference Swede [1] can be invoked from Nagios as follows:

define command {
        command_name check_tlsa
        command_line cd [nagios]/etc/swede && [nagios]/bin/swede
verify -q $HOSTADDRESS$
}

with dlv.isc.org.key and root.key in [nagios]/etc/swede.

[1] https://github.com/pieterlexis/swede

---

From: Viktor Dukhovni <[email-masked]>
Date: Mon, 10 Nov 2014 15:58:09 +0000

>         command_line cd [nagios]/etc/swede && [nagios]/bin/swede

I don't believe that swede is sufficiently robust for this purpose:

    - No certificate signature checks or expiration checks for usage 2.
      (Invalid or expired chains pass)

    - Extraneous hostname check for usage 3.  (Valid certs fail)
      [Yes, I know the OPS draft has not yet been through WGLC) so
      the new semantics of DANE-EE with respect to hostname and
      expiration checks are not yet "standard".]

    - Unsafe hostname checks for usages 0, 1, 2 (remote name is
      used after insufficient input validation as a regular
      expression!).  The name checks are erroneously case sensitive
      for ASCII input.  (Valid names fail, invalid names pass, and
      possibly security issues depending on safety of using remotely
      provided regexps in Python)

Less critically, and for now also applicable to my Perl code:

    - Does not yet support UTF-8 (IDNA) hostnames.  The SNI extension
      is supposed to be UTF-8.  Name checks on DNS altNames are
      supposed to use ASCII-encoded A-labels.

-- 
	Viktor.

---

From: Shumon Huque <[email-masked]>
Date: Mon, 10 Nov 2014 08:02:38 -1000

> https://github.com/getdnsapi/getdns-python-bindings/blob/master/examples/checkdanecert.py
There's a slightly newer version of that script in the develop branch:

https://github.com/getdnsapi/getdns-python-bindings/blob/develop/examples/checkdanecert.py

Note that this script currently only does usage type 3, and it works for
services that do SSL first (rather than negotiate STARTTLS). The Python
M2Crypto SSL interface has some significant limitations. For example, it
doesn't expose the function to set the TLS SNI extension, so on some
multihomed servers, the server won't be able to figure out the correct
certificate to present leading to the script failing the check. If there is
a better python SSL module that folks would recommend, I'd glad to hear
that.

We have a more complete Python example that additionally does the PKIX-*
mode checks (0 and 1), and we had slides on that example in our recent
RIPE69 getdns tutorial (which we ran out of time to present during the
session itself). I'll work on getting that example posted on the github
site soon.

--Shumon.

---

From: Paul Wouters <[email-masked]>
Date: Mon, 10 Nov 2014 13:21:46 -0500 (EST)

> [1] https://github.com/pieterlexis/swede

Note swede was folded into hash-slinger as the "tlsa" command.

Paul

---

From: Viktor Dukhovni <[email-masked]>
Date: Mon, 10 Nov 2014 18:30:48 +0000

On Mon, Nov 10, 2014 at 08:02:38AM -1000, Shumon Huque wrote:

> certificate to present leading to the script failing the check.

The "swede" code on github, for all its faults, seems to suggest that
M2Crypto does in fact support SNI.

    from M2Crypto import X509, SSL
	...
	connection = SSL.Connection(ctx, sock=sock)
	# Try to use SNI for virtual hosts if available
	try:
	    # We don't want the trailing dot here
	    connection.set_tlsext_host_name(args.host[:-1])

Perhaps you need a sufficiently new version of the module.

> session itself). I'll work on getting that example posted on the github

The ssl_dane library is easy to embed into Python (perhaps easier
than into Perl).  That may be a good approach, and would support
all the parameter values and other fine details.  It uses OpenSSL
for the underlying non-DANE-specific bits.

Though useful for online validation of peers with which you then
communicate, in test mode it operates "off-line", give it a chain,
TLSA record and a peername list, and it tells you whether the
chain is matched or not.

So you can use any SSL toolkit you want to grab the chain, and the
library then handles the validation.  Only known limitations are
that digest agility currently belongs in the application layer
outside the library and that IDNA hostnames are not yet supported.

-- 
	Viktor.

---

From: Viktor Dukhovni <[email-masked]>
Date: Mon, 10 Nov 2014 18:31:55 +0000

> Note swede was folded into hash-slinger as the "tlsa" command.

Did the implementation improve at that time or since?

-- 
	Viktor.

---

From: Shumon Huque <[email-masked]>
Date: Mon, 10 Nov 2014 09:20:31 -1000

> Perhaps you need a sufficiently new version of the module.

The latest official release of M2Crypto doesn't support it (there is a long
standing unaddressed bug report filed on the topic). Some OS distributions
however (such as Fedora) have local patches that add it.

My code currently does this (use it if available):

        # set TLS SNI extension if available in M2Crypto on this platform
        # Note: the official M2Crypto release does not yet (as of late 2014)
        # have support for SNI, sigh, but patches exist.
        try:
            connection.set_tlsext_host_name(hostname)
        except AttributeError:
            pass

The Fedora patch also does it incompletely. It allows you to call the
function and set the SNI extension but then doesn't use it properly in
hostname matching checks (e.g. if you explicitly connect to an IP address
it will complain).

> for the underlying non-DANE-specific bits.

Thanks for the pointer. I'll take a look at ssl_dane.

--Shumon.