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

本文介绍了一种防范Socket攻击的方法,通过限制最大字节流大小并利用协议头定位有效数据包,确保服务器安全。针对恶意的数据包攻击,文章详细阐述了如何在接收到的数据中正确解析协议包,避免内存溢出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值