-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
UPDATE: Please skip to follow-up comment, the original reproduction is flawed: #2883 (comment)
Before you open an issue please check which version you are running and whether it is the latest in stable / dev branch
GHCR.io 3.3dev image (published 3 hours ago)
Before you open an issue please whether this is a known problem by searching the issues
I couldn't find anything
Command line / docker command to reproduce
docker compose up -d --force-recreate
docker compose run --rm -it testssl --quiet --preference mail.example.test:993Output
Testing all IPv4 addresses (port 993): 172.18.0.4
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Start 2025-09-06 08:56:03 -->> 172.18.0.4:993 (mail.example.test) <<--
rDNS (172.18.0.4): example-dms-1.example_default.
Service detected: IMAP, thus skipping HTTP specific checks
Testing server's cipher preferences
Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits Cipher Suite Name (IANA/RFC)
-----------------------------------------------------------------------------------------------------------------------------
SSLv2
-
SSLv3
-
TLSv1
-
TLSv1.1
-
TLSv1.2 (server order)
xc02b ECDHE-ECDSA-AES128-GCM-SHA256 ECDH 253 AESGCM 128 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
xc02c ECDHE-ECDSA-AES256-GCM-SHA384 ECDH 253 AESGCM 256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
xcca9 ECDHE-ECDSA-CHACHA20-POLY1305 ECDH 253 ChaCha20 256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLSv1.3 (server order)
x1302 TLS_AES_256_GCM_SHA384 ECDH 253 AESGCM 256 TLS_AES_256_GCM_SHA384
x1303 TLS_CHACHA20_POLY1305_SHA256 ECDH 253 ChaCha20 256 TLS_CHACHA20_POLY1305_SHA256
x1301 TLS_AES_128_GCM_SHA256 ECDH 253 AESGCM 128 TLS_AES_128_GCM_SHA256
Has server cipher order? yes (OK) -- TLS 1.3 and below
Done 2025-09-06 08:56:22 [ 27s] -->> 172.18.0.4:993 (mail.example.test) <<--
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Done testing now all IP addresses (on port 993): 172.18.0.4Associated compose.yaml:
`compose.yaml` (collapsed for brevity)
name: example
services:
testssl:
scale: 0 # This avoids running the container during `docker compose up`
image: ghcr.io/testssl/testssl.sh:3.3dev
# Config for `testssl.sh` to trust the locally generated cert:
environment:
ADDTL_CA_FILES: "/tmp/tls/ca-cert.pem"
configs:
- source: tls-ca-cert
target: /tmp/tls/ca-cert.pem
# Service to test against:
dms:
image: mailserver/docker-mailserver:15.1.0
hostname: mail.example.test
environment:
- SSL_TYPE=manual
- SSL_KEY_PATH=/tmp/tls/key.pem
- SSL_CERT_PATH=/tmp/tls/cert.pem
configs:
# Extra config bundled into the `compose.yaml` to ease testing:
- source: dms-accounts
target: /tmp/docker-mailserver/postfix-accounts.cf
- source: tls-cert
target: /tmp/tls/cert.pem
- source: tls-key
target: /tmp/tls/key.pem
# Required to reproduce the observed bug by removing DHE support (while retaining DHE in server order):
- source: dovecot-overrides
target: /tmp/docker-mailserver/dovecot.cf
# Optional - Allows clients in the container to verify cert trust with the CA that signed it:
- source: tls-ca-cert
target: /tmp/tls/ca-cert.pem
configs:
# Pre-provisioned account for local reproduction use:
# NOTE: `$` is escaped by repeating it to avoid the Docker Compose ENV interpolation feature
# Password is `secret`
dms-accounts:
content: |
[email protected]|{SHA512-CRYPT}$$6$$sbgFRCmQ.KWS5ryb$$EsWrlYosiadgdUOxCBHY0DQ3qFbeudDhNMqHs6jZt.8gmxUwiLVy738knqkHD4zj4amkb296HFqQ3yDq4UXt8.
# Example ECDSA cert files for testing locally (provisioned for `mail.example.test`):
tls-ca-cert:
content: |
-----BEGIN CERTIFICATE-----
MIIBfTCCASKgAwIBAgIRAMAZttlRlkcuSun0yV0z4RwwCgYIKoZIzj0EAwIwHDEa
MBgGA1UEAxMRU21hbGxzdGVwIFJvb3QgQ0EwHhcNMjEwMTAxMDAwMDAwWhcNMzEw
MTAxMDAwMDAwWjAcMRowGAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTBZMBMGByqG
SM49AgEGCCqGSM49AwEHA0IABJX2hCtoK3+bM5I3rmyApXLJ1gOcVhtoSSwM8XXR
SEl25Kkc0n6mINuMK8UrBkiBUgexf6CYayx3xVr9TmMkg4KjRTBDMA4GA1UdDwEB
/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBQD8sBrApbyYyqU
y+/TlwGynx2V5jAKBggqhkjOPQQDAgNJADBGAiEAi8N2eOETI+6hY3+G+kzNMd3K
Sd3Ke8b++/nlwr5Fb/sCIQDYAjpKp/MpTDWICeHC2tcB5ptxoTdWkTBuG4rKcktA
0w==
-----END CERTIFICATE-----
tls-key:
content: |
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOc6wqZmSDmT336K4O26dMk1RCVc0+cmnsO2eK4P5K5yoAoGCCqGSM49
AwEHoUQDQgAEFOWNgekKKvUZE89vJ7henUYxODYIvCiHitRc2ylwttjqt1KUY1cp
q3jof2fhURHfBUH3dHPXLHig5V9Jw5gqeg==
-----END EC PRIVATE KEY-----
tls-cert:
content: |
-----BEGIN CERTIFICATE-----
MIIB9DCCAZqgAwIBAgIQE53a/y2c//YXRsz2kLm6gDAKBggqhkjOPQQDAjAcMRow
GAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTAeFw0yMTAxMDEwMDAwMDBaFw0zMTAx
MDEwMDAwMDBaMBkxFzAVBgNVBAMTDlNtYWxsc3RlcCBMZWFmMFkwEwYHKoZIzj0C
AQYIKoZIzj0DAQcDQgAEFOWNgekKKvUZE89vJ7henUYxODYIvCiHitRc2ylwttjq
t1KUY1cpq3jof2fhURHfBUH3dHPXLHig5V9Jw5gqeqOBwDCBvTAOBgNVHQ8BAf8E
BAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBSz
w74g+O6dcBbwienD70D8A9ESmDAfBgNVHSMEGDAWgBQD8sBrApbyYyqUy+/TlwGy
nx2V5jBMBgNVHREERTBDghFtYWlsLmV4YW1wbGUudGVzdIIVbWFpbC5kZXN0aW5h
dGlvbi50ZXN0ghdzbXRwLnJlbGF5LXNlcnZpY2UudGVzdDAKBggqhkjOPQQDAgNI
ADBFAiEAoety5oClZtuBMkvlUIWRmWlyg1VIOZ544LSEbplsIhcCIHb6awMwNdXP
m/xHjFkuwH1+UjDDRW53Ih7KZoLrQ6Cp
-----END CERTIFICATE-----
dovecot-overrides:
content: |
# Unset this setting to no longer support negotiating DHE cipher suites
ssl_dh =
# This setting is the equivalent value configured in the image,
# except the DHE cipher suites have been removed. Uncomment this setting to get expected output:
# Ref: https://github.com/docker-mailserver/docker-mailserver/blob/5f4e868c541b142c705a643315ba8828d1836660/target/scripts/helpers/ssl.sh#L145-L146
#ssl_cipher_list = ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384Expected behavior
This took a while to troubleshoot, but eventually realized OpenSSL could negotiate it successfully (EDIT: Bad recall on my part), but testssl.sh was failing to report the cipher, I have found I could successfully negotiate the cipher suites that are expected to remain compatible:
# Directly verify `-cipher` negotiates successfully (requires uncommenting `ssl_cipher_list` in `compose.yaml`):
$ docker compose exec dms bash
$ timeout 1 openssl s_client -tls1_2 -cipher ECDHE-ECDSA-AES256-SHA384 -connect mail.example.test:993 -CAfile /tmp/tls/ca-cert.pemUPDATE: I thought this was a (EDIT: this observation was flawed, OpenSSL can directly negotiate a compatible cipher successfully) 😓 Assuming that testssl.sh issue, but realized while filing the report that my OpenSSL results were actually with the corrected Dovecot ssl_cipher_list settingtestssl.sh behaves the same as OpenSSL, it may not be able to negotiate any other compatible cipher due to the configured server preference order for Dovecot (which is where the actual bug of a contribution was coming from, caught thanks to testssl.sh! ❤️).
Instead of this incorrect result:
TLSv1.2 (server order)
xc02b ECDHE-ECDSA-AES128-GCM-SHA256 ECDH 253 AESGCM 128 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
xc02c ECDHE-ECDSA-AES256-GCM-SHA384 ECDH 253 AESGCM 256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
xcca9 ECDHE-ECDSA-CHACHA20-POLY1305 ECDH 253 ChaCha20 256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
I expected the valid ciphers (or some warning emitted about bailing early):
TLSv1.2 (server order)
xcca9 ECDHE-ECDSA-CHACHA20-POLY1305 ECDH 253 ChaCha20 256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
xc02b ECDHE-ECDSA-AES128-GCM-SHA256 ECDH 253 AESGCM 128 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
xc02c ECDHE-ECDSA-AES256-GCM-SHA384 ECDH 253 AESGCM 256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
xc023 ECDHE-ECDSA-AES128-SHA256 ECDH 253 AES 128 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
xc024 ECDHE-ECDSA-AES256-SHA384 ECDH 253 AES 256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
or equivalent if results were stored via JSON using options --jsonfile-pretty port_993.json --overwrite:
$ docker compose run --rm -it \
--volume ./testssl:/output \
--workdir /output \
--user "$(id -u):$(id -g)" \
testssl --quiet --preference --jsonfile-pretty port_993.json --overwrite mail.example.test:993
# Get the TLS 1.2 cipher suite server order:
$ jq --raw-output '.scanResult[0].serverPreferences[] | select(.id == "cipherorder_TLSv1_2") | .finding' testssl/port_993.json
ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA384Your system (please complete the following information):
- N/A (using the GHCR.io image)
Additional context
--debug 2 comparison:
Actual: (bailed early on (TLS) ServerHello empty for failed negotiation on DHE ciphersuite?)
Output
TLSv1.2
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
(TLS) ServerHello empty, TCP connection closed
(1 lines returned)
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
(server order)
xc02b ECDHE-ECDSA-AES128-GCM-SHA256 ECDH 253 AESGCM 128 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
xc02c ECDHE-ECDSA-AES256-GCM-SHA384 ECDH 253 AESGCM 256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
xcca9 ECDHE-ECDSA-CHACHA20-POLY1305 ECDH 253 ChaCha20 256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
Expected:
Output
TLSv1.2
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
sending close_notify...
(46 lines returned)
sending client hello... sending client hello... reading server hello...
(TLS) ServerHello empty, TCP connection closed
(1 lines returned)
(server order)
xcca9 ECDHE-ECDSA-CHACHA20-POLY1305 ECDH 253 ChaCha20 256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
xc02b ECDHE-ECDSA-AES128-GCM-SHA256 ECDH 253 AESGCM 128 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
xc02c ECDHE-ECDSA-AES256-GCM-SHA384 ECDH 253 AESGCM 256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
xc023 ECDHE-ECDSA-AES128-SHA256 ECDH 253 AES 128 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
xc024 ECDHE-ECDSA-AES256-SHA384 ECDH 253 AES 256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384