SunJSSE中TLS最大分片长度协商(MFLN)配置与实现问题问询
我来帮你逐个梳理这些问题,结合TLS RFC规范和SunJSSE的实现细节来分析:
问题1:你的MFLN配置是否正确?
首先,系统属性设置有误:你使用的jsse.enableMFLNExtension是JSSE文档里的定义,但实际OpenJDK源码中对应的启用属性是jsse.enableMFLExtension(少了一个字母N),这会导致MFLN扩展根本没有被服务器启用,自然无法在Server Hello中回应客户端的MFLN请求。
其次,设置setMaximumPacketSize的时机不对:你是在调用srvSock.accept()之后才设置SSL参数,但此时SSLSocket可能已经启动握手流程,参数设置无法生效到当前握手。正确的做法应该是在创建SSLContext或配置SSLServerSocket时预先设置该参数,或者在accept之后、调用startHandshake()之前完成参数配置。
另外,关于maxPacketSize的计算是正确的:512字节的TLSPlaintext.fragment加上5字节的TLS记录头,总记录长度确实是517字节,这个数值符合RFC 6066的要求。
问题2:Server Hello未包含MFLN扩展,但TLS记录已被分片,该行为是否合规?
根据RFC 6066的规定,Maximum Fragment Length Negotiation是双向协商机制:
- 客户端发送MFLN扩展是请求使用指定的分片大小;
- 服务器必须在Server Hello中回应对应的MFLN扩展,才算协商成功;
- 如果服务器不回应,客户端应当使用默认的最大分片长度(16384字节),握手继续。
你的服务器在未回应MFLN扩展的情况下,自行对握手消息进行了拆分,但这并不是TLS记录层的分片(而是握手消息层面的拆分),导致最终发送的TLS记录总长度(586字节)超过了客户端请求的512字节fragment限制,这种行为不合规:
- 未协商成功的情况下,服务器无权单方面强制使用客户端请求的分片大小;
- 更关键的是,SunJSSE当前的实现错误地拆分了握手消息而非TLS记录,完全不符合RFC 6066中针对
TLSPlaintext.fragment的分片要求,这才导致客户端触发record_overflow警报。
问题3:JDK v10.0.1的SunJSSE分片实现是否存在错误?
是的,从你的描述和源码验证来看,存在两个明显的问题:
文档与代码不一致:JSSE文档中定义的启用MFLN的系统属性是
jsse.enableMFLNExtension,但OpenJDK源码中实际使用的是jsse.enableMFLExtension,这会导致开发者按照文档配置后无法启用MFLN扩展,属于文档或代码的疏漏。分片逻辑错误:
setMaximumPacketSize的预期作用应该是控制TLS记录层的最大长度(即TLSPlaintext的总长度,对应协商后的MFLN分片大小),但当前实现却将其用于拆分握手消息,而非TLS记录。这种逻辑混淆直接导致了服务器发送的记录长度超过客户端的限制,触发握手中断,完全不符合RFC 6066的规范要求。
内容的提问来源于stack exchange,提问作者tswong

