Skip to content

Instantly share code, notes, and snippets.

@kevinz
Created November 21, 2014 10:12
Show Gist options
  • Save kevinz/77325087b1a61da12240 to your computer and use it in GitHub Desktop.
Save kevinz/77325087b1a61da12240 to your computer and use it in GitHub Desktop.
//’Hello World’ v2 netfilter hooks example
//For any packet, get the ip header and check the protocol field
//if the protocol number equal to UDP (17), log in var/log/messages
//default action of module to let all packets through
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <net/tcp.h>
static struct nf_hook_ops nfho; //net filter hook option struct
static struct nf_hook_ops nfho_; //net filter hook option struct
static unsigned int shift_bits = 4;
static unsigned int ts_id= 1;
unsigned int hook_func(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 = ip_hdr(skb);
struct tcphdr *hdr;
unsigned int hdroff = iph->ihl*4;
int datalen = skb->len - hdroff;
int hdrsize = 8; /* TCP connection tracking guarantees this much */
const unsigned char *ptr;
unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
int length;
int recalc = 0;
//printk(KERN_DEBUG "+++index=%d %pI4 -> %pI4 :\n", out->ifindex,&iph->saddr, &iph->daddr);
if (iph->protocol != IPPROTO_TCP) {
return NF_ACCEPT;
}
if(out->ifindex!=4)
return NF_ACCEPT;
hdr = (struct tcphdr *)(skb->data + hdroff);
if (skb->len >= hdroff + sizeof(struct tcphdr))
hdrsize = sizeof(struct tcphdr);
if (!skb_make_writable(skb, hdroff + hdrsize))
return NF_ACCEPT;
length = (hdr->doff*4) - sizeof(struct tcphdr);
ptr = skb_header_pointer(skb, sizeof(struct tcphdr) + hdroff,
length, buff);
while (length > 0) {
int opcode=*ptr++;
int opsize;
switch (opcode) {
case TCPOPT_EOL:
return NF_ACCEPT;
case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */
length--;
continue;
case TCPOPT_TIMESTAMP:
{
int i = 0;
char *base = ptr-1;
opsize=*ptr;
// printk(KERN_DEBUG "+++%pI4 -> %pI4 datalen=%d jiffies=%u ntohl(jiffies)=%u:", &iph->saddr, &iph->daddr, datalen, jiffies, ntohl(jiffies));
unsigned int * tsp = (unsigned int *)(base+2);
unsigned int ts = ntohl(*tsp);
// unsigned int ts_echo = ntohl(*(unsigned int *)(base+6));
ts = (ts << shift_bits) + ts_id;
printk(KERN_DEBUG "+++%pI4 -> %pI4,before ts=%u,after jiffies =%u ntohl(jiffies)=%u ts=%u===\n",&iph->saddr, &iph->daddr,ntohl(*tsp),jiffies,ntohl(jiffies),ts);
*tsp = htonl(ts);
recalc = 1;
}
default:
opsize=*ptr++;
length -= opsize;
ptr += opsize - 2;
}
}
if (recalc) {
// hdr->check = 0;
// hdr->check = tcp_v4_check(datalen,iph->saddr, iph->daddr, csum_partial(hdr,datalen, 0));
// ip_send_check(iph);
// tcp_v4_send_check(skb->sk,skb);
// hdr->check = 0;
/*
hdr->check = tcp_v4_check(datalen,
iph->saddr, iph->daddr,
csum_partial(hdr,
datalen, 0));
*/
// skb->ip_summed = CHECKSUM_NONE; //stop offloading
skb->ip_summed == CHECKSUM_COMPLETE;
}
return NF_ACCEPT;
}
unsigned int hook_func_pre(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 = (struct iphdr *)(skb->data);
struct tcphdr *hdr;
unsigned int hdroff = iph->ihl*4;
int datalen = skb->len - hdroff;
int hdrsize = 8; /* TCP connection tracking guarantees this much */
const unsigned char *ptr;
unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
int length;
int recalc = 0;
if (iph->protocol != IPPROTO_TCP) {
return NF_ACCEPT;
}
//printk(KERN_DEBUG "---index=%d %pI4 -> %pI4 :\n", in->ifindex,&iph->saddr, &iph->daddr);
if(in->ifindex!=4)
return NF_ACCEPT;
hdr = (struct tcphdr *)(skb->data + hdroff);
if (skb->len >= hdroff + sizeof(struct tcphdr))
hdrsize = sizeof(struct tcphdr);
if (!skb_make_writable(skb, hdroff + hdrsize))
return NF_ACCEPT;
length = (hdr->doff*4) - sizeof(struct tcphdr);
ptr = skb_header_pointer(skb, sizeof(struct tcphdr) + hdroff,
length, buff);
while (length > 0) {
int opcode=*ptr++;
int opsize;
switch (opcode) {
case TCPOPT_EOL:
return NF_ACCEPT;
case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */
length--;
continue;
case TCPOPT_TIMESTAMP:
{
int i = 0;
char *base = ptr-1;
opsize=*ptr;
unsigned int ts = ntohl(*(unsigned int *)(base+2));
unsigned int * tse= (unsigned int *)(base+6);
unsigned int ts_echo = ntohl(*tse);
if(ts_echo){
ts_echo = ts_echo - ts_id;
unsigned int high = (jiffies & 0xf0000000);
ts_echo = (ts_echo >> shift_bits)|high;
printk(KERN_DEBUG "---%pI4 -> %pI4 before ts_echo=%u,after high =%u ts_echo=%u===\n",&iph->saddr, &iph->daddr,ntohl(*tse),high,ts_echo);
*tse = htonl(ts_echo);
recalc = 1;
}
}
default:
opsize=*ptr++;
length -= opsize;
ptr += opsize - 2;
}
}
if (recalc) {
/*
hdr->check = 0;
hdr->check = tcp_v4_check(datalen,
iph->saddr, iph->daddr,
csum_partial(hdr,
datalen, 0));
*/
skb->ip_summed == CHECKSUM_COMPLETE;
// iph->check=0;
// iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
// ip_send_check(iph);
// tcp_v4_send_check(skb->sk,skb);
}
return NF_ACCEPT;
}
int init_hack()
{
printk(KERN_DEBUG " hackts init.\n");
nfho.hook = hook_func;
nfho.hooknum = NF_INET_POST_ROUTING;
nfho.pf = PF_INET;
nfho.priority = NF_IP_PRI_FIRST;
nfho_.hook = hook_func_pre;
nfho_.hooknum = NF_INET_PRE_ROUTING;
nfho_.pf = PF_INET;
nfho_.priority = NF_IP_PRI_FIRST;
nf_register_hook(&nfho);
nf_register_hook(&nfho_);
printk(KERN_DEBUG " hackts init finished.\n");
return 0;
}
void cleanup_hack()
{
nf_unregister_hook(&nfho);
nf_unregister_hook(&nfho_);
}
module_init( init_hack);
module_exit( cleanup_hack);
MODULE_LICENSE("GPL");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment