Postfix 和 OpenJDK 11:"No appropriate protocol (protocol is disabled or cipher suites are inappropriate)"

回答 7 浏览 15.9万 2021-06-09

我知道这个主题还有一些其他问题(及其答案)。但这些对我都没有帮助。

我有一个 Postfix 服务器(Debian 10 (Buster) 上的 postfix 3.4.14),具有以下配置(只有有趣的部分):

smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA,
    CAMELLIA128, 3DES, CAMELLIA256, RSA+AES, eNULL
smtp_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA,
    CAMELLIA128, 3DES, CAMELLIA256, RSA+AES, eNULL
tls_preempt_cipherlist = yes
tls_high_cipherlist = !aNULL:!eNULL:!CAMELLIA:HIGH:@STRENGTH

如果我使用 OpenSSL 检查配置,我会得到(请注意,我用 "xxxxxx.de "使域名无法识别):

#> openssl s_client -connect xxxxxx.de:25 -starttls smtp
CONNECTED(00000003)
depth=3 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = xxxxxx.de
verify return:1
---
Certificate chain
 0 s:/CN=xxxxxx.de
   i:/C=US/O=Let's Encrypt/CN=R3
 1 s:/C=US/O=Let's Encrypt/CN=R3
   i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
 2 s:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFRjCCBC6gAwIBAgISA6SNmc1MPKtxwSiNNKEvxc/EMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
...
...
...
VG2iG8sEGCcgG4w1LnWTO4tMlCYFE+tcXxAfE/7pB/VjmvRZlLCypanuwBzVRw5W
bPwabUtCMRDrRlT8wI9UHAhQYTb5Hhm0F0u1hi6e/7fybK6tuFnPpWs/vgT3Z4Fj
2onoaTHk/rKlhQ==
-----END CERTIFICATE-----
subject=/CN=xxxxxx.de
issuer=/C=US/O=Let's Encrypt/CN=R3
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4950 bytes and written 450 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: B20E725616C98083988847B90FB42BFDCAEED745129C53E79E723692C641F6F5
    Session-ID-ctx:
    Master-Key: A3D2C497E11E47C6260C119E47DC3B4CAA119485EAFA5BCF6CDA882F115D80E78960C802A48E375DAA293A3A2C1DAE35
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - ec 40 39 d6 f4 94 ac 7b-d8 f8 ef 94 98 62 d7 35   .@9....{.....b.5
    0010 - de fb c3 f5 f3 b1 3a d1-24 3e 62 57 fb 06 56 eb   ......:.$>bW..V.
    0020 - 84 61 2a 0d 30 7d 9f ac-70 e7 a8 a3 23 4a c6 57   .a*.0}..p...#J.W
    0030 - dc 21 7c d3 5d f4 e8 14-c5 4c 18 da 35 1d 32 49   .!|.]....L..5.2I
    0040 - f0 19 de 75 77 22 25 f9-74 4d a2 47 39 0d ce 75   ...uw"%.tM.G9..u
    0050 - 0a 04 41 85 0d 67 05 fe-a4 09 ec 72 4b a5 ad f4   ..A..g.....rK...
    0060 - 8b 73 a2 a3 2e 28 46 b8-2a 60 4b ed ce 75 09 fb   .s...(F.*`K..u..
    0070 - ef 95 e3 e2 6e 6a 90 bd-9e 46 e8 c9 aa 52 c3 ae   ....nj...F...R..
    0080 - 72 6f 9f 37 fd 6c 12 e9-bb 60 83 c6 c4 44 ca 85   ro.7.l...`...D..
    0090 - cb ee 1d bd 69 29 77 31-4f 96 d5 4d 93 8e 63 d2   ....i)w1O..M..c.

    Start Time: 1623221077
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
250 CHUNKING

在这里,我想知道这句话

New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384

因为 TLSv1/SSLv3 应通过 postfix 配置禁用。可能是这个问题吗?

然而。在客户端,我有一个 Java 应用程序(OpenJDK 11.0.11),每次发送电子邮件时,我都会收到:

javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
at javax.mail.Service.connect(Service.java:295)
...

当然,我已经编辑了conf/security/java.security文件。我已经将ECDHE-RSA-AES256-GCM-SHA384 添加为jdk.tls.legacyAlgorithms。以下是java.securtity的有趣设置:

