linux网络数据包修改,程序员罗杰-用netfilter_queue 在用户态修改网络数据包的例子程序...

/*

* =====================================================================================

*

* Filename: nf_queue_test.c

*

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

*

* Version: 1.0

* Created: 09/02/2020 09:49:48 AM

* Revision: none

* Compiler: gcc

*

* Author: luojie (luojie), luojie@mayikf.com

* Company: WEIFU

*

* =====================================================================================

*/

#include 

#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

struct tcp_pseudo /*the tcp pseudo header*/

{

__u32 src_addr;

__u32 dst_addr;

__u8 zero;

__u8 proto;

__u16 length;

} pseudohead;

long checksum(unsigned short *addr, unsigned int count) {

/* Compute Internet Checksum for "count" bytes

* beginning at location "addr".

*/

register long sum = 0;

while( count > 1 ) {

/* This is the inner loop */

sum += * addr++;

count -= 2;

}

/* Add left-over byte, if any */

if( count > 0 )

sum += * (unsigned char *) addr;

/* Fold 32-bit sum to 16 bits */

while (sum>>16)

sum = (sum & 0xffff) + (sum >> 16);

return ~sum;

}

/*************************tcp checksum**********************/

long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {

__u16 total_len = ntohs(myip->tot_len);

int tcpopt_len = mytcp->doff*4 - 20;

int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);

pseudohead.src_addr=myip->saddr;

pseudohead.dst_addr=myip->daddr;

pseudohead.zero=0;

pseudohead.proto=IPPROTO_TCP;

pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);

int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct tcphdr) + tcpopt_len +tcpdatalen;

//unsigned short * tcp = new unsigned short[totaltcp_len];

unsigned short * tcp = malloc(totaltcp_len);

memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));

memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned char*)mytcp,sizeof(struct tcphdr));

memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(struct tcphdr),(unsigned char *)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);

memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(structtcphdr)+tcpopt_len, (unsigned char *)mytcp+(mytcp->doff*4), tcpdatalen);

/* printf("pseud length: %d\n",pseudohead.length);

printf("tcp hdr length: %d\n",mytcp->doff*4);

printf("tcp hdr struct length: %d\n",sizeof(struct tcphdr));

printf("tcp opt length: %d\n",tcpopt_len);

printf("tcp total+psuedo length: %d\n",totaltcp_len);

fflush(stdout);

printf("tcp data len: %d, data start %u\n", tcpdatalen,mytcp + (mytcp->doff*4));

*/

return checksum(tcp,totaltcp_len);

}

static u_int16_t tcp_checksum(struct iphdr* iphdrp){

struct tcphdr *tcphdrp =

(struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));

return get_tcp_checksum(iphdrp, tcphdrp);

}

static void set_tcp_checksum(struct iphdr* iphdrp){

struct tcphdr *tcphdrp =

(struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));

tcphdrp->check = 0;

tcphdrp->check = get_tcp_checksum(iphdrp, tcphdrp);

}

/****************************tcp checksum end****************************/

/********************************Ip checksum*****************************/

static u_int16_t ip_checksum(struct iphdr* iphdrp){

return checksum((unsigned short*)iphdrp, iphdrp->ihl<<2);

}

static void set_ip_checksum(struct iphdr* iphdrp){

iphdrp->check = 0;

iphdrp->check = checksum((unsigned short*)iphdrp, iphdrp->ihl<<2);

}

/****************************Ip checksum end******************************/

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_checksum(iphdrp));

}

#define TO "220.181.37.55"

#define DNAT_TO "202.118.236.130"

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_checksum(iphdrp);

printf(" ipsum+ %hu tcpsum+ %hu",

ip_checksum(iphdrp), tcp_checksum(iphdrp));

}

}

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

iphdrp->saddr = inet_addr(TO);

printf(" !hacked!");

set_ip_checksum(iphdrp);

if(iphdrp->protocol == IPPROTO_TCP){

set_tcp_checksum(iphdrp);

printf(" ipsum+ %hu tcpsum+ %hu",

ip_checksum(iphdrp), tcp_checksum(iphdrp));

}

}

printf("\n");

return nfq_set_verdict_mark(qh, id, NF_REPEAT, 1,

(u_int32_t)pdata_len, pdata);

}

int main(int argc, char **argv)

{

struct nfq_handle *h;

struct nfq_q_handle *qh;

struct nfnl_handle *nh;

int fd;

int rv;

char buf[4096];

h = nfq_open();

if (!h) {

exit(1);

}

nfq_unbind_pf(h, AF_INET);

/*2.6.24 的内核有BUG, nfq_unbind_pf 返回值不正确,

见:http://article.gmane.org/gmane.c ... ilter.general/33573*/

/*

if (nfq_unbind_pf(h, AF_INET) 

exit(1);

}

*/

if (nfq_bind_pf(h, AF_INET) 

exit(1);

}

int qid = 0;

if(argc == 2){

qid = atoi(argv[1]);

}

printf("binding this socket to queue %d\n", qid);

qh = nfq_create_queue(h, qid, &cb, NULL);

if (!qh) {

exit(1);

}

if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) 

exit(1);

}

nh = nfq_nfnlh(h);

fd = nfnl_fd(nh);

while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {

nfq_handle_packet(h, buf, rv);

}

/* never reached */

nfq_destroy_queue(qh);

nfq_close(h);

exit(0);

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值