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

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

(2012-07-21 03:44:56)

标签:

网络

数据包

程序

用户

杂谈

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

http://blog.chinaunix.net/u/8057/showart_431074.html

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

程序功能, 将输出端目的地为 220.181.37.55 的包,都改为目的地为

64.233.189.104,输入段反之,达到DNAT的一小半功能,完整的NAT要做状态记录的。

注意点 :

1 - 2.6.23 的内核有BUG, nfq_unbind_pf 返回值不正确,见 :

http://article.gmane.org/gmane.comp.security.firewalls.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), \

((unsigned char *)&addr), \

((unsigned char *)&addr), \

((unsigned char *)&addr)

#else

#define IPQUAD(addr) \

((unsigned char *)&addr), \

((unsigned char *)&addr), \

((unsigned char *)&addr), \

((unsigned char *)&addr)

#endif

static u_int16_t checksum(u_int32_t init, u_int8_t *addr, size_t

count){

u_int32_t sum = init;

while( count > 1 ) {

sum += ntohs(* (u_int16_t*) addr);

addr += 2;

count -= 2;

}

if( count > 0 )

sum += * (u_int8_t *) addr;

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

cksum += ntohs(iphdrp->daddr &

0x0000ffff);

cksum += iphdrp->protocol &

0x00ff;

cksum += tcplen;

return checksum(cksum, (u_int8_t*)tcphdrp, tcplen);

}

static u_int16_t tcp_checksum1(struct iphdr* iphdrp){

struct tcphdr *tcphdrp =

(struct tcphdr*)((u_int8_t*)iphdrp +

(iphdrp->ihl<<2));

return tcp_checksum2(iphdrp, tcphdrp);

}

static void set_tcp_checksum2(struct iphdr* iphdrp, struct tcphdr*

tcphdrp){

tcphdrp->check = 0;

tcphdrp->check = htons(tcp_checksum2(iphdrp,

tcphdrp));

}

static void set_tcp_checksum1(struct iphdr* iphdrp){

struct tcphdr *tcphdrp =

(struct tcphdr*)((u_int8_t*)iphdrp +

(iphdrp->ihl<<2));

set_tcp_checksum2(iphdrp, tcphdrp);

}

static int cb(struct nfq_q_handle *qh, struct nfgenmsg

*nfmsg,

struct nfq_data *nfa, void *data){

(void)nfmsg;

(void)data;

u_int32_t id = 0;

struct nfqnl_msg_packet_hdr *ph;

unsigned char *pdata = NULL;

int pdata_len;

ph = nfq_get_msg_packet_hdr(nfa);

if (ph){

id = ntohl(ph->packet_id);

}

pdata_len = nfq_get_payload(nfa,

(char**)&pdata);

if(pdata_len == -1){

pdata_len = 0;

}

struct iphdr *iphdrp = (struct iphdr *)pdata;

printf("len %d iphdr %d %u.%u.%u.%u

->",

pdata_len,

iphdrp->ihl<<2,

IPQUAD(iphdrp->saddr));

printf(" %u.%u.%u.%u %s",

IPQUAD(iphdrp->daddr),

getprotobynumber(iphdrp->protocol)->p_name);

printf(" ipsum %hu",

ip_checksum(iphdrp));

if(iphdrp->protocol == IPPROTO_TCP){

printf(" tcpsum %hu",

tcp_checksum1(iphdrp));

}

#define TO "220.181.37.55"

#define DNAT_TO

"64.233.189.104"

if(iphdrp->daddr == inet_addr(TO)){

printf(" !hacked!");

iphdrp->daddr = inet_addr(DNAT_TO);

set_ip_checksum(iphdrp);

if(iphdrp->protocol == IPPROTO_TCP){

set_tcp_checksum1(iphdrp);

printf(" ipsum+ %hu tcpsum+

%hu",

ip_checksum(iphdrp), tcp_checksum1(iphdrp));

}

}

if(iphdrp->saddr == inet_addr(DNAT_TO)){

iphdrp->saddr = inet_addr(TO);

printf(" !hacked!&quo

分享:

a4c26d1e5885305701be709a3d33442f.png喜欢

0

a4c26d1e5885305701be709a3d33442f.png赠金笔

加载中,请稍候......

评论加载中,请稍候...

发评论

登录名: 密码: 找回密码 注册记住登录状态

昵   称:

评论并转载此博文

a4c26d1e5885305701be709a3d33442f.png

发评论

以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值