jdk.tls.legacyAlgorithms= \
        K_NULL, C_NULL, M_NULL, \
        DH_anon, ECDH_anon, \
        RC4_128, RC4_40, DES_CBC, DES40_CBC, \
        3DES_EDE_CBC, ECDHE-RSA-AES256-GCM, ECDHE-RSA-AES256-GCM-SHA384

jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
    RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, \
    include jdk.disabled.namedCurves

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves

也许我是瞎子,但我不知道我的问题在哪里......

好吧,首先我已经从jdk.tls.legacyAlgorithms中删除了我的扩展,因为这些扩展没有帮助而且是错误的(感谢 dave_thompson_085 的提示)。

以下是发送电子邮件的 Java 代码(该代码具有“悠久”的历史,所以请不要奇怪为什么使用 Vector 而不是 ArrayList 或如此......)

// Create some properties and get the default Session
Properties props = new Properties();
props.put("mail.smtp.host", smtpServer);
props.put("mail.smtp.port", "25");
props.put("mail.debug", "true");

// SMTP authentication?
Session session;
if (username != null && pwd != null && username.length() > 0 && pwd.length() > 0) {
  props.put("mail.smtp.auth", "true");
  //props.put("mail.smtp.user", username);
  //props.put("mail.password", pwd);

  // if SMTP authentication: use TLS in every case!
  tls = true;

  session = Session.getInstance(props, new MyPasswordAuthenticator(username, pwd));
} else {
  session = Session.getDefaultInstance(props, null);
}

// TLS?
if (tls) {
  props.put("mail.smtp.starttls.enable", "true");
  //props.put("mail.smtp.tls", "true");
}

// create a message
SMTPMessage mimeMsg = new SMTPMessage(session);

InternetAddress addressFrom = new InternetAddress(sender);
mimeMsg.setFrom(addressFrom);
mimeMsg.setEnvelopeFrom(sender);

// Set recipients ...
InternetAddress[] tos = new InternetAddress[receivers.size()];
int i = 0;
for (String addr : receivers) {
  tos[i++] = new InternetAddress(addr, extractPersonalNameFromEMailAddr(addr));
}

// Set CC recipients ...
InternetAddress[] ccAddrs = new InternetAddress[0];
if (ccs != null) {
  ccAddrs = new InternetAddress[ccs.size()];

  i = 0;
  for (String addr : ccs) {
    ccAddrs[i++] = new InternetAddress(addr, extractPersonalNameFromEMailAddr(addr));
  }
}

mimeMsg.setRecipients(Message.RecipientType.TO, tos);
mimeMsg.setRecipients(Message.RecipientType.CC, ccAddrs);

// Set return notifications
if (readNotificationRequest) {
  String notifyAddr = replyTo;
  if (notifyAddr == null || notifyAddr.trim().length() == 0) notifyAddr = sender;

  mimeMsg.addHeader("Disposition-Notification-To", "<" + notifyAddr + ">");
  mimeMsg.addHeader("Return-Receipt-To", "<" + notifyAddr + ">");
}

mimeMsg.addHeader("Date", mailDateFormat.format(new Date()));

mimeMsg.setNotifyOptions(deliverNotificationRequest);
mimeMsg.setReturnOption(deliverNotificationContent);

if (replyTo != null) {
  Address[] replyToAddrs = new Address[1];
  replyToAddrs[0] = new InternetAddress(this.replyTo);

  mimeMsg.setReplyTo(replyToAddrs);
  mimeMsg.setFrom(replyToAddrs[0]);
}

mimeMsg.setSentDate(new Date());
mimeMsg.setSubject(subject);
//mimeMsg.setContent(msg, msgType);

// Set the text content:
MimeBodyPart msgPart = new MimeBodyPart();
msgPart.setContent(msg, msgType + "; charset=" + charset);

Multipart multipart = new MimeMultipart();
multipart.addBodyPart(msgPart);

// Add the attachments:
String attFile;
MimeBodyPart attachment;
Iterator<String> it = new Vector<String>(attachments).iterator();

while (it.hasNext()) {
  attFile = it.next();

  attachment = new MimeBodyPart();
  attachment.setDataHandler(new DataHandler(new AppOctetStreamFileDataSource(attFile)));
  attachment.setFileName(FileUtil.extractFilename(attFile));

  multipart.addBodyPart(attachment);
}

