-
Notifications
You must be signed in to change notification settings - Fork 219
Description
服务器接收Socket代码
`import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.springframework.stereotype.Component;
/**
-
TLS版本检测器
-
通过分析SSL握手包来准确获取客户端使用的TLS版本
*/
@component
public class TlsVersionDetector extends ChannelInboundHandlerAdapter {@OverRide
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof ByteBuf) {
ByteBuf buf = (ByteBuf) msg;
String clientIp = ctx.channel().remoteAddress().toString();// 尝试解析TLS握手包 String tlsVersion = parseTlsVersion(buf); if (tlsVersion != null) { // 根据TLS版本决定日志级别 if (isSecureTlsVersion(tlsVersion)) { LogP.info("检测到客户端 {} 使用TLS版本: {}", clientIp, tlsVersion); } else { LogP.warn("检测到客户端 {} 使用不安全的TLS版本: {} (建议升级到TLS1.2或TLS1.3)", clientIp, tlsVersion); } // 解析完成后移除自己,避免影响后续处理 ctx.pipeline().remove(this); } else { LogP.info("无法检测到客户端 {} 使用TLS版本: {}", clientIp, tlsVersion); } } // 继续传递消息 super.channelRead(ctx, msg);}
/**
- 判断是否为安全的TLS版本
*/
private boolean isSecureTlsVersion(String tlsVersion) {
return "TLSv1.2".equals(tlsVersion) || "TLSv1.3".equals(tlsVersion);
}
/**
-
解析TLS握手包中的版本信息
*/
private String parseTlsVersion(ByteBuf buf) {
if (buf.readableBytes() < 5) {
return null;
}// 保存当前读取位置
int readerIndex = buf.readerIndex();try {
// TLS记录格式:
// Byte 0: Content Type (0x16 = Handshake)
// Byte 1-2: Protocol Version
// Byte 3-4: Lengthbyte contentType = buf.readByte(); if (contentType != 0x16) { // 不是握手包 return null; } // 读取协议版本 (2 bytes) byte majorVersion = buf.readByte(); byte minorVersion = buf.readByte(); return decodeTlsVersion(majorVersion, minorVersion);} catch (Exception e) {
LogP.debug("解析TLS版本时出错: {}", e.getMessage());
return null;
} finally {
// 恢复读取位置
buf.readerIndex(readerIndex);
}
}
/** -
将版本字节转换为TLS版本字符串
*/
private String decodeTlsVersion(byte major, byte minor) {
if (major == 3) {
switch (minor) {
case 0:
return "SSLv3.0";
case 1:
return "TLSv1.0";
case 2:
return "TLSv1.1";
case 3:
return "TLSv1.2";
case 4:
return "TLSv1.3";
default:
return "TLS未知版本(3." + (minor & 0xFF) + ")";
}
} else if (major == 2) {
return "SSLv2.0";
} else {
return "未知协议版本(" + (major & 0xFF) + "." + (minor & 0xFF) + ")";
}
}
@OverRide
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// 如果出现异常,移除自己并继续
ctx.pipeline().remove(this);
super.exceptionCaught(ctx, cause);
}
}` - 判断是否为安全的TLS版本
报错日志
2025-09-13T15:56:38.681+0800 [soccer3 PVP server_NETTY_WORKER_1] ERROR n.g.l.netty.MessageDataServerHandleio.netty.handler.ssl.ReferenceCountedOpenSslEngine$OpenSslHandshakeException: error:10000416:SSL routines:OPENSSL_internal:SSLV3_ALERT_CERTIFICATE_UNKNOWN
io.netty.handler.codec.DecoderException: io.netty.handler.ssl.ReferenceCountedOpenSslEngine$OpenSslHandshakeException: error:10000416:SSL routines:OPENSSL_internal:SSLV3_ALERT_CERTIFICATE_UNKNOWN
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:499)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.access$600(AbstractChannelHandlerContext.java:61)
at io.netty.channel.AbstractChannelHandlerContext$7.run(AbstractChannelHandlerContext.java:425)
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)
at io.netty.util.concurrent.DefaultEventExecutor.run(DefaultEventExecutor.java:66)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at java.lang.Thread.run(Thread.java:748)
Caused by: io.netty.handler.ssl.ReferenceCountedOpenSslEngine$OpenSslHandshakeException: error:10000416:SSL routines:OPENSSL_internal:SSLV3_ALERT_CERTIFICATE_UNKNOWN
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.newSSLExceptionForError(ReferenceCountedOpenSslEngine.java:1377)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.shutdownWithError(ReferenceCountedOpenSslEngine.java:1089)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.sslReadErrorResult(ReferenceCountedOpenSslEngine.java:1399)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1325)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1426)
at io.netty.handler.ssl.ReferenceCountedOpenSslEngine.unwrap(ReferenceCountedOpenSslEngine.java:1469)
at io.netty.handler.ssl.SslHandler$SslEngineType$1.unwrap(SslHandler.java:223)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1353)
at io.netty.handler.ssl.SslHandler.decodeNonJdkCompatible(SslHandler.java:1257)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1297)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:468)