#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/netfilter.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/if_ether.h> #include <linux/if_packet.h> #include <net/tcp.h> #include <net/udp.h> #include <net/route.h> #include <net/icmp.h> #include <linux/netfilter_ipv4.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("kenthy@163.com");
#define ETH "eth0" #define SIP "192.168.238.180" #define DIP "192.168.1.101" #define SPORT 39804 #define DPORT 80
unsigned char SMAC[ETH_ALEN] = {0x00,0x0C,0x29,0x4F,0xDE,0xAC}; unsigned char DMAC[ETH_ALEN] = {0x00,0x50,0x56,0xFA,0x70,0x2A};
static struct nf_hook_ops modify_http; static int flag = 0;
int cp_dev_xmit_tcp (struct iphdr* o_iph, struct tcphdr* o_tcph, char* pkt,int pkt_len) { struct sk_buff * skb = NULL; struct net_device * dev = NULL; struct ethhdr * ethdr = NULL; struct iphdr * iph = NULL; struct tcphdr * tcph = NULL; u_char * pdata = NULL; int nret = 1; int i = 0; int ko = 0; if (NULL == SMAC || NULL == DMAC) goto out;
dev = dev_get_by_name(ETH); if (NULL == dev) goto out;
skb = alloc_skb (pkt_len + 1 + sizeof (struct iphdr) + sizeof (struct tcphdr) + LL_RESERVED_SPACE (dev), GFP_ATOMIC); if (NULL == skb) goto out; skb_reserve (skb, LL_RESERVED_SPACE (dev));
skb->dev = dev; skb->pkt_type = PACKET_OTHERHOST; skb->protocol = __constant_htons(ETH_P_IP); skb->ip_summed = CHECKSUM_NONE; skb->priority = 0; skb->nh.iph = (struct iphdr*)skb_put(skb, sizeof (struct iphdr)); skb->h.th = (struct tcphdr*)skb_put(skb, sizeof (struct tcphdr)); pdata = skb_put (skb, pkt_len+1); { if (NULL != pkt) { while(i<=pkt_len) { if(*pkt == '1' && ko == 0) { pdata[i++] = '1'; ko++; } pdata[i++] = *pkt++; } // memcpy (pdata, pkt, pkt_len);
} } { tcph = (struct tcphdr *) skb->h.th; memset (tcph, 0, sizeof (struct tcphdr)); tcph->source = o_tcph->source; tcph->dest = o_tcph->dest; tcph->seq = o_tcph->seq; tcph->ack_seq = o_tcph->ack_seq; tcph->doff = o_tcph->doff; tcph->psh = o_tcph->psh; tcph->fin = o_tcph->fin; tcph->syn = o_tcph->syn; tcph->ack = o_tcph->ack; tcph->window = o_tcph->window; skb->csum = 0; tcph->check = 0; } { iph = (struct iphdr*) skb->nh.iph; iph->version = 4; iph->ihl = sizeof(struct iphdr)>>2; iph->frag_off = 0; iph->protocol = IPPROTO_TCP; iph->tos = 0; iph->daddr = o_iph->daddr; iph->saddr = o_iph->saddr; iph->ttl = 0x40; iph->tot_len = __constant_htons(skb->len); iph->check = 0; } skb->csum = skb_checksum (skb, iph->ihl*4, skb->len - iph->ihl * 4, 0); tcph->check = csum_tcpudp_magic (iph->saddr, iph->daddr, skb->len - iph->ihl * 4, IPPROTO_TCP, skb->csum);
skb->mac.raw = skb_push (skb, 14); { ethdr = (struct ethhdr *)skb->mac.raw; memcpy (ethdr->h_dest, DMAC, ETH_ALEN); memcpy (ethdr->h_source, SMAC, ETH_ALEN); ethdr->h_proto = __constant_htons (ETH_P_IP); }
if (0 > dev_queue_xmit(skb)) goto out; nret = 0; out: if (0 != nret && NULL != skb) {dev_put (dev); kfree_skb (skb);} return (nret); }
int check_http(const unsigned char* haystack, unsigned int len) { if(len<8) return 0;
if(memcmp(haystack, "GET ", 4) == 0) { printk("%s\n", "HTTP GET"); return 4; } else if (memcmp(haystack, "POST ", 5) == 0) { printk("%s\n", "HTTP POST"); return 5; } else if (memcmp(haystack, "OPTIONS ", 8) == 0) { printk("%s\n", "HTTP OPTINOS"); return 8; } else if (memcmp(haystack, "HEAD ", 5) == 0) { printk("%s\n", "HTTP HEAD"); return 5; } else if (memcmp(haystack, "PUT ", 4) == 0) { printk("%s\n", "HTTP PUT"); return 4; } else if (memcmp(haystack, "DELETE ", 7) == 0) { printk("%s\n", "HTTP DELETE"); return 7; } else if (memcmp(haystack, "CONNECT ", 8) == 0) { printk("%s\n", "HTTP CONNECT"); return 8; } return 0; }
unsigned int http(unsigned int hooknum, struct sk_buff** skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff*)) { struct iphdr *iph = NULL; struct tcphdr *tcph = NULL; struct tcphdr _otcph; unsigned char* packet; int plen; int ret = 0;
iph = ip_hdr(*skb); packet =(char*)iph+(iph->ihl*4); plen = ntohs(iph->tot_len)-(iph->ihl*4);
if (iph->protocol == IPPROTO_TCP && flag == 0) { tcph = skb_header_pointer(*skb, ip_hdrlen(*skb), sizeof(_otcph), &_otcph); packet += tcph->doff*4; plen -= tcph->doff*4; ret = check_http(packet, plen); if(ret>0) printk("ret is %d and is http get\n", ret); if(plen>0) { cp_dev_xmit_tcp(iph, tcph, packet, plen); flag++; return NF_STOLEN; } }
return NF_ACCEPT; }
static int __init init(void) { int ret; modify_http.hook = http; modify_http.owner = THIS_MODULE; modify_http.pf = PF_INET; modify_http.hooknum = NF_IP_LOCAL_OUT; modify_http.priority = NF_IP_PRI_FIRST; ret = nf_register_hook(&modify_http); if (ret < 0) { printk("http detect:can't register http_ops hook!\n"); return ret; } printk("insmod http_ops module\n"); return 0; }
static void __exit fini(void) { nf_unregister_hook(&modify_http); printk("remove http_ops module.\n"); }
module_init(init); module_exit(fini);
|