用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
分享:
喜欢
0
赠金笔
加载中,请稍候......
评论加载中,请稍候...
发评论
登录名: 密码: 找回密码 注册记住登录状态
昵 称:
评论并转载此博文
发评论
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。