后缀和 openJDK 11:"No appropriate protocol (protocol is disabled or cipher suites are inappropriate)"
postfix and openJDK 11: "No appropriate protocol (protocol is disabled or cipher suites are inappropriate)"
我知道这个主题还有一些其他问题(有答案)。但是这些都对我没有帮助。
我有一个 postfix 服务器(debian 10 上的 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 应该被后缀配置禁用。会不会是这个问题?
不过。在客户端,我有一个 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 AUTH?
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 AUTH: use in every case TLS!
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 用于输出一些有趣的值。
此处 stdout
输出:
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]
和 stderr
:
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
Here I'm wondering about the line [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 没有实现高于 TLS1.0 ) 的结构与用于 SSLv2 的那些不同,因此通过它所在的 'universe' 来限定密码套件很重要。它几乎与实际使用的协议版本无关,它稍后出现在会话参数中解码:
SSL-Session:
Protocol : TLSv1.2
...
--虽然你已经从ciphersiote中知道了这一点,因为ECDHE-RSA-AES256-GCM-SHA384不能用于除TLS1.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 and Docker Container 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
.
也是如此
EDIT2:它依赖于版本。低于 1.5.3 (2015-04-15) 的旧 Sun/Oracle(即雅加达之前)版本具有默认值(如果未配置 mail.smtp.ssl.protocols
)HARDCODED to TLSv1
meaning 1.0 ONLY。结果,连接将失败,但在禁用了 TLS1.0 的 Java 上的 Q 中出现异常,就像安装时 11.0.11 以及 16.0.0 和 8u291(大概是向上)一样。在未禁用 TLS1.0 的 Java 个实例上,它将 尝试 连接,但如果服务器拒绝 TLS1.0——这个 Q 中应该拒绝的——连接将仍然失败,出现不同的异常。
I have added already ECDHE-RSA-AES256-GCM-SHA384 as jdk.tls.legacyAlgorithms.
倒退了。遗留算法是您不希望使用的算法,仅作为后备接受;这个密码套件是目前可用的最好的密码套件之一,应该是首选(默认情况下,所以你不应该改变它)。另外,虽然文件中的文档和评论没有明确说明,但遗留约束无论如何只适用于服务器端——因为这是密码套件选择和 1.3 相关算法选择的地方。
将 JavaMail 从 1.4.7 升级到 1.6.2 后错误消失了!我敢肯定还有其他客户端使用 JavaMail 1.4.7 并且可以正常工作。所以那台机器上肯定还有另一个区别。但是,现在可以了!
非常感谢 dave_thompson_085。你给我指出了正确的方法:-)。我认为你的回答对其他有同样问题的人来说是一个很好的指导(我可以检查哪些属性等等)。
我在使用 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
就我而言,postfix 支持 TLSv1、TLSv1.1、TLSv1.2 和 TLSv1.3。
我准备了一些测试,使用不同的 OpenJDKs.
使用打开JDK 11.0.9 (2020-10-20)
我能够毫无例外地发送电子邮件
使用打开JDK 11.0.10 (2021-01-19)
我能够毫无例外地发送电子邮件
使用打开JDK 11.0.11 (2021-04-20)
我遇到了异常,
SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
- 使用打开JDK 11.0.12 (2021-07-20)
我遇到了同样的异常,
SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
据我所知,问题的原因是OpenJdk需要TLSv1.2或TLSv1.3,从版本11.0.11开始。 更新:此更改将至少适用于 OpenJDK 8u292 及以上版本、OpenJDK 11.0.11 及以上版本,以及 JRE 之后的所有 OpenJDK 16 版本和 JDK Oracle reference.
发布的加密路线图
如何解决问题,
- 回到OpenJDK 11.0.10,可以找到二进制文件here. More OpenJDK versions here.
- (首选) 将 TLS 版本设置为 TLSv1.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");
我通过将此添加到我的连接字符串中摆脱了上述异常。
jdbc:mysql://localhost:3306/Peoples?autoReconnect=true&useSSL=false
我知道这个主题还有一些其他问题(有答案)。但是这些都对我没有帮助。
我有一个 postfix 服务器(debian 10 上的 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 应该被后缀配置禁用。会不会是这个问题?
不过。在客户端,我有一个 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 AUTH?
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 AUTH: use in every case TLS!
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 用于输出一些有趣的值。
此处 stdout
输出:
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]
和 stderr
:
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
Here I'm wondering about the line [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 没有实现高于 TLS1.0 ) 的结构与用于 SSLv2 的那些不同,因此通过它所在的 'universe' 来限定密码套件很重要。它几乎与实际使用的协议版本无关,它稍后出现在会话参数中解码:
SSL-Session:
Protocol : TLSv1.2
...
--虽然你已经从ciphersiote中知道了这一点,因为ECDHE-RSA-AES256-GCM-SHA384不能用于除TLS1.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 and Docker Container 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
.
EDIT2:它依赖于版本。低于 1.5.3 (2015-04-15) 的旧 Sun/Oracle(即雅加达之前)版本具有默认值(如果未配置 mail.smtp.ssl.protocols
)HARDCODED to TLSv1
meaning 1.0 ONLY。结果,连接将失败,但在禁用了 TLS1.0 的 Java 上的 Q 中出现异常,就像安装时 11.0.11 以及 16.0.0 和 8u291(大概是向上)一样。在未禁用 TLS1.0 的 Java 个实例上,它将 尝试 连接,但如果服务器拒绝 TLS1.0——这个 Q 中应该拒绝的——连接将仍然失败,出现不同的异常。
I have added already ECDHE-RSA-AES256-GCM-SHA384 as jdk.tls.legacyAlgorithms.
倒退了。遗留算法是您不希望使用的算法,仅作为后备接受;这个密码套件是目前可用的最好的密码套件之一,应该是首选(默认情况下,所以你不应该改变它)。另外,虽然文件中的文档和评论没有明确说明,但遗留约束无论如何只适用于服务器端——因为这是密码套件选择和 1.3 相关算法选择的地方。
将 JavaMail 从 1.4.7 升级到 1.6.2 后错误消失了!我敢肯定还有其他客户端使用 JavaMail 1.4.7 并且可以正常工作。所以那台机器上肯定还有另一个区别。但是,现在可以了!
非常感谢 dave_thompson_085。你给我指出了正确的方法:-)。我认为你的回答对其他有同样问题的人来说是一个很好的指导(我可以检查哪些属性等等)。
我在使用 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
就我而言,postfix 支持 TLSv1、TLSv1.1、TLSv1.2 和 TLSv1.3。
我准备了一些测试,使用不同的 OpenJDKs.
使用打开JDK 11.0.9 (2020-10-20)
我能够毫无例外地发送电子邮件使用打开JDK 11.0.10 (2021-01-19)
我能够毫无例外地发送电子邮件使用打开JDK 11.0.11 (2021-04-20)
我遇到了异常,
SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
- 使用打开JDK 11.0.12 (2021-07-20)
我遇到了同样的异常,
SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
据我所知,问题的原因是OpenJdk需要TLSv1.2或TLSv1.3,从版本11.0.11开始。 更新:此更改将至少适用于 OpenJDK 8u292 及以上版本、OpenJDK 11.0.11 及以上版本,以及 JRE 之后的所有 OpenJDK 16 版本和 JDK Oracle reference.
发布的加密路线图如何解决问题,
- 回到OpenJDK 11.0.10,可以找到二进制文件here. More OpenJDK versions here.
- (首选) 将 TLS 版本设置为 TLSv1.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");
我通过将此添加到我的连接字符串中摆脱了上述异常。
jdbc:mysql://localhost:3306/Peoples?autoReconnect=true&useSSL=false