linux netfilter queue 修改数据包,用netfilter_queue 在用户态修改网络数据包的例子程序...

用netfilter_queue 在用户态修改网络数据包的例子程序

libnetfilter_queue缺乏文档,看着libnetfilter_queue自带的例子弄的。现在写不出有头有尾的文章了,就贴贴代码(还没注释),提几个我记得的几个注意点就不写了,见谅。

程序功能, 将输出端目的地为 220.181.37.55 的包,都改为目的地为 64.233.189.104,输入段反之,达到DNAT的一小半功能,完整的NAT要做状态记录的。

注意点 :

1 - 2.6.23 的内核有BUG, nfq_unbind_pf 返回值不正确,见 : http://doc.xuehai.net/http://doc.xuehai.netfilter.general/33573

2 - TCP 要做正确的checksum重新计算,否则包发不出去。UDP也是,不过这段程序里没写,如果你有兴趣就练练手吧。

3 - iptables 的 QUEUE target 内核模块不返回 XT_CONTINUE/IPT_CONTINUE 的——NF_QUEUE 是一个netfilter的机制,不是x_tables的——所以如果要在QUEUE之后继续遍历 iptables 的规则就需要点小技巧,技巧在下面的loader.sh程序里展示了:通过在mangle表里的mark来判断是第一次进入QUEUE还是第二次。而且规 则是放在最前的,保证不影响后面的mark和用户态的traffict control程序。

就这些了,不写了,贴代码。

Makefile :

nf_queue_test : nf_queue_test.c

gcc $(CFLAGS) -lnetfilter_queue $< -o $@ clean :

rm -f nf_queue_test

nf_queue_test.c :

#include #include #include #include #include #include #include #include #include #include #include #ifdef __LITTLE_ENDIAN #define IPQUAD(addr) /

((unsigned char *)&addr)[0], /

((unsigned char *)&addr)[1], /

((unsigned char *)&addr)[2], /

((unsigned char *)&addr)[3] #else #define IPQUAD(addr) /

((unsigned char *)&addr)[3], /

((unsigned char *)&addr)[2], /

((unsigned char *)&addr)[1], /

((unsigned char *)&addr)[0] #endif static u_int16_t checksum(u_int32_t init, u_int8_t *addr, size_t count){ /* Compute Internet Checksum for "count" bytes

* beginning at location "addr". */ u_int32_t sum = init; while( count > 1 ) { /* This is the inner loop */ sum += ntohs(* (u_int16_t*) addr);

addr += 2;

count -= 2;

} /* Add left-over byte, if any */ if( count > 0 )

sum += * (u_int8_t *) addr; /* Fold 32-bit sum to 16 bits */ while (sum>>16)

sum = (sum & 0xffff) + (sum >> 16); return (u_int16_t)~sum;

} static u_int16_t ip_checksum(struct iphdr* iphdrp){ return checksum(0, (u_int8_t*)iphdrp, iphdrp->ihl<<2);

} static void set_ip_checksum(struct iphdr* iphdrp){

iphdrp->check = 0;

iphdrp->check = htons(checksum(0, (u_int8_t*)iphdrp, iphdrp->ihl<<2));

} static u_int16_t tcp_checksum2(struct iphdr* iphdrp, struct tcphdr* tcphdrp){ size_t tcplen = ntohs(iphdrp->tot_len) - (iphdrp->ihl<<2); u_int32_t cksum = 0;

cksum += ntohs((iphdrp->saddr >> 16) & 0x0000ffff);

cksum += ntohs(iphdrp->saddr & 0x0000ffff);

cksum += ntohs((iphdrp->daddr >> 16) & 0x0000ffff);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值