Ssl – Dovecot issuing LetsEncrypt certificate, openssl / node tls fail to verify

dovecotlets-encryptnode.jsssl

EDIT running openssl s_client -connect mail.mydomain.com:993 -showcerts -CAfile identtrustroot.pem works. So that suggests that node tls doesn't have any knowledge of that root, surely that can't be?

I've got a dovecot instance issuing a LetsEncrypt cert for mail.mydomain.com. Thunderbird doens't complain, webmail doesn't complain, but both openssl s_client and nodejs tls do.

Example:

$ openssl s_client -connect mail.mydomain.com:993 -showcerts

depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
 0 s:/CN=mail.domain.com
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
-----BEGIN CERTIFICATE-----
#
# Removed for brevity
#
ZlmxXZ8eRkcfhlu6Sw==
-----END CERTIFICATE-----
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
-----BEGIN CERTIFICATE-----
#
# Removed for brevity
#
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=mail.domain.com
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-384, 384 bits
---
SSL handshake has read 3176 bytes and written 334 bytes
Verification error: unable to get local issuer certificate
---

My doveot config simply points to the Cerbot generated fullchain.pem and privkey.pem.

When using nodejs tls, I get a similar problem:

[connection] Error: Error: self signed certificate in certificate chain
{ Error: self signed certificate in certificate chain
    at TLSSocket.<anonymous> (_tls_wrap.js:1108:38)
    at emitNone (events.js:105:13)
    at TLSSocket.emit (events.js:207:7)
    at TLSSocket._finishInit (_tls_wrap.js:638:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:468:38) code: 'SELF_SIGNED_CERT_IN_CHAIN', source: 'socket' }
[connection] Closed

The certs CN is the same as the host, mail.domain.com, but I can only assume I'm eiter missing a cert or dovecot is in some way incorrectly configured. Has anyone come across this before or got any suggestions?

Best Answer

Works fine on my machine (Debian Jessie). I've had an issue with an older version of the certbot client, on an older version of Debian, using Courier - the fullchain.pem certificate wasn't created automatically, I had to cat several certs together to generate it each time I updated.

Output of your same sslclient command followed by output of doveconf -n from one working machine:

ivan@darkstar ~ $ openssl s_client -connect mail.example.com:993 -showcerts
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = example.com
verify return:1
---
Certificate chain
 0 s:/CN=example.com
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
-----BEGIN CERTIFICATE-----
MIIFVTCCBD2gAwIBAgISA+jVgnfoK82K032B7XyPIuO2MA0GCSqGSIb3DQEBCwUA
** snip **
idWK19DrVDGbqBItrFBkh9FFbaJDt7P7UUcUPtZW1JS8exsMYoz3peSw7unl+FC6
bVoetZqKD86UdI1nRhfsx5cTtY5IoGMdQg==
-----END CERTIFICATE-----
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
** snip **
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=example.com
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-384, 384 bits
---
SSL handshake has read 3237 bytes and written 463 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: F533DE0F3B74AA229A9B856A81B36D7B5E537AEDB1A1A70196582BA3734ED361
    Session-ID-ctx: 
    Master-Key: 2D16BBC4E5EF3367E448522AB16E8C34C572D0224669FFC9AEECCC6FD2928022E498E761323346D969101B9261825E22
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 02 cb be 44 b3 35 da fc-b9 f1 7f 6f 90 4f 97 9c   ...D.5.....o.O..
    0010 - a8 26 22 8c bb c4 cd e7-f2 94 39 35 27 19 91 b3   .&".......95'...
    0020 - 6b 19 b7 cd 89 55 53 78-c6 ba ee 56 36 42 a5 23   k....USx...V6B.#
    0030 - b0 43 1e a2 be 65 a8 be-fe 4b a1 68 cb f2 31 b5   .C...e...K.h..1.
    0040 - 0f ee 84 e1 d1 b3 e0 9a-c8 5c d1 a3 0f 6b ef c1   .........\...k..
    0050 - 13 c8 2c 1c 7a 43 a5 76-04 a0 d9 5c cf 8e ce a6   ..,.zC.v...\....
    0060 - 26 87 7e d0 0d fd 84 eb-0b 7c 89 7c bf b7 33 94   &.~......|.|..3.
    0070 - d4 1e be d1 07 f2 2c 59-9b b0 b9 4b 73 66 27 63   ......,Y...Ksf'c
    0080 - 21 a0 e9 88 bf d8 5e 47-e0 3d c1 df fc 60 63 c0   !.....^G.=...`c.
    0090 - 1c 67 5e 50 b5 1b 5e 4b-ba 1f 96 4d cc f8 43 a3   .g^P..^K...M..C.

    Start Time: 1506208904
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN] Dovecot ready.

And the doveconf -n output:

# 2.2.13: /etc/dovecot/dovecot.conf
# OS: Linux 4.9.36-x86_64-linode85 x86_64 Debian 8.8 ext4
auth_mechanisms = plain login
mail_location = maildir:/var/vmail/%d/%n/Maildir
managesieve_notify_capability = mailto
managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date ihave
namespace inbox {
  inbox = yes
  location = 
  mailbox Drafts {
    auto = subscribe
    special_use = \Drafts
  }
  mailbox Junk {
    auto = subscribe
    special_use = \Junk
  }
  mailbox Sent {
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
  mailbox Trash {
    auto = subscribe
    special_use = \Trash
  }
  prefix = 
}
passdb {
  args = /etc/dovecot/dovecot-sql.conf.ext
  driver = sql
}
plugin {
  sieve = ~/.dovecot.sieve
  sieve_after = /etc/dovecot/sieve-after
  sieve_dir = ~/sieve
}
postmaster_address = postmaster@%d
protocols = " imap lmtp sieve pop3"
service auth {
  unix_listener /var/spool/postfix/private/auth {
    group = postfix
    mode = 0660
    user = postfix
  }
}
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    group = postfix
    mode = 0600
    user = postfix
  }
}
ssl_cert = </etc/letsencrypt/live/example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/example.com/privkey.pem
userdb {
  args = uid=vmail gid=vmail home=/var/vmail/%d/%n
  driver = static
}
protocol lmtp {
  mail_plugins = " sieve"
}