mimeMsg.setContent(multipart);

System.out.println("mail.smtp.ssl.trust: <<" + System.getProperty("mail.smtp.ssl.trust") + ">>");
System.out.println("mail.smtp.ssl.socketfactory.class: <<" + System.getProperty("mail.smtp.ssl.socketfactory.class") + ">>");
System.out.println("mail.smtp.socketfactory.class: <<" + System.getProperty("mail.smtp.socketfactory.class") + ">>");
System.out.println("mail.smtp.ssl.protocols: <<" + System.getProperty("mail.smtp.ssl.protocols") + ">>");
System.out.println("mail.smtp.ssl.ciphersuites: <<" + System.getProperty("mail.smtp.ssl.ciphersuites") + ">>");
System.out.println("SSLContext.getDefault().getDefaultSSLParameters().getProtocols(): "
        + Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getProtocols()));
System.out.println("Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites(): "
        + Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites()));

session.setDebug(debug);
Transport transport = session.getTransport("smtp");
transport.connect(smtpServer, 25, username, pwd);

//System.out.println("#########" + System.getProperty("mail.smtp.localhost"));

transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());

transport.close();

为了调试,我添加了一些 System.out 来输出一些有趣的值。

这里是标准输出:

DEBUG: JavaMail version 1.4.7
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
mail.smtp.ssl.trust: <<null>>
mail.smtp.ssl.socketfactory.class: <<null>>
mail.smtp.socketfactory.class: <<null>>
mail.smtp.ssl.protocols: <<null>>
mail.smtp.ssl.ciphersuites: <<null>>
SSLContext.getDefault().getDefaultSSLParameters().getProtocols(): [TLSv1.3, TLSv1.2]
Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites(): [TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]

和标准错误:

javax.net.ssl|DEBUG|01|main|2021-06-10 08:28:39.042 CEST|SSLCipher.java:438|jdk.tls.keyLimits: entry = AES/GCM/NoPadding KeyUpdate 2^37. AES/GCM/NOPADDING:KEYUPDATE = 137438953472
javax.net.ssl|ERROR|01|main|2021-06-10 08:28:39.306 CEST|TransportContext.java:341|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking (
"throwable" : {
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at java.base/sun.security.ssl.HandshakeContext.(HandshakeContext.java:170)
at java.base/sun.security.ssl.ClientHandshakeContext.(ClientHandshakeContext.java:98)
at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:221)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:433)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549)
at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:486)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1902)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
at javax.mail.Service.connect(Service.java:295)
at com.coco_on.tools.general.useCases.net.UCSendEMail.start(UCSendEMail.java:470)
at com.tetrixSystems.tHiddenExecuter.Executer.start(Executer.java:233)
at com.tetrixSystems.tHiddenExecuter.UCMain.start(UCMain.java:83)
at com.tetrixSystems.tHiddenExecuter.UCMain.main(UCMain.java:49)}

)
javax.net.ssl|DEBUG|01|main|2021-06-10 08:28:39.306 CEST|SSLSocketImpl.java:1638|close the underlying socket
javax.net.ssl|DEBUG|01|main|2021-06-10 08:28:39.306 CEST|SSLSocketImpl.java:1657|close the SSL connection (initiative)
javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
at javax.mail.Service.connect(Service.java:295)
at com.coco_on.tools.general.useCases.net.UCSendEMail.start(UCSendEMail.java:470)
at com.tetrixSystems.tHiddenExecuter.Executer.start(Executer.java:233)
at com.tetrixSystems.tHiddenExecuter.UCMain.start(UCMain.java:83)
at com.tetrixSystems.tHiddenExecuter.UCMain.main(UCMain.java:49)
Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at java.base/sun.security.ssl.HandshakeContext.(HandshakeContext.java:170)
at java.base/sun.security.ssl.ClientHandshakeContext.(ClientHandshakeContext.java:98)
at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:221)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:433)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549)
at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:486)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1902)
... 6 more

在 Postfix 服务器端,安装了 OpenSSL 1.1.1:

#> openssl version
OpenSSL 1.1.1d  10 Sep 2019

我不确定Java是否在内部使用OpenSSL,但客户端openssl版本(CentOS/ RHEL 7) 也可能很有趣:

