/hook_ipv4

基于netfilter修改HTTP数据包(插入、修改、删除)base on netfilter, add some js into http packet

Primary LanguageC

基于netfilter修改HTTP数据包(插入、修改、删除)

测试内核:3.13.0-32-generic

hook点

{ 
		.hook 			= hook_func,
		.pf 		    = NFPROTO_IPV4,
		.hooknum 		= NF_INET_FORWARD, 
		.priority 		= NF_IP_PRI_MANGLE,
		.owner			= THIS_MODULE
},

内核NAT修正数据接口:

static inline int nf_nat_mangle_tcp_packet(
              struct sk_buff *skb,
              struct nf_conn *ct,
              enum ip_conntrack_info ctinfo,
              // IP头偏移量
              unsigned int protoff,
              // 插入点偏移量(距离payload首部)
              unsigned int match_offset,
              // 插入点覆盖长度
              unsigned int match_len,
              // 待插入数据
              const char *rep_buffer,
              // 带插入数据长度
              unsigned int rep_len)

注意事项:

  • 在调用nf_nat_mangle_tcp_packet前需要调用nfct_seqadj_ext_add将当前连接跟踪信息加入seq修正。

  • 修改数据包长度后3.13内核可自动修改seq和ack

    原理:

    nf_nat_mangle_tcp_packet时会做以下处理set_bit(IPS_SEQ_ADJUST_BIT, &ct->status)

    后续内核跟踪钩子会修正test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)的tcp数据包的seq和ack)

  • 3.2以及2.68以下内核只是在ct->status中高几位做了标记(IPS_SEQ_ADJUST_BIT),还需要后续手动hook修改

    unsigned int fix_seq(unsigned int hooknum, struct sk_buff *skb,
       const struct net_device *in, const struct net_device *out, int(*okfn)(struct sk_buff *))
    {
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) 
        && (ctinfo != IP_CT_RELATED + IP_CT_IS_REPLY)  ) {
            nf_nat_seq_adjust(skb, ct, ctinfo);
        }
        return NF_ACCEPT;
    }
    // 3.2以及2.68以下内核适用
      {
      	.hook		   	= fix_seq,
      	.pf			 	= PF_INET,
      	.hooknum		= NF_INET_PRE_ROUTING,
      	.priority	   	= NF_IP_PRI_CONNTRACK_CONFIRM,
      	.owner			= THIS_MODULE
      },
      {
      	.hook		   	= fix_seq,
      	.pf			 	= PF_INET,
      	.hooknum		= NF_INET_POST_ROUTING,
      	.priority	  	= NF_IP_PRI_CONNTRACK_CONFIRM,
      	.owner			= THIS_MODULE
      },
  • 处理gzip压缩:发送请求时删除请求头中Accept-Encoding字段,防止收到gzip压缩包

  • 处理chunked分段传输:发送请求时将HTTP/1.1修改为HTTP/1.0防止收到chunked数据包(Transfer-Encoding: chunked是HTTP 1.1中特有的)

  • 对数据包进行修改需要重新计算checksum

  • 处理完整数据包需要合并ip分片

    // IP数据包frag合并
    if (0 != skb_linearize(skb)) {
      return NF_ACCEPT;
    }