dpdk发送RST报文(一)—— 构建RST包

suricata中阻断报文函数“RejectSendLibnet11IPv4TCP”使用libnet11构造阻断报文。今天试一下自己手动构建RST报文,然后通过dpdk发送出去。

注:仅适用于标准eth/ip/tcp情况,vlan或gtp等特殊报文需要自己动手改。

dpdk-response-reject.h

#ifndef __DPDK_RESPONSE_REJECT_H__
#define __DPDK_RESPONSE_REJECT_H__

#include "rte_mbuf.h"

enum RejectDirection {
    REJECT_DIR_SRC = 0,
    REJECT_DIR_DST = 1,
};

struct rte_mbuf * DpdkRejectBuildIpv4TCP(struct rte_mbuf *originalMbuf, enum RejectDirection dir);

#endif

dpdk-response-reject.c

#include "dpdk-response-reject.h"
#include "rte_ip.h"
#include "rte_tcp.h"
#include "rte_ether.h"

#define TH_FIN  0x01
#define TH_SYN  0x02
#define TH_RST  0x04
#define TH_PUSH 0x08
#define TH_ACK  0x10
#define TH_URG  0x20
#define TH_RES2 0x40
#define TH_RES1 0x80
#define TH_NORESERVED (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG)

// 构造tcp头
static int BuildTCP(struct rte_ipv4_hdr *ip, struct rte_tcp_hdr *tcp, uint16_t payloadLen, enum RejectDirection dir)
{
    uint16_t tmpPort;
    uint32_t uTmpSeq;
    // 更改tcp头
    switch (dir)
    {
        case REJECT_DIR_SRC:
            tmpPort = tcp->src_port;
            tcp->src_port = tcp->dst_port;
            tcp->dst_port = tmpPort;
            uTmpSeq = ntohl(tcp->sent_seq);
            if(0 == (tcp->tcp_flags & TH_ACK))
            {
                tcp->sent_seq = 0;  // 没有ack标致,seq应该为0
                tcp->recv_ack = htonl(uTmpSeq + payloadLen + 1);
            }
            else
            {
                tcp->sent_seq = tcp->recv_ack;
                tcp->recv_ack = htonl(uTmpSeq + payloadLen + 1);
            }
            break;
        case REJECT_DIR_DST:
        default:
            break;
    }
    tcp->tcp_flags = 0x014;  // 置位rst, TH_ACK | TH_RST
    tcp->cksum = 0;
    tcp->cksum = rte_ipv4_udptcp_cksum(ip, (const void *)tcp);
    return 0;
}

// 构造ip头
static int BuildIpv4(struct rte_ipv4_hdr *ip, enum RejectDirection dir)
{
    uint16_t ident;
    uint32_t tmpAddr;
    // 更改ip头
    switch (dir)
    {
        case REJECT_DIR_SRC:
            ident = ntohs(ip->packet_id) + 27; /* 改写ident */
            ip->packet_id       = htons(ident);
            ip->fragment_offset = 0;
            tmpAddr             = ip->src_addr;
            ip->src_addr        = ip->dst_addr;
            ip->dst_addr        = tmpAddr;
            break;
        case REJECT_DIR_DST:
        default:
            break;
    }
    ip->hdr_checksum    = 0;
    ip->hdr_checksum    = rte_ipv4_cksum((const struct rte_ipv4_hdr *)ip);
    return 0;
}

// 构造以太头
static int BuildEther(struct rte_ether_hdr *ethhdr, enum RejectDirection dir)
{
    struct rte_ether_addr stTmpMac;
    // 更改以太头
    switch (dir)
    {
        case REJECT_DIR_SRC:
            memcpy( &stTmpMac, &ethhdr->s_addr, sizeof(struct rte_ether_addr));
            memcpy( &ethhdr->s_addr, &ethhdr->d_addr, sizeof(struct rte_ether_addr));
            memcpy( &ethhdr->d_addr, &stTmpMac, sizeof(struct rte_ether_addr));
            break;
        case REJECT_DIR_DST:
        default:
            break;
    }
    return 0;
}

// 构造tcp阻断报文
struct rte_mbuf * DpdkRejectBuildIpv4TCP(struct rte_mbuf *originalMbuf, enum RejectDirection dir)
{
    // 申请新mbuf用于存储Rst报文内容
    struct rte_mbuf *mbuf = rte_pktmbuf_alloc(originalMbuf->pool);
    /* 从原mbuf拷贝内容到新mbuf */
    memcpy(rte_pktmbuf_mtod(mbuf, void *), rte_pktmbuf_mtod(originalMbuf, void *), originalMbuf->data_len);
    mbuf->packet_type = originalMbuf->packet_type;
    mbuf->pkt_len     = originalMbuf->pkt_len;
    mbuf->data_len    = originalMbuf->data_len;
    mbuf->hash.rss   = originalMbuf->hash.rss;

    struct rte_ether_hdr *eth_hdr  = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); //获取以太头地址
    struct rte_ipv4_hdr  *ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);           //获取ip头地址
    struct rte_tcp_hdr   *tcp_hdr  = (struct rte_tcp_hdr *)(ipv4_hdr + 1);           //获取tcp头地址
    uint16_t usTcpPayloadLen       = rte_pktmbuf_data_len(mbuf) - sizeof(struct rte_ether_hdr) - sizeof(struct rte_ipv4_hdr) - (tcp_hdr->data_off>>2); //计算tcp payload长度,填ack number时用到
    /* 在原始包上更改,组Rst报文 */
    BuildTCP( ipv4_hdr, tcp_hdr, usTcpPayloadLen, dir );
    BuildIpv4( ipv4_hdr, dir );
    BuildEther( eth_hdr, dir );

    return mbuf;
}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高晓伟_Steven

相逢即是有缘,动力源于金钱。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值