#> openssl version
OpenSSL 1.0.2k-fips  26 Jan 2017
Steffen 提问于2021-06-09
7 个回答
#1楼
得票数 42

我在使用 JDK 11 时遇到了同样的问题。但我通过在 java.security 文件中注释这一行来解决它:

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA,
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL,
    include jdk.disabled.namedCurves
Zeenat Hussain 提问于2021-07-26
Peter Mortensen 修改于2022-08-19
当我在 Linux 机器上运行带有开放 JDK 11 安装的应用程序时,这个答案对我有帮助Prasanth Rajendran 2021-08-17
用于1.8.0_301l33tHax0r 2021-10-11
这解决了我的问题。文件的路径对我来说是/usr/lib/jvm/java-11-openjdk-amd64/conf/security/java.securityAsocia 2021-10-19
这很危险!然后您允许使用不安全的算法。Georg Schölly 2021-11-18
调整这些设置可能存在安全风险,但至少您可以让“旧”库再次工作。如果您无法更新旧的遗留代码,请将其视为解决方法。至少你可以更新java版本。TMS 2021-11-30
#2楼 已采纳
得票数 39

将JavaMail从1.4.7升级到1.6.2后,错误消失了!我确信还有其他客户端使用 JavaMail 1.4.7 并且可以正常工作。所以那台机器上肯定还存在另一个差异。然而,现在它可以工作

Steffen 提问于2021-06-14
Peter Mortensen 修改于2022-08-19
其他使用旧版 javamail 的客户端连接到此仅允许 TLS1.2 和 1.3 的服务器?你确定吗?您可以使用 javax.net.debug 或使用wireshark 等外部跟踪来确认 ServerHello 中的协议是什么?dave_thompson_085 2021-06-15
@dave_thompson_085:我找到了另一个带有 JavaMail 1.4.7 的客户端,你是对的。该错误也存在(但由于“... > /dev/null 2>&1”arrgh而未报告)。但我发现另外两个客户端上的 JavaMail 1.3 就像它一样存储在 jar 的 MANIFEST 中(噢,该死,那太旧了!!!)。并且在该客户端上它有效! javax.net.debug 属性不起作用(可能在 1.3 中没有实现...)。在更新 JavaMail 之前,我将尝试创建(可能是明天)一个 tcpdumpSteffen 2021-06-15
javax.net.debug 位于 JRE(特别是 JSSE)而不是 Javamail 中——尽管较旧的 JRE 写入 stdout,而较新的 JRE 写入 stderr,这可能会对捕获它产生影响。 AFAICS Javamail 的在线存储库不会回到 1.3,但我可以想象旧版本根本不支持 SSL/TLS 或至少不支持 STARTTLS。dave_thompson_085 2021-06-15
今天我也遇到了这个问题,在最新的 Java 8 JRE 上运行 javax.mail 1.4.7。完全相同的代码在另一台具有较新的 Java 8 JRE 和相同的 1.4.7 JavaMail JAR 的服务器上运行得非常好。按照您的建议,我通过升级到 JavaMail 1.6.7 在第一个系统上修复了此问题。然后我也升级了另一台服务器,所以现在应用程序在两台服务器上都成功运行了 JavaMail 1.6.7。也许最近的 Java 8 版本中发生了一些变化,破坏了 JavaMail 1.4.7 的某些 SMTP 服务器......Mauro Molinari 2021-08-06
为我工作(至少在找到旧 Oracle 版本 java.mail 的正确替代品之后)。我最终使用:com.sun.mail / jakarta.mail Verison 1.6.7McIntosh 2022-02-10
#3楼
得票数 18

就我而言,Postfix 支持 TLS 1.0、TLS 1.1、TLS 1.2 和 TLS 1.3。 我使用不同的 OpenJDK 准备了一些测试。

  • 使用 OpenJDK 11.0.9 (2020-10-20)

    我能够毫无例外地发送电子邮件

  • 使用 OpenJDK 11.0.10 (2021-01-19)

    我能够毫无例外地发送电子邮件

  • 使用 OpenJDK 11.0.11 (2021-04-20)

    我得到了例外,

    SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

  • 使用 OpenJDK 11.0.12 (2021-07-20)

    我遇到了同样的异常,

    SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

