您的位置:首页 > 其它

Netty 快速入门系列 - Chapter 8 数据包协议【第二十二讲】Socket攻击及防护

2018-03-27 08:18 941 查看
1. Socket攻击
把长度定义的很大,这种数据包,通常被称为socket攻击,字节流式攻击,导致服务器OOM。
由于:FrameDecoder里面的cumulation其实就是一个缓存的buffer对象 ,导致OOM



2. 防止Socket攻击
通过设置字节流Max大小,防止Socket攻击。
分析 Decoder  假设 Bytes_Max = 2048 
a. 字节流大于Max,跳过所有字节流 // 防止Socket攻击
if (buffer.readableBytes() > 2048) {
buffer.skipBytes(buffer.readableBytes());
return null;
}
b. 当跳过所有字节流后,必须协议头 Protocol_Header 用于定位到下一个正确的协议开始的地方, 所有标准协议必须包括 协议header。 如果仅仅使用 定义一个稳定的结构 length + 数据,一旦Socket攻击,就无法正确解析后续协议包。 按照一个int,检测包头,通过跳过一个byte一个byte,不是int
while (true) {
buffer.markReaderIndex();
// 直到找到包头 如果Socket 攻击,4个字节,可能跳过包头
if (buffer.readInt() == SystemConstants.Protocol_Header_Flag) {
break;
}
buffer.resetReaderIndex();
buffer.readByte(); // 跳过一个Byte,开始比较下一组int是否等于Flag
//可读长度小于基本长度
if (buffer.readableBytes() < Base_Protocol_Length) {
return null;
}
}
c. 剩余字节流小于最小长度,放回null,继续等待 while (true) {
buffer.markReaderIndex();
// 直到找到包头 如果Socket 攻击,4个字节,可能跳过包头
if (buffer.readInt() == SystemConstants.Protocol_Header_Flag) {
break;
}
buffer.resetReaderIndex();
buffer.readByte(); // 跳过一个Byte,开始比较下一组int是否等于Flag
//可读长度小于基本长度
if (buffer.readableBytes() < Base_Protocol_Length) {
return null;
}

}
RequestDecoder public class RequestDecoder extends FrameDecoder {
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
// 可读长度必须大于基本长度
if (buffer.readableBytes() < Base_Protocol_Length) {
// 数据包不完成,继续等待数据包
return null;
}
// 防止Socket攻击
if (buffer.readableBytes() > 2048) {
buffer.skipBytes(buffer.readableBytes());
return null;
}
// 记录包头开始位置
while (true) {
buffer.markReaderIndex();
// 直到找到包头 如果Socket 攻击,4个字节,可能跳过包头
if (buffer.readInt() == SystemConstants.Protocol_Header_Flag) {
break;
}
buffer.resetReaderIndex();
buffer.readByte(); // 跳过一个Byte,开始比较下一组int是否等于Flag
//可读长度小于基本长度
if (buffer.readableBytes() < Base_Protocol_Length) {
return null;
}
}
int beginReader = buffer.readerIndex();
long requsetId = buffer.readLong();
short module = buffer.readShort();
short cmd = buffer.readShort();
int length = buffer.readInt();
// 判断请求数据是否到齐
if (buffer.readableBytes() < length) {
// reset 已经读取Base_Protocol_Length12字节
buffer.readerIndex(beginReader);
return null;
}
// 读取数据
byte[] data = new byte[length];
buffer.readBytes(data);
Request req = new Request();
req.setModule(module);
req.setCmd(cmd);
req.setData(data);
req.setRequestId(requsetId);
return req;
}
/**
* 数据包最小长度
*/
private static int Base_Protocol_Length = 4 + 8 + 2 + 2 + 4;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Netty
相关文章推荐