/*************ltw,tony ipt_REDIRECT.c*/ /** using:insmod ipt_hook.ko remark=2 dst=192.168.0.116 default remark=1,dst=127.0.0.1 */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/netfilter.h> #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/ctype.h> #include <linux/inet.h> #include <net/checksum.h> #include <net/tcp.h> #include <net/udp.h>
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_conntrack_helper.h> #include <linux/netfilter/nf_conntrack_ftp.h> #include <linux/types.h> #include <linux/skbuff.h> //skb_network_header(skb) CHECKSUM_UNNECESSARY
#include <linux/in.h> //IPPROTO_xxx
#include <linux/timer.h> #include <net/xfrm.h> #include <linux/netfilter.h> #include <linux/netdevice.h> //netif_receive_skb netif_rx
#include <linux/if.h> #include <linux/inetdevice.h> #include <net/protocol.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter/x_tables.h> #include <net/netfilter/nf_nat_rule.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("ltw"); static int remark=1; char *dst="127.0.0.1"; module_param(remark,uint,0644); module_param(dst,charp,0644); MODULE_PARM_DESC(remark,"Copy the packet with the mark is remark"); static struct nf_hook_ops myhook; unsigned int myhook_func(unsigned int hooknum,struct sk_buff *skb,const struct net_device *in,const struct net_device *out,int(*okfn)(struct sk_buff*)) { //printk(KERN_ALERT "get hook\n");
struct iphdr *nowiph; nowiph=(struct iphdr*)skb_network_header(skb); __u32 mark=skb->mark; __be32 mydst; mydst = in_aton(dst); //__be32 testip= in_aton("203.208.37.99");
//if(nowiph->saddr==testip&&nowiph->daddr==mydst) printk("OK\n");
if(nowiph->daddr==mydst) { printk("%8x-%8x\n",ntohl(nowiph->saddr),ntohl(nowiph->daddr)); //if(mydst==in_aton("127.0.0.1")) skb->pkt_type=5;
return NF_ACCEPT; } //printk(KERN_ALERT "mark=%d\n",mark);
if(mark==remark) { //printk(KERN_ALERT "OK\n");
struct sk_buff *myskb=skb_copy(skb,GFP_ATOMIC); struct iphdr *myiph; //myskb->pkt_type=PACKET_OTHERHOST;
myiph=(struct iphdr*)skb_network_header(myskb); if(myiph==NULL) { kfree_skb(myskb); return NF_ACCEPT; } myiph->daddr=mydst; if(myiph->protocol==IPPROTO_TCP) { __wsum csum=0; struct tcphdr *mytcphdr; unsigned int tcphoff; mytcphdr=(struct tcphdr*)(myskb->data+myiph->ihl*4); if(mytcphdr==NULL) { kfree_skb(myskb); return NF_ACCEPT; } nf_reset(myskb); tcphoff=myiph->ihl*4; ip_send_check(myiph); mytcphdr->check=0; csum=skb_checksum(myskb,tcphoff,myskb->len-tcphoff,0); myskb->csum=csum; myskb->ip_summed=CHECKSUM_NONE; /*mytcphdr->check=csum_tcpudp_magic(myiph->saddr,myiph->daddr,myskb->len,IPPROTO_TCP,csum_partial((char *)mytcphdr,myskb->len-tcphoff,0)); mytcphdr->check+=0x1400;*/ mytcphdr->check=0; mytcphdr->check=tcp_v4_check(myskb->len-tcphoff,myiph->saddr,myiph->daddr,csum_partial(mytcphdr,myskb->len-tcphoff,0)); //printk("%u--%u\n",ntohs(myiph->saddr),ntohs(myiph->daddr));
netif_rx(myskb); } else if(myiph->protocol==IPPROTO_UDP) { int csum=0; struct udphdr *myudphdr; unsigned int udphoff; myudphdr=(struct udphdr*)(myskb->data+myiph->ihl*4); if(myudphdr==NULL) { kfree_skb(myskb); return NF_ACCEPT; } udphoff=myiph->ihl*4; myskb->csum=0; ip_send_check(myiph); csum=skb_checksum(myskb,udphoff,myskb->len-udphoff,0); myskb->csum=csum; myskb->ip_summed=CHECKSUM_NONE; myudphdr->check=0; myudphdr->check=csum_tcpudp_magic(myiph->saddr,myiph->daddr,myskb->len-udphoff,IPPROTO_UDP,csum_partial(myudphdr,myskb->len-udphoff,0)); nf_reset(myskb); netif_rx(myskb); } } return NF_ACCEPT; } static int __init myhook_init(void) { printk(KERN_ALERT "ipt_hook init\n"); memset(&myhook,0,sizeof(struct nf_hook_ops)); myhook.hook=myhook_func; myhook.owner=THIS_MODULE; myhook.pf=PF_INET; myhook.hooknum=NF_IP_PRE_ROUTING; myhook.priority=INT_MAX; return nf_register_hook(&myhook); } static void __exit myhook_exit(void) { nf_unregister_hook(&myhook); } module_init(myhook_init); module_exit(myhook_exit);
|