我目前正在尝试测试我自己的基于Grizzly框架的SMTP服务器的实现,现在在JavaMail的帮助下检查SMTPS支持时遇到握手问题。
我发现similar problem有握手,但希望(或不适合我)我不使用客户端模式Grizlly SSLEngineConfigurator,所以我猜问题的根源应该是不同的。
我的Grizzly SSL配置初始化代码(在集成测试中)如下所示:
try (InputStream keystoreStream = TransportEncryptionIT.class.getResourceAsStream("server_keystore.jks")) {
SSLContextConfigurator sslCon = new SSLContextConfigurator();
sslCon.setSecurityProtocol("TLSv1.2");
sslCon.setKeyStoreType("JKS");
sslCon.setKeyStoreBytes(IOUtils.toByteArray(keystoreStream));
sslCon.setKeyStorePass("");
sslConf = new SSLEngineConfigurator(sslCon, false, false, false);
}
我还在TransportFilter(这是链中的第一个过滤器)后立即将SSLFilter安装到FilterChain(带有服务器SSL配置)。
filterChainBuilder.add(new SSLFilter(sslConf , null));
并按以下方式为SMTPS配置javamail:
Properties properties = new Properties();
properties.setProperty("mail.transport.protocol", "smtps");
properties.setProperty("mail.smtps.host", ${host});
properties.setProperty("mail.smtps.port", ${port});
//need this since i'm using self signed certificate which is not added to truststore
properties.setProperty("mail.smtps.ssl.trust", "*");
握手结果(SSL调试服务器):
[Raw read]: length = 163
0000: 01 00 00 9F 03 01 54 7C D5 30 98 30 CA 59 39 D7 ......T..0.0.Y9.
0010: B0 4A B6 FC 8F 8D E9 BD 4B 88 D6 BF EE E8 F9 FF .J......K.......
0020: 8A EB 28 CF 98 AB 00 00 38 C0 0A C0 14 00 35 C0 ..(.....8.....5.
0030: 05 C0 0F 00 39 00 38 C0 09 C0 13 00 2F C0 04 C0 ....9.8...../...
0040: 0E 00 33 00 32 C0 07 C0 11 00 05 C0 02 C0 0C C0 ..3.2...........
0050: 08 C0 12 00 0A C0 03 C0 0D 00 16 00 13 00 04 00 ................
0060: FF 01 00 00 3E 00 0A 00 34 00 32 00 17 00 01 00 ....>...4.2.....
0070: 03 00 13 00 15 00 06 00 07 00 09 00 0A 00 18 00 ................
0080: 0B 00 0C 00 19 00 0D 00 0E 00 0F 00 10 00 11 00 ................
0090: 02 00 12 00 04 00 05 00 14 00 08 00 16 00 0B 00 ................
00A0: 02 01 00 ...
Grizzly-worker(1), READ: TLSv1 Handshake, length = 163
Grizzly-worker(2), fatal error: 80: problem unwrapping net record
javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 1
Grizzly-worker(2), SEND TLSv1.2 ALERT: fatal, description = internal_error
Grizzly-worker(2), WRITE: TLSv1.2 Alert, length = 2
握手结果(SSL调试客户端):
[Raw read]: length = 249
0000: 01 00 00 F5 03 03 54 7C D5 30 6E 1C E7 B3 36 DE ......T..0n...6.
0010: A6 26 73 78 2B 66 D1 D1 E8 C4 94 CA 63 34 22 BF .&sx+f......c4".
0020: 60 9D 13 03 59 1F 00 00 70 C0 24 C0 28 00 3D C0 `...Y...p.$.(.=.
0030: 26 C0 2A 00 6B 00 6A C0 0A C0 14 00 35 C0 05 C0 &.*.k.j.....5...
0040: 0F 00 39 00 38 C0 23 C0 27 00 3C C0 25 C0 29 00 ..9.8.#.'.<.%.).
0050: 67 00 40 C0 09 C0 13 00 2F C0 04 C0 0E 00 33 00 g.@...../.....3.
0060: 32 C0 07 C0 11 00 05 C0 02 C0 0C C0 2C C0 2B C0 2...........,.+.
0070: 30 00 9D C0 2E C0 32 00 9F 00 A3 C0 2F 00 9C C0 0.....2...../...
0080: 2D C0 31 00 9E 00 A2 C0 08 C0 12 00 0A C0 03 C0 -.1.............
0090: 0D 00 16 00 13 00 04 00 FF 01 00 00 5C 00 0A 00 ............\...
00A0: 34 00 32 00 17 00 01 00 03 00 13 00 15 00 06 00 4.2.............
00B0: 07 00 09 00 0A 00 18 00 0B 00 0C 00 19 00 0D 00 ................
00C0: 0E 00 0F 00 10 00 11 00 02 00 12 00 04 00 05 00 ................
00D0: 14 00 08 00 16 00 0B 00 02 01 00 00 0D 00 1A 00 ................
00E0: 18 06 03 06 01 05 03 05 01 04 03 04 01 03 03 03 ................
00F0: 01 02 03 02 01 02 02 01 01 .........
main, READ: TLSv1.2 Handshake, length = 249
main, handling exception: javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 1
main, SEND TLSv1.2 ALERT: fatal, description = unexpected_message
main, WRITE: TLSv1.2 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 03 00 02 02 0A .......
main, called closeSocket()
对我来说奇怪的是,SMTP + StartTLS与我的服务器完美配合,握手成功完成,我通过ssl debug检查了这一点。
我不确定的唯一的事情是我使用自己创建的证书,而不是添加到信任库。可能是java邮件选项“mail。$ {protocol} .ssl.trust”适用于SMTP + StartTLS但不知何故不适用于SMTPS?
我还尝试使用MailSSLSocketFactory强制javamail信任服务器证书,但它似乎甚至没有被调用(使用debuger检查)。
JavaMail版本1.4.7
Grizzly 2.3.17
更新
最后我发现源代码有所不同,似乎没有关于javamail,但我使用Grizzly框架和安装SSLFilter到FilterChain。 当我将服务器作为SMTPS服务器启动时,过滤器按以下方式安装:
filterChainBuilder.add(new TransportFilter());
if (configuration.getSslConfig() != null) {
sslFilter = new SSLFilter(configuration.getSslConfig(), null);
if (configuration.isSmtpsEnabled()) {
filterChainBuilder.add(sslFilter);
}
}
smtpLineCodecFilter = new SmtpLineCodecFilter();
filterChainBuilder.add(smtpLineCodecFilter);
但是对于StartTLS(因为客户端可能会要求提高传输加密),它以另一种方式完成:
FilterChain securedFilterChain = new DefaultFilterChain(defaultChain);
int transportFilterindex = defaultChain.indexOfType(TransportFilter.class);
// Add connection security layer to the chain
securedFilterChain.add(transportFilterindex + 1, sslFilter);
这种差异会导致安装不同的过滤器,因此过滤器链看起来像这样:
在第一种情况下 - SSLBaseFilter.SSLTransportFilterWrapper - &gt; SSLFilter
在第二种情况下 - TransportFilter - &gt; SSLFilter
现在我不确定哪种方法是正确的,但至少第二种情况对我有用 我非常感谢Grizzly Guru的回答:)
答案 0 :(得分:0)
您正在为&#34; smtps&#34;配置所有内容。协议,但也许您实际上使用 smtps协议?你是如何连接服务器的?尝试使用getTransport(&#34; smtps&#34;),如this JavaMail FAQ entry中的代码示例所示。另外,请确保您not using Session.getDefaultInstance。如果这不起作用,请发布JavaMail debug output。
答案 1 :(得分:0)
最后我找到了握手失败的原因。
所有关于在handleAccept方法下打印SMTP服务器横幅 对于普通的SMTP连接和StartTLS情况是可以的,因为在客户端建立连接之后不会发生任何握手。但对于SMTPS,它不会以这种方式工作,因为客户端期望服务器helo而不是欢迎横幅 真是个愚蠢的错误:/