据我所知,问题的原因是 OpenJDK 从 11.0.11 版本开始需要 TLSv1.2 或 TLSv1.3。 此更改将适用于至少 OpenJDK 8u292 及以上版本、OpenJDK 11.0.11 及以上版本以及 OpenJDK 16 的所有版本,遵循 Oracle 参考

如何解决问题,

  1. 返回 OpenJDK 11.0.10,您可以找到二进制文件 这里。更多 OpenJDK 版本此处
  2. (首选) 将 TLS 版本设置为 TLS 1.2 以发送电子邮件。在配置 Java SMTP 客户端之前,您可以通过设置如下所示的系统属性来完成此操作。

System.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");

我使用 Apache Commons 电子邮件并在初始化我的 HtmlEmail 对象之前设置上述属性,我能够使用当前 OpenJDK 版本 11.0.12 发送。

无论如何,您使用 POP3 Java 客户端,同样如此,

System.setProperty("mail.pop3s.ssl.protocols", "TLSv1.2");

Georgios Syngouroglou 提问于2021-08-07
Peter Mortensen 修改于2022-08-19
我知道我应该避免这种评论,但谢谢你。Felipe 2022-07-04
在我的情况下(openjdk 1.8.0_332),将 JavaMail 从 1.4.7 更新到 1.6.2 没有效果。这个解决了!Gilberto 2022-07-06
#4楼
得票数 9

我通过将其添加到我的连接字符串中摆脱了上述异常。

jdbc:mysql://localhost:3306/Peoples?autoReconnect=true&useSSL=false
Usama 提问于2021-09-23
Peter Mortensen 修改于2022-08-19
禁用 SSL 会带来安全风险。这是一种解决方法,而不是解决方案Dave B 2021-11-18
@DaveB 我发现这个答案对于我在本地测试时很有用。无论如何,生产使用 SSL。该解决方法是可以接受的。ivan0kurnia 2023-08-15
#5楼
得票数 5

在这里我想知道 [in s_client] 行
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384

显然您正在使用 OpenSSL 1.0.2,这基本上是一个无用的遗留物。回到 OpenSSL 支持 SSLv2 的时代(主要到 2010 年,尽管 2000 年之后几乎没有人使用它),用于 SSLv3 及更高版本的密码套件值(包括所有 TLS,但在 2014 年之前 OpenSSL 没有实现高于 TLS 1.0)的结构与 SSL 2.0,因此通过“universe”来限定密码套件非常重要它与实际使用的协议版本几乎无关,它出现在稍后的 session-param 解码中:

SSL-Session:
    Protocol  : TLSv1.2
...

-- 尽管您已经从密码套件中知道了这一点,因为 ECDHE-RSA-AES256-GCM-SHA384 不能在 TLS 1.2 以外的任何协议版本中使用。

在OpenSSL 1.1.0版本中,协议状态机被重新设计,除其他外,该字段被更改为显示与密码套件兼容的最小协议版本,这不再完全无用,但仍然可能与实际使用的协议不同。

无论如何,您的异常发生在 JSSE 客户端向服务器发送 ClientHello 开始握手之前,因此物理上不可能是由服务器中的任何错误引起的。 相反,它是由(Java)客户端上的编码或配置错误引起的,而您几乎没有提供有关该错误的信息。

使用 sysprop javax.net.debug=ssl:handshake 运行可能有所帮助,尽管此问题发生得很早,并且可能早于任何有用的可追踪的事情。

确保您没有将 sysprops mail.smtp.ssl.{protocols,ciphersuites} 设置为不合适的内容。参见例如com.sun.mail.util.SocketFetcher.configureSSLSocket) 和 Docker container error: "javax.mail.MessagingException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate);" 和链接。 还要检查mail.smtp.ssl.trust mail.smtp.ssl.socketfactory.class mail.smtp.socketfactory.class的任何设置,以及任何改变SSLSocketFactory默认值的代码,以及对SSLContext默认值的可能编辑)更改,即位于或接近点您尝试使用 javamail print 连接或以其他方式获取 Arrays.toString(SSLContext.getDefaultSSLParameters().getProtocols())getCipherSuites 相同。

