Netty学习10-Netty的socket攻击及预防

在前面的文章我们说到过,可以采用长度+数据的格式定义包结构;但是如果长度定义的特别大,那么缓冲区必然会存储不下,而引起宕机或其他问题。这便是一种socket攻击。

除此之外,如果定义的长度和实际长度不匹配,比如实际长度为5,定义的长度为6,那么读取的时候可能会把下一个数据包的一部分读取到,造成以后的数据不能正常解析;这也是一种socket攻击。

可以通过以下几个方面处理socket攻击:

1.定义字节的最大长度,如果字节流大于Max,跳过所有字节流

  // 防止Socket攻击
    if (buffer.readableBytes() > 2048) {
      buffer.skipBytes(buffer.readableBytes());
      return null;
    }
2.但是当跳过所有字节流后,可用包头定位到下一个正确的数据包开始的地方,所以标准包结构还应该有个起始的包头标志。跳过最大长度后,循环读取数据包一个字节,判断是否是包头;如果不是则跳过继续读,直到读到包头,跳出循环,然后才可以继续解析;但是这个过程可能会在读的过程中长度小于最小包结构长度了,这时候要直接返回null,等待下次数据到来后再解析;

具体代码如下:

package com.cn.codc;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import com.cn.constant.ConstantValue;
import com.cn.model.Response;

/**
 * response解码器
 * 
 * 数据包格式
 * +——----——+——-----——+——----——+——----——+——-----——+——-----——+
 * | 包头          | 模块号        | 命令号       |  状态码    |  长度          |   数据       |
 * +——----——+——-----——+——----——+——----——+——-----——+——-----——+
 * 
* 包头4字节 * 模块号2字节short * 命令号2字节short * 长度4字节(描述数据部分字节长度) * - * */ public class ResponseDecoder extends FrameDecoder{ /** * 数据包基本长度 */ public static int BASE_LENTH = 4 + 2 + 2 + 4; @Override protected Object decode(ChannelHandlerContext arg0, Channel arg1, ChannelBuffer buffer) throws Exception { //可读长度必须大于基本长度 if(buffer.readableBytes() >= BASE_LENTH){ //防止字节流攻击 if(buffer.readableBytes()>2048){ //清除缓存中的数据 buffer.skipBytes(buffer.readableBytes()); } //记录包头开始的index int beginReader ; while(true){ beginReader = buffer.readerIndex(); //标记当前索引 buffer.markReaderIndex(); //判断包头是否是当前的包头 //因为清除了数据之后,因为可能会出现分包截断的现象,下次进来的时候, //可能不是开头,所以不能知道哪个是长度,哪个是数据,所以需要包头, //只有当时读到包头的时候才继续往下走。 if(buffer.readInt() == ConstantValue.FLAG){ break; } //未读到包头超过了一个字节 buffer.resetReaderIndex(); //因为可能读一个int之后,略过了包头,因为可能包头在第一个字节处 //所以这里选择继续往下读一个字节 buffer.readByte(); //可能出现极端的情况,长度又变得不满足 if(buffer.readableBytes()


 

你可能感兴趣的:(IO)