编辑 2依赖于版本。旧版 Sun/Oracle(即 Jakarta 之前的版本)低于 1.5.3 (2015-04 -15) 具有默认值(如果mail.smtp.ssl.protocols未配置)硬编码TLSv1,表示 1.0。因此,连接将失败,并在禁用 TLS 1.0 的 Java 上出现异常,如安装 11.0.11 时的情况,以及 16.0.0 及 8u291(可能是 up)。在没有禁用 TLS 1.0 的 Java 实例上,它将尝试连接,但如果服务器拒绝 TLS 1.0(本问题中的服务器应该这样做),连接仍然会失败,并出现不同的异常。

我已经添加了 ECDHE-RSA-AES256-GCM-SHA384 作为 jdk.tls.legacyAlgorithms。

那是倒退了。遗留算法是您不喜欢使用的算法,仅作为后备算法接受;这个密码套件是当前可用的最好的密码套件之一,应该是首选(并且是默认的,所以您不应该更改它)。另外,尽管文件中的文档和注释没有明确说明这一点,但遗留约束无论如何仅适用于服务器端——因为这是完成密码套件选择和 1.3 相关算法选择的地方。

dave_thompson_085 提问于2021-06-09
Peter Mortensen 修改于2022-08-19
谢谢。我已编辑我的问题并添加更详细的信息Steffen 2021-06-09
Steffen:(1)正如我担心的,JSSE 跟踪没有帮助(2)你检查了 3 个 sysprops,但没有检查其他 2 个(3)我提醒 SSLSocketFactory 没有自己的默认值,所以我们不需要要检查这一点,但 SSLContext 确实如此,因此请检查 - 请参阅编辑 (4) Java 不使用 openssl,但是当您在客户端计算机上执行 openssl s_client 时,您使用了 OpenSSL 1.0.2 ,这就是我所解释的dave_thompson_085 2021-06-10
为了不让我的问题太长,我只更新了我的编辑部分(而不是添加一个新的编辑部分)。致(4):是的,你说得对。当我从命令行调用 openssl 时,“TLSv1/SSLv3”输出正在到来(与 java 无关):-)Steffen 2021-06-10
好吧,我现在很困惑——因为 sysprops 没有设置,而 JSSE 默认的 AFAICS 应该可以工作。我目前没有可以调试这个的环境;我会设置一个,但这可能需要一段时间。如果重要的话,请确定您正在使用的 javamail 版本。dave_thompson_085 2021-06-12
我有另一个想法,这可能是问题所在。邮件服务器的 LetsEncrypt 证书可能发生了任何变化。我将重试将 LetsEncrypt 的根证书添加到信任库中并再次检查。但我也不确定我是否可以在接下来的几天内做到这一点(因为在私人项目和另一边的其他商业项目中出现了一些时间问题......):但是,如果在Java中某些SSL加密失败我希望有更多错误详细信息。目前,它就像错误消息“有什么问题”......:-(Steffen 2021-06-13
#6楼
得票数 4

如果您使用 Java 1.8,请转到目录

..\Java\jre1.8.0_261\lib\security

如果您使用 Java 11 或 17,

..\Java\jdk-11.0.15\conf\security\

找到文件java.security

找到线条

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL

在每行前面加上#,然后保存。

Vladi 提问于2022-07-25
Peter Mortensen 修改于2022-08-19
#7楼
得票数 0

对于Java

openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment (build 11.0.13+8-Ubuntu-0ubuntu1.20.04)
OpenJDK 64-Bit Server VM (build 11.0.13+8-Ubuntu-0ubuntu1.20.04, mixed mode, sharing)

我有同样的问题。 smtp服务器使用的是Tls1.2,openssl测试证明了这一点:

 openssl s_client  smtp -connect ourhost:587

此输出清楚地向我显示 SMTP 服务器使用 Tls1.2:

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 2412 bytes and written 442 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated

但对于所有设置,例如

mail.properties.mail.smtp.auth=true
mail.properties.mail.smtp.starttls.enable=true
mail.properties.mail.smtp.ssl.protocols=TLSv1.2
jdk.tls.client.protocols=TLSv1.2
mail.properties.mail.smtp.ssl.trust=*

仍然是错误

Mail server connection failed; nested exception is javax.mail.MessagingException: Could not convert socket to TLS; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate). Failed messages: javax.mail.MessagingException: Could not convert socket to TLS; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

唯一有帮助的就是从 java.security 文件中删除 Tls 部分,如上所述:

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves
Eljah 提问于2023-02-09