From 24a7930091ebca5e30dfd228101c368bfe571286 Mon Sep 17 00:00:00 2001 From: chn <897331845@qq.com> Date: Mon, 13 Jan 2020 19:42:05 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B2=8C=E4=BC=BC=E6=98=AF=E5=A4=A7=E5=8A=9F?= =?UTF-8?q?=E5=91=8A=E6=88=90=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +- src/common.h | 11 +- src/rkp-ua.c | 32 +-- src/rkpManager.h | 34 +-- src/rkpMap.h | 82 ++++--- src/rkpPacket.h | 59 ++--- src/rkpSetting.h | 20 +- src/rkpStream.h | 587 ++++++++++++++++++++++------------------------- 8 files changed, 404 insertions(+), 429 deletions(-) diff --git a/README.md b/README.md index 9b47039..46558d5 100644 --- a/README.md +++ b/README.md @@ -143,9 +143,7 @@ flush 函数,关闭超时的流。 用比较宽松的方案去处理。当找不到需要的流的时候去新建而不是寻找三次握手的首包。当扫描到 User-Agent: 后再捕获包、分析、修改,避免不是 HTTP 流量的包被捕获。如果捕获过程中读到 psh,即使没有读到 UA 末尾也要提交。UA 的长度也需要作假设;可以假定为最多两个包。 -接下里需要修改的文件: +debug 的计划: -c -Manager -Map -Stream \ No newline at end of file +打印出序列号,同时抓包 +根据序列号确认需要的包的流向 \ No newline at end of file diff --git a/src/common.h b/src/common.h index 551f699..b816e09 100644 --- a/src/common.h +++ b/src/common.h @@ -1,3 +1,4 @@ +#pragma once #include #include #include @@ -13,7 +14,9 @@ #include #include #include -#pragma once + +typedef _Bool bool; +#define static_assert _Static_assert const static unsigned char* str_uaBegin = "User-Agent: "; const static unsigned char* str_uaEnd = "\r\n"; @@ -31,3 +34,9 @@ void rkpFree(void* p) { kfree(p); } + +#include "rkpSetting.h" +#include "rkpPacket.h" +#include "rkpMap.h" +#include "rkpStream.h" +#include "rkpManager.h" \ No newline at end of file diff --git a/src/rkp-ua.c b/src/rkp-ua.c index 7dde3d7..eaf0363 100644 --- a/src/rkp-ua.c +++ b/src/rkp-ua.c @@ -1,6 +1,6 @@ -#include "rkpManager.h" +#include "common.h" -static struct nf_hook_ops nfho; +static struct nf_hook_ops nfho[3]; // 需要在 INPUT、OUTPUT、FORWARD 各挂一个 static struct rkpManager* rkpm; unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) @@ -9,14 +9,15 @@ unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct nf_hook_ static unsigned n_skb_captured = 0, n_skb_captured_lastPrint = 1; - if(!rkpSettings_capture(skb)) + if(!rkpSetting_capture(skb)) return NF_ACCEPT; rtn = rkpManager_execute(rkpm, skb); n_skb_captured++; if(n_skb_captured == n_skb_captured_lastPrint * 2) { - printk("rkp-ua: Captured %d packets.\n", n_skb_captured); + if(verbose) + printk("rkp-ua: Captured %d packets.\n", n_skb_captured); n_skb_captured_lastPrint *= 2; } return rtn; @@ -25,6 +26,7 @@ unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct nf_hook_ static int __init hook_init(void) { int ret; + unsigned i; rkpm = rkpManager_new(); @@ -32,15 +34,19 @@ static int __init hook_init(void) memcpy(str_uaRkp + 4, VERSION, 2); memcpy(str_uaRkp + 6, ".0", 3); - nfho.hook = hook_funcion; - nfho.pf = NFPROTO_IPV4; - nfho.hooknum = NF_INET_POST_ROUTING; - nfho.priority = NF_IP_PRI_RAW; - + nfho[0].hooknum = NF_INET_LOCAL_IN; + nfho[1].hooknum = NF_INET_LOCAL_OUT; + nfho[2].hooknum = NF_INET_FORWARD; + for(i = 0; i < 3; i++) + { + nfho[i].hook = hook_funcion; + nfho[i].pf = NFPROTO_IPV4; + nfho[i].priority = NF_IP_PRI_MANGLE; + } #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) - ret = nf_register_net_hook(&init_net, &nfho); + ret = nf_register_net_hooks(&init_net, nfho, 3); #else - ret = nf_register_hook(&nfho); + ret = nf_register_hooks(nfho, 3); #endif printk("rkp-ua: Started, version %s\n", VERSION); @@ -58,9 +64,9 @@ static int __init hook_init(void) static void __exit hook_exit(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) - nf_unregister_net_hook(&init_net, &nfho); + nf_unregister_net_hooks(&init_net, nfho, 3); #else - nf_unregister_hook(&nfho); + nf_unregister_hooks(nfho, 3); #endif if(rkpm != 0) rkpManager_delete(rkpm); diff --git a/src/rkpManager.h b/src/rkpManager.h index b45937e..e98b79e 100644 --- a/src/rkpManager.h +++ b/src/rkpManager.h @@ -1,5 +1,5 @@ #pragma once -#include "rkpStream.h" +#include "common.h" struct rkpManager { @@ -11,9 +11,9 @@ struct rkpManager struct rkpManager* rkpManager_new(void); void rkpManager_delete(struct rkpManager*); -int rkpManager_execute(struct rkpManager*, struct sk_buff*); // 处理一个数据包。返回值为 rkpStream_execute 的返回值。 -int __rkpManager_execute(struct rkpManager*, struct rkpPacket*); -void __rkpManager_refresh(unsigned long); // 清理长时间不活动的流 +unsigned rkpManager_execute(struct rkpManager*, struct sk_buff*); // 处理一个数据包。返回值为 rkpStream_execute 的返回值。 +unsigned __rkpManager_execute(struct rkpManager*, struct rkpPacket*); +void __rkpManager_refresh(unsigned long); // 清理长时间不活动的流,参数实际上是 rkpm 的地址 void __rkpManager_lock(struct rkpManager*, unsigned long*); void __rkpManager_unlock(struct rkpManager*, unsigned long); @@ -21,6 +21,8 @@ void __rkpManager_unlock(struct rkpManager*, unsigned long); struct rkpManager* rkpManager_new(void) { struct rkpManager* rkpm = (struct rkpManager*)rkpMalloc(sizeof(struct rkpManager)); + if(debug) + printk("rkpManager_new\n"); if(rkpm == 0) return 0; memset(rkpm -> data, 0, sizeof(struct rkpStream*) * 256); @@ -36,7 +38,10 @@ void rkpManager_delete(struct rkpManager* rkpm) { unsigned i; unsigned long flag; + if(debug) + printk("rkpManager_delete\n"); __rkpManager_lock(rkpm, &flag); + del_timer(&rkpm -> timer); for(i = 0; i < 256; i++) { struct rkpStream* rkps = rkpm -> data[i]; @@ -47,22 +52,19 @@ void rkpManager_delete(struct rkpManager* rkpm) rkps = rkps2; } } - del_timer(&rkpm -> timer); __rkpManager_unlock(rkpm, flag); rkpFree(rkpm); } -int rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb) +unsigned rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb) { unsigned long flag; - int rtn; - struct rkpPacket* rkpp = rkpPacket_new(skb); - if(rkpPacket_appLen(rkpp) == 0) - { - rkpPacket_delete(rkpp); - return NF_ACCEPT; - } + unsigned rtn; + struct rkpPacket* rkpp; + if(debug) + printk("rkpManager_execute\n"); __rkpManager_lock(rkpm, &flag); + rkpp = rkpPacket_new(skb, rkpSetting_ack(skb)); rtn = __rkpManager_execute(rkpm, rkpp); if(debug) { @@ -76,11 +78,9 @@ int rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb) __rkpManager_unlock(rkpm, flag); if(rtn == NF_ACCEPT || rtn == NF_DROP) rkpPacket_delete(rkpp); - if(debug) - skb -> mark |= 0x10; return rtn; } -int __rkpManager_execute(struct rkpManager* rkpm, struct rkpPacket* rkpp) +unsigned __rkpManager_execute(struct rkpManager* rkpm, struct rkpPacket* rkpp) { struct rkpStream *rkps, *rkps_new; @@ -109,6 +109,8 @@ void __rkpManager_refresh(unsigned long param) unsigned i; unsigned long flag; struct rkpManager* rkpm = (struct rkpManager*)param; + if(debug) + printk("rkpManager_refresh\n"); __rkpManager_lock(rkpm, &flag); for(i = 0; i < 256; i++) { diff --git a/src/rkpMap.h b/src/rkpMap.h index c47b82f..95fc9e9 100644 --- a/src/rkpMap.h +++ b/src/rkpMap.h @@ -1,20 +1,19 @@ #pragma once #include "common.h" -#include "rkpPacket.h" struct rkpMap // 以相对序列号记录应用层数据中需要修改的部分的位置,提供修改的函数 { - int32_t begin, length; // begin 为绝对序列号 - // int32_t &seq_offset = beign; // 需要一个差不多的数值作为偏移来计算序列号谁先谁后的问题,这个偏移取为 begin + int32_t begin, length; // begin 为绝对序列号 + // int32_t &seq_offset = beign; // 需要一个差不多的数值作为偏移来计算序列号谁先谁后的问题,这个偏移取为 begin struct rkpMap *prev, *next; }; -struct rkpMap* rkpMap_new(int32_t, int32_t); // 两个参数分别为起始和终止绝对序列号 +struct rkpMap* rkpMap_new(int32_t, int32_t); // 两个参数分别为起始和终止绝对序列号 void rkpMap_delete(struct rkpMap*); unsigned char __rkpMap_map(const struct rkpMap*, int32_t); // 返回某个序列号对应的映射后的值。假定参数是合法的。这里的参数是相对序列号 -void rkpMap_modify(const struct rkpMap*, struct rkpPacket**); // 对一列序列号连续且递增的包进行修改 +void rkpMap_modify(struct rkpMap**, struct rkpPacket**); // 对一列序列号连续且递增的包进行修改 void rkpMap_insert_begin(struct rkpMap**, struct rkpMap*); // 在开头位置插入一个映射 void rkpMap_insert_end(struct rkpMap**, struct rkpMap*); @@ -42,35 +41,43 @@ unsigned char __rkpMap_map(const struct rkpMap* rkpm, int32_t seq) else return ' '; } -void rkpMap_modify(const struct rkpMap* rkpm, struct rkpPacket** rkppl) +void rkpMap_modify(struct rkpMap** rkpml, struct rkpPacket** rkppl) { - struct rkpPacket* rkpp; - unsigned char* p; - int32_t seq; - - // 尝试确定第一个需要修改的包 - for(rkpp = *rkppl; rkpp != 0; rkpp = rkpp -> next) - if(rkpPacket_seq(rkpp, rkpm -> begin) + rkpPacket_appLen(rkpp) > 0) - break; - if(rkpp == 0) - return; - p = rkpPacket_appBegin(rkpp) - rkpPacket_seq(rkpp, rkpm -> begin); - seq = 0; - - // 开始修改 - for(; rkpp != 0; rkpp = rkpp -> next) + const struct rkpMap* rkpm; + for(rkpm = *rkpml; rkpm != 0; rkpm = rkpm -> next) { - if(seq != 0) - p = rkpPacket_appBegin(rkpp); - for(; p != rkpPacket_appEnd(rkpp) && seq < rkpm -> length; p++, seq++) - *p = __rkpMap_map(rkpm, seq); - rkpPacket_csum(rkpp); - if(seq == rkpm -> length) + struct rkpPacket* rkpp; + unsigned char* p = 0; + int32_t seq; + + // 尝试确定第一个需要修改的包以及需要修改的开始处 + for(rkpp = *rkppl; rkpp != 0; rkpp = rkpp -> next) + if(rkpPacket_seq(rkpp, rkpm -> begin) + rkpPacket_appLen(rkpp) > 0) + break; + if(rkpp == 0) break; + if(rkpPacket_seq(rkpp, rkpm -> begin) <= 0) + { + p = rkpPacket_appBegin(rkpp) - rkpPacket_seq(rkpp, rkpm -> begin); + seq = 0; + } + else // p 会在稍后被设置到包的开头 + seq = rkpPacket_seq(rkpp, rkpm -> begin); + + // 开始修改 + for(; rkpp != 0; rkpp = rkpp -> next) + { + if(seq != 0) + p = rkpPacket_appBegin(rkpp); + for(; p != rkpPacket_appEnd(rkpp) && seq < rkpm -> length; p++, seq++) + *p = __rkpMap_map(rkpm, seq); + rkpPacket_csum(rkpp); + if(seq == rkpm -> length) + break; + } } } - void rkpMap_insert_begin(struct rkpMap** rkpml, struct rkpMap* rkpm) { rkpm -> next = *rkpml; @@ -92,9 +99,20 @@ void rkpMap_insert_end(struct rkpMap** rkpml, struct rkpMap* rkpm) } void rkpMap_refresh(struct rkpMap** rkpml, int32_t seq) { - struct rkpMap* rkpm; + struct rkpMap *rkpm1, *rkpm2, *rkpm3; // 找到第一个不用删除的映射 - for(rkpm = *rkpml; rkpm != 0; rkpm = rkpm -> next) - // if(rkpm -> begin + rkpm -> length <= seq) 需要避免绝对值很大的负数小于绝对值很大的正数的情况 - if((int32_t)(seq - rkpm -> begin) + rkpm -> length) - seq) <= 0) + for(rkpm1 = *rkpml; rkpm1 != 0; rkpm1 = rkpm1 -> next) + // if(rkpm -> begin + rkpm -> length > seq) 需要避免绝对值很大的负数小于绝对值很大的正数的情况 + if((int32_t)(seq - rkpm1 -> begin) - rkpm1 -> length < 0) + break; + // 将这个映射之前的所有映射都删除 + for(rkpm2 = *rkpml; rkpm2 != rkpm1; rkpm2 = rkpm3) + { + rkpm3 = rkpm2 -> next; + rkpMap_delete(rkpm2); + } + // 修改一些指针 + if(rkpm1 != 0) + rkpm1 -> prev = 0; + *rkpml = rkpm1; } \ No newline at end of file diff --git a/src/rkpPacket.h b/src/rkpPacket.h index 7a46d75..0f5d038 100644 --- a/src/rkpPacket.h +++ b/src/rkpPacket.h @@ -1,5 +1,5 @@ -#include "common.h" #pragma once +#include "common.h" struct rkpPacket // 存储一个个数据包的类,完全被 rkpStream 和 rkpManager 包裹 @@ -39,7 +39,7 @@ void rkpPacket_insert_begin(struct rkpPacket**, struct rkpPacket*); // 在 void rkpPacket_insert_end(struct rkpPacket**, struct rkpPacket*); // 在指定链表尾部插入一个包 struct rkpPacket* rkpPacket_pop_begin(struct rkpPacket**); // 将指定链表头部的包取出 struct rkpPacket* rkpPacket_pop_end(struct rkpPacket**); // 将指定链表尾部的包取出 -unsigned rkpPacket_num(const struct rkpPacket*); // 返回指定链表中包的数目 +unsigned rkpPacket_num(struct rkpPacket**); // 返回指定链表中包的数目 void rkpPacket_sendl(struct rkpPacket**); void rkpPacket_deletel(struct rkpPacket**); @@ -73,44 +73,44 @@ struct rkpPacket* rkpPacket_new(struct sk_buff* skb, bool ack) } return rkpp; } -void rkpPacket_send(struct rkpPacket* p) +void rkpPacket_send(struct rkpPacket* rkpp) { - if(dev_queue_xmit(p -> skb)) + if(dev_queue_xmit(rkpp -> skb)) { printk("rkp-ua: rkpPacket_new: Send failed. Drop it.\n"); - kfree_skb(p -> skb); + kfree_skb(rkpp -> skb); } - rkpFree(p); + rkpFree(rkpp); } -void rkpPacket_delete(struct rkpPacket* p) +void rkpPacket_delete(struct rkpPacket* rkpp) { - rkpFree(p); + rkpFree(rkpp); } -void rkpPacket_drop(struct rkpPacket* p) +void rkpPacket_drop(struct rkpPacket* rkpp) { - kfree_skb(p -> skb); - rkpFree(p); + kfree_skb(rkpp -> skb); + rkpFree(rkpp); } -unsigned char* rkpPacket_appBegin(const struct rkpPacket* p) +unsigned char* rkpPacket_appBegin(const struct rkpPacket* rkpp) { - return ((unsigned char*)tcp_hdr(p -> skb)) + tcp_hdr(p -> skb) -> doff * 4; + return ((unsigned char*)tcp_hdr(rkpp -> skb)) + tcp_hdr(rkpp -> skb) -> doff * 4; } -unsigned char* rkpPacket_appEnd(const struct rkpPacket* p) +unsigned char* rkpPacket_appEnd(const struct rkpPacket* rkpp) { - return ((unsigned char*)ip_hdr(p -> skb)) + ntohs(ip_hdr(p -> skb) -> tot_len); + return ((unsigned char*)ip_hdr(rkpp -> skb)) + ntohs(ip_hdr(rkpp -> skb) -> tot_len); } -unsigned rkpPacket_appLen(const struct rkpPacket* p) +unsigned rkpPacket_appLen(const struct rkpPacket* rkpp) { - return ntohs(ip_hdr(p -> skb) -> tot_len) - ip_hdr(p -> skb) -> ihl * 4 - tcp_hdr(p -> skb) -> doff * 4; + return ntohs(ip_hdr(rkpp -> skb) -> tot_len) - ip_hdr(rkpp -> skb) -> ihl * 4 - tcp_hdr(rkpp -> skb) -> doff * 4; } -int32_t rkpPacket_seq(const struct rkpPacket* p, const int32_t offset) +int32_t rkpPacket_seq(const struct rkpPacket* rkpp, const int32_t offset) { - return (int32_t)ntohl(tcp_hdr(p -> skb) -> seq) - offset; + return (int32_t)ntohl(tcp_hdr(rkpp -> skb) -> seq) - offset; } -int32_t rkpPacket_seqAck(const struct rkpPacket* p, const int32_t offset) +int32_t rkpPacket_seqAck(const struct rkpPacket* rkpp, const int32_t offset) { - return (int32_t)ntohl(tcp_hdr(p -> skb) -> ack) - offset; + return (int32_t)ntohl(tcp_hdr(rkpp -> skb) -> ack_seq) - offset; } u_int32_t rkpPacket_sip(const struct rkpPacket* rkpp) { @@ -147,8 +147,8 @@ void rkpPacket_csum(struct rkpPacket* rkpp) struct tcphdr* tcph = tcp_hdr(rkpp -> skb); tcph -> check = 0; iph -> check = 0; - iph -> check = ip_fast_csum((unsigned char*)iph, iph -> ihl); rkpp -> skb -> csum = skb_checksum(rkpp -> skb, iph -> ihl * 4, ntohs(iph -> tot_len) - iph -> ihl * 4, 0); + iph -> check = ip_fast_csum((unsigned char*)iph, iph -> ihl); tcph -> check = csum_tcpudp_magic(iph -> saddr, iph -> daddr, ntohs(iph -> tot_len) - iph -> ihl * 4, IPPROTO_TCP, rkpp -> skb -> csum); } @@ -175,16 +175,12 @@ void rkpPacket_insert_auto(struct rkpPacket** buff, struct rkpPacket* rkpp, int3 { // 如果链表是空的,那么就直接加进去 if(*buff == 0) - { *buff = rkpp; - rkpp -> prev = rkpp -> next = 0; - } // 又或者,要插入的包需要排到第一个 else if(rkpPacket_seq(*buff, offset) >= rkpPacket_seq(rkpp, offset)) { (*buff) -> prev = rkpp; rkpp -> next = *buff; - rkpp -> prev = 0; *buff = rkpp; } // 接下来寻找最后一个序列号小于 rkpp 的包,插入到它的后面。 @@ -203,10 +199,7 @@ void rkpPacket_insert_auto(struct rkpPacket** buff, struct rkpPacket* rkpp, int3 void rkpPacket_insert_begin(struct rkpPacket** buff, struct rkpPacket* rkpp) { if(*buff == 0) - { *buff = rkpp; - rkpp -> next = rkpp -> prev = 0; - } else { (*buff) -> prev = rkpp; @@ -217,10 +210,7 @@ void rkpPacket_insert_begin(struct rkpPacket** buff, struct rkpPacket* rkpp) void rkpPacket_insert_end(struct rkpPacket** buff, struct rkpPacket* rkpp) { if(*buff == 0) - { *buff = rkpp; - rkpp -> next = rkpp -> prev = 0; - } else { struct rkpPacket* rkpp2 = *buff; @@ -228,7 +218,6 @@ void rkpPacket_insert_end(struct rkpPacket** buff, struct rkpPacket* rkpp) rkpp2 = rkpp2 -> next; rkpp2 -> next = rkpp; rkpp -> prev = rkpp2; - rkpp -> next = 0; } } struct rkpPacket* rkpPacket_pop_begin(struct rkpPacket** buff) @@ -258,10 +247,10 @@ struct rkpPacket* rkpPacket_pop_end(struct rkpPacket** buff) } return rkpp; } -unsigned rkpPacket_num(const struct rkpPacket* buff) +unsigned rkpPacket_num(struct rkpPacket** buff) { unsigned n = 0; - const struct rkpPacket* rkpp = buff; + const struct rkpPacket* rkpp = *buff; while(rkpp != 0) { rkpp = rkpp -> next; diff --git a/src/rkpSetting.h b/src/rkpSetting.h index 761ab4c..5fa3eb6 100644 --- a/src/rkpSetting.h +++ b/src/rkpSetting.h @@ -1,8 +1,8 @@ -#include "common.h" #pragma once +#include "common.h" -_Static_assert(sizeof(int) == 4, "int is not 4 bit."); -_Static_assert(sizeof(unsigned long) >= sizeof(void*), "ulong is too short."); +static_assert(sizeof(int) == 4, "int is not 4 bit."); +static_assert(sizeof(unsigned long) >= sizeof(void*), "ulong is too short."); static bool autocapture = true; module_param(autocapture, bool, 0); @@ -22,10 +22,10 @@ module_param(verbose, bool, 0); static bool debug = false; module_param(debug, bool, 0); -bool rkpSettings_capture(const struct sk_buff*); -bool rkpSettings_ack(const struct sk_buff*); +bool rkpSetting_capture(const struct sk_buff*); +bool rkpSetting_ack(const struct sk_buff*); -bool rkpSettings_capture(const struct sk_buff* skb) +bool rkpSetting_capture(const struct sk_buff* skb) { if(!autocapture) { @@ -33,7 +33,7 @@ bool rkpSettings_capture(const struct sk_buff* skb) } else { - if(rkpSettings_ack(skb)) + if(rkpSetting_ack(skb)) return true; if(ip_hdr(skb) -> protocol != IPPROTO_TCP) return false; @@ -46,7 +46,7 @@ bool rkpSettings_capture(const struct sk_buff* skb) return true; } } -bool rkpSettings_ack(const struct sk_buff* skb) +bool rkpSetting_ack(const struct sk_buff* skb) { if(!autocapture) { @@ -61,9 +61,7 @@ bool rkpSettings_ack(const struct sk_buff* skb) else if((ntohl(ip_hdr(skb) -> daddr) & 0xFFFF0000) != (192 << 24) + (168 << 16) || (ntohl(ip_hdr(skb) -> saddr) & 0xFFFF0000) == (192 << 24) + (168 << 16)) return false; - else if(tcp_hdr(skb) -> ack) - return true; else - return false; + return tcp_hdr(skb) -> ack; } } \ No newline at end of file diff --git a/src/rkpStream.h b/src/rkpStream.h index 1b24115..64abb64 100644 --- a/src/rkpStream.h +++ b/src/rkpStream.h @@ -1,9 +1,8 @@ #pragma once -#include "rkpSettings.h" -#include "rkpPacket.h" +#include "common.h" struct rkpStream -// 接管一个 TCP 流。忽略重传(一律放行)。因此,也不需要捕获来自服务端的包。 +// 接管一个 TCP 流。 { enum { @@ -11,13 +10,24 @@ struct rkpStream __rkpStream_sniffing_uaEnd, // 已经找到 ua,正在寻找它的结尾,buff_scan 中可能有包 __rkpStream_waiting // 已经找到 ua 的结尾或者 http 头的结尾并且还没有 psh,接下来的包都直接放行 } status; + enum + { + __rkpStream_scan_noFound, // 还没找到 ua 的开头 + __rkpStream_scan_uaBegin, // 匹配到了 ua 开头,但是 ua 实际的开头在下个数据包 + __rkpStream_scan_uaRealBegin, // 匹配到了 ua 开头,ua 实际的开头在这个数据包 + __rkpStream_scan_uaEnd, // 匹配到了 ua 的结尾,并且需要修改 ua + __rkpStream_scan_uaGood, // 匹配到了 ua 的结尾,但是不需要修改 ua + __rkpStream_scan_headEnd // 匹配到了 http 头部的结尾,没有发现 ua + } scan_status; // 记录扫描结果,仅由 __rkpStream_scan 和 __rkpStream_reset 设置,由 rkpStream_execute 和 __rkpStream_scan 读取 u_int32_t id[3]; // 按顺序存储客户地址、服务地址、客户端口、服务端口,已经转换字节序 struct rkpPacket *buff_scan, *buff_disordered; // 分别存储准备扫描的、因乱序而提前收到的数据包,都按照序号排好了 - int32_t seq_offset; // 序列号的偏移。使得 buff_scan 中第一个字节的编号为零。在 rkpStream 中,序列号基本使用相对值;但在传给下一层时,基本使用绝对值 + int32_t seq_offset; // 序列号的偏移。使得 buff_scan 中第一个字节的编号为零。在 rkpStream 中,序列号使用相对值;但在传给下一层时,使用绝对值 bool active; // 是否仍然活动,流每次处理的时候会置为 true,每隔一段时间会删除标志为 false(说明它在这段时间里没有活动)的流,将标志为 true 的流的标志也置为 false。 - unsigned scan_headEnd_matched, scan_uaBegin_matched, scan_uaEnd_matched; // 记录现在已经匹配了多少个字节,由 __rkpStream_scan 设置,但可以由其它过程置零 - unsigned char *scan_uaBegin_p, *scan_uaEnd_p; // 记录扫描的一些结果,由 __rkpStream_scan 设置,但可以由其它过程置零 - struct rkpMap* map; + unsigned scan_headEnd_matched, scan_uaBegin_matched, scan_uaEnd_matched, *scan_uaPreserve_matched; + // 记录现在已经匹配了多少个字节,仅由 __rkpStream_scan 和 __rkpStream_reset 使用 + uint32_t scan_uaBegin_seq, scan_uaEnd_seq; + // 记录 ua 开头和结束的序列号,仅由 __rkpStream_scan、__rkpStream_reset 设置 + struct rkpMap* map; // 记录 ua 的位置,方便修改重传数据包,仅由 __rkpStream_modify 使用 struct rkpStream *prev, *next; }; @@ -31,59 +41,79 @@ int32_t __rkpStream_seq_desired(const struct rkpStream*); // 返 void __rkpStream_scan(struct rkpStream*, struct rkpPacket*); // 对一个最新的包进行扫描 void __rkpStream_reset(struct rkpStream*); // 重置扫描进度,包括将 buff_scan 中的包全部发出 -void __rkpStream_modify(struct rkpStream*); // 在收集到完整的 ua 后,对 ua 进行修改 struct rkpStream* rkpStream_new(const struct rkpPacket* rkpp) { struct rkpStream* rkps; if(debug) printk("rkpStream_new\n"); - rkps = (struct rkpStream*)rkpMalloc(sizeof(struct rkpStream)); + rkps = (struct rkpStream*)rkpMalloc(sizeof(struct rkpStream) + sizeof(unsigned) * n_str_preserve); if(rkps == 0) return 0; + rkps -> scan_uaPreserve_matched = (unsigned*)((void*)rkps + sizeof(struct rkpStream)); rkps -> status = __rkpStream_sniffing_uaBegin; memcpy(rkps -> id, rkpp -> lid, 3 * sizeof(u_int32_t)); rkps -> buff_scan = rkps -> buff_disordered = 0; rkps -> seq_offset = rkpPacket_seq(rkpp, 0); + if(rkpPacket_syn(rkpp)) + rkps -> seq_offset++; rkps -> active = true; - rkps -> scan_headEnd_matched = rkps -> scan_uaBegin_matched = rkps -> scan_uaEnd_matched = 0; - rkps -> scan_uaBegin_p = rkps -> scan_uaEnd_p = 0; rkps -> map = 0; rkps -> prev = rkps -> next = 0; + __rkpStream_reset(rkps); return rkps; } void rkpStream_delete(struct rkpStream* rkps) { - struct rkpPacket* rkpp; + struct rkpMap* rkpm; if(debug) printk("rkpStream_delete\n"); rkpPacket_deletel(&rkps -> buff_scan); rkpPacket_deletel(&rkps -> buff_disordered); + for(rkpm = rkps -> map; rkpm != 0; rkpm = rkpm -> next) + rkpMap_delete(rkpm); rkpFree(rkps); } bool rkpStream_belongTo(const struct rkpStream* rkps, const struct rkpPacket* rkpp) { + if(debug) + printk("rkpStream_belongTo\n"); return memcmp(rkps -> id, rkpp -> lid, 3 * sizeof(u_int32_t)) == 0; } unsigned rkpStream_execute(struct rkpStream* rkps, struct rkpPacket* rkpp) // 不要害怕麻烦,咱们把每一种情况都慢慢写一遍。 -// 以下假定:包是客户端发到服务端的,并且带有应用层数据 { if(debug) - printk("rkp-ua: rkpStream_execute start, judging...\n"); + printk("rkp-ua: rkpStream_execute start, judging %u ...\n", rkpPacket_seq(rkpp, 0)); // 肯定需要更新活动情况 rkps -> active = true; + // 首先处理如果是 ack 的情况 + if(rkpp -> ack) + { + if(debug) + printk("ack packet\n"); + rkpMap_refresh(&rkps -> map, rkpPacket_seqAck(rkpp, 0)); + return NF_ACCEPT; + } + + // 其它情况,首先放掉所有没有应用层数据的包 + if(rkpPacket_appLen(rkpp) == 0) + { + if(debug) + printk("empty packet\n"); + return NF_ACCEPT; + } + // 接下来从小到大考虑数据包的序列号的几种情况 // 已经发出的数据包,使用已有的映射修改 if(rkpPacket_seq(rkpp, rkps -> seq_offset) < 0) { if(debug) - printk("\tThe packet is re-transforming or has been modified, return NF_ACCEPT.\n"); - if(debug && rkpp -> skb -> mark & 0x10) - printk("\tThe packet seems has been modified.\n"); + printk("\tThe packet is re-transforming or has been modified.\n"); + rkpMap_modify(&rkps -> map, &rkpp); return NF_ACCEPT; } // 已经放到 buff_scan 中的数据包,丢弃 @@ -99,7 +129,7 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct rkpPacket* rkpp) { if(debug) printk("\tThe packet is disordered, return NF_STOLEN.\n"); - __rkpStream_insert_auto(rkps, &rkps -> buff_disordered, rkpp); + rkpPacket_insert_auto(&rkps -> buff_disordered, rkpp, rkps -> seq_offset); return NF_STOLEN; } @@ -108,45 +138,31 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct rkpPacket* rkpp) if(true) { // 因为一会儿可能还需要统一考虑 buff_disordered 中的包,因此不直接 return,将需要的返回值写到这里,最后再 return - unsigned rtn; + unsigned rtn = NF_ACCEPT; if(debug) printk("\tThe packet is desired one, further judging.\n"); // 接下来分析几种情况 - // * sniffing_uaBegin 状态下,先扫描这个数据包,再看情况处理 - // 需要考虑的方面有: - // * 是否扫描到了 uaBegin,通过 uaBegin_matched 是否与 str_uaBegin 长度相等判断 - // * 在扫描到了 uaBegin 的前提下,是否得到了 ua 的开头位置。这是因为,可能一个数据包的结尾恰好是 `User-Agent: `,结果扫描到了 uaBegin 但是 ua 的开头在下一个数据包。通过 uaBegin_p 是否为非零值判断 - // * 在扫描到了 uaBegin 和 ua 开头位置的前提下,是否扫描到了 uaEnd,通过 uaEnd_matched 是否与 str_uaEnd 长度相等判断 - // * 在没有扫描到 uaBegin 的前提下,是否扫描到了 headEnd,通过 headEnd_matched 是否与 str_headEnd 长度相等判断;无需区分扫描到 - // uaBegin 的各种情况中,扫描到 headEnd 与没有扫描到 headEnd 的情况,因为如果扫描到 headEnd,必然扫描到 ua 开头位置、uaEnd;分别考虑 - // 是否有 psh 的两对情况,得到的处理方法相同 - // * 是否有 psh - // 这些方面可能的组合(包括一些标准的 HTTP 协议不应该出现的组合)和处理办法为: - // 1. 什么都没有扫描到,没有 psh。更新 seq_offset,返回 NF_ACCEPT。 - // 2. 什么都没有扫描到,有 psh。重置,更新 seq_offset,返回 NF_ACCEPT。 - // 3. 扫描到了 headEnd(其它都没有扫描到,下同),没有 psh。重置,状态切换为 waiting,更新 seq_offset,返回 NF_ACCEPT。 - // 4. 扫描到了 headEnd,有 psh。重置,更新 seq_offset,返回 NF_ACCEPT。 - // 5. 扫描到了 uaBegin,没有 psh。状态切换为 sniffing_uaEnd,更新 seq_offset,返回 NF_ACCEPT。 - // 6. 扫描到了 uaBegin,有 psh。发出警告,重置,更新 seq_offset,返回 NF_ACCEPT。 - // 7. 扫描到了 uaBegin、ua 开头位置,没有 psh。保留数据包,状态切换为 sniffing_uaEnd,返回 NF_STOLEN。 - // 8. 扫描到了 uaBegin、ua 开头位置,有 psh。发出警告,重置,更新 seq_offset,返回 NF_ACCEPT。 - // 9. 扫描到了 uaBegin、ua 开头位置、uaEnd,没有 psh。修改数据包,重置,状态切换为 waiting,更新 seq_offset,返回 NF_ACCEPT。 - // 10. 扫描到了 uaBegin、ua 开头位置、uaEnd,有 psh。修改数据包,重置,更新 seq_offset,返回 NF_ACCEPT。 - // 上面的情况中,有些情况的处置方法是类似的,因此可以合并;但为了整齐,在写代码时还是一个一个写出。 - // * sniffing_uaEnd 状态下,如果之前没有扫描到 ua 开头位置,需要先将这个数据包的应用层起始位置作为 ua 开头位置,再扫描数据包,然后再分情况处理。 - // 需要考虑的方面有(这时 uaBegin 和 ua 开头位置一定已经扫描到,并且 headEnd 是否扫描到不影响结果): - // * 是否扫描到了 uaEnd,判断方法同上 - // * 在没有扫描到 uaEnd 的前提下,算上这个数据包,是否达到了预估的 ua 最大长度 - // * 是否有 psh - // 可能的组合和处理办法为: - // 1. 没有扫描到 uaEnd,不到最大长度,没有 psh。保留数据包,返回 NF_STOLEN。 - // 2. 没有扫描到 uaEnd,不到最大长度,有 psh。发出警告,重置,状态切换为 sniffing_uaBegin,更新 seq_offset,返回 NF_ACCEPT。 - // 3. 没有扫描到 uaEnd,到最大长度,没有 psh。发出警告(ua 最大长度可能太小),重置,状态切换为 waiting,更新 seq_offset,返回 NF_ACCEPT。 - // 4. 没有扫描到 uaEnd,到最大长度,有 psh。发出警告,重置,状态切换为 sniffing_uaBegin,更新 seq_offset,返回 NF_ACCEPT。 - // 5. 扫描到 uaEnd,没有 psh。修改数据包,重置,状态切换为 waiting,更新 seq_offset,返回 NF_ACCEPT。 - // 6. 扫描到 uaEnd,有 psh。修改数据包,重置,状态切换为 sniffing_uaBegin,更新 seq_offset,返回 NF_ACCEPT。 + // * sniffing_uaBegin 状态下,先扫描这个数据包,再看情况处理。需要考虑 scan_status 和是否有 psh。 + // * 没有 psh 的情况: + // * noFound:更新 seq_offset,返回 NF_ACCEPT。 + // * uaBegin:状态切换为 sniffing_uaEnd,更新 seq_offset,返回 NF_ACCEPT。 + // * uaRealBegin:保留数据包,状态切换为 sniffing_uaEnd,返回 NF_STOLEN。 + // * uaEnd:生成映射,修改数据包,重置扫描进度,状态切换为 waiting,更新 seq_offset,返回 NF_ACCEPT。 + // * uaGood 或 headEnd:重置扫描进度,状态切换为 waiting,更新 seq_offset,返回 NF_ACCEPT。 + // * 有 psh 的情况: + // * noFound、uaBegin、uaRealBegin、uaGood 或 headEnd:重置扫描进度,更新 seq_offset,返回 NF_ACCEPT。 + // * uaEnd:生成映射,修改数据包,重置扫描进度,更新 seq_offset,返回 NF_ACCEPT。 + // * sniffing_uaEnd 状态下,同样是先扫描数据包,然后再分情况处理。需要考虑 scan_status、是否有 psh 以及是否达到最大长度 + // * 没有 psh 的情况: + // * uaBegin 或 uaRealBegin:如果到了最大长度,就发出警告(ua 最大长度可能太小),重置扫描进度,发出数据包,状态切换为 waiting,更新 seq_offset,返回 NF_ACCEPT; + // 否则,保留数据包,返回 NF_STOLEN。 + // * uaEnd:生成映射,修改数据包,重置扫描进度,发出数据包,状态切换为 waiting,更新 seq_offset,返回 NF_ACCEPT。 + // * uaGood:重置扫描进度,发出数据包,状态切换为 waiting,更新 seq_offset,返回 NF_ACCEPT。 + // * 有 psh 的情况: + // * uaBegin、uaRealBegin 或 uaGood:重置扫描进度,发出数据包,状态切换为 sniffing_uaBegin,更新 seq_offset,返回 NF_ACCEPT。 + // * uaEnd:生成映射,修改数据包,重置扫描进度,发出数据包,状态切换为 sniffing_uaBegin,更新 seq_offset,返回 NF_ACCEPT。 // * waiting 状态下,如果有 psh,则将状态切换为 sniffing_uaBegin,否则不切换;然后更新 seq_offset,返回 NF_ACCEPT 即可。 if(rkps -> status == __rkpStream_sniffing_uaBegin) @@ -156,172 +172,161 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct rkpPacket* rkpp) __rkpStream_scan(rkps, rkpp); if(debug) { - if(rkps -> scan_uaBegin_matched == strlen(str_uaBegin)) - printk("\t\tuaBegin_matched.\n"); - if(rkps -> scan_uaBegin_p != 0) - printk("\t\tuaBegin_p matched.\n"); - if(rkps -> scan_uaEnd_matched == strlen(str_uaEnd)) - printk("\t\tuaEnd_matched.\n"); - if(rkps -> scan_headEnd_matched == strlen(str_headEnd)) - printk("\t\theadEnd_matched.\n"); + if(rkps -> scan_status == __rkpStream_scan_noFound) + printk("\t\tnoFound\n"); + else if(rkps -> scan_status == __rkpStream_scan_uaBegin) + printk("\t\tuaBegin\n"); + else if(rkps -> scan_status == __rkpStream_scan_uaRealBegin) + printk("\t\tuaRealBegin\n"); + else if(rkps -> scan_status == __rkpStream_scan_uaEnd) + printk("\t\tuaEnd\n"); + else if(rkps -> scan_status == __rkpStream_scan_uaGood) + printk("\t\tuaGood\n"); + else if(rkps -> scan_status == __rkpStream_scan_headEnd) + printk("\t\theadEnd\n"); if(rkpPacket_psh(rkpp)) - printk("\t\tpsh.\n"); + printk("\t\tpsh\n"); } - if(rkps -> scan_uaBegin_matched < strlen(str_uaBegin)) - if(rkps -> scan_headEnd_matched < strlen(str_headEnd)) - if(!rkpPacket_psh(rkpp)) - { - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - { - __rkpStream_reset(rkps); - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - if(!rkpPacket_psh(rkpp)) - { - __rkpStream_reset(rkps); - rkps -> status = __rkpStream_waiting; - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - { - __rkpStream_reset(rkps); - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - if(rkps -> scan_uaBegin_p == 0) - if(!rkpPacket_psh(rkpp)) - { - rkps -> status = __rkpStream_sniffing_uaEnd; - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - { - if(verbose) - printk("half of ua found before psh.\n"); - __rkpStream_reset(rkps); - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - if(rkps -> scan_uaEnd_matched < strlen(str_uaEnd)) - if(!rkpPacket_psh(rkpp)) - { - __rkpStream_insert_end(rkps, &rkps -> buff_scan, rkpp); - rkps -> status = __rkpStream_sniffing_uaEnd; - rtn = NF_STOLEN; - } - else - { - if(verbose) - printk("half of ua found before psh.\n"); - __rkpStream_reset(rkps); - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - if(!rkpPacket_psh(rkpp)) - { - __rkpStream_insert_end(rkps, &rkps -> buff_scan, rkpp); - __rkpStream_modify(rkps); - __rkpStream_pop_end(rkps, &rkps -> buff_scan); - __rkpStream_reset(rkps); - rkps -> status = __rkpStream_waiting; - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - { - __rkpStream_insert_end(rkps, &rkps -> buff_scan, rkpp); - __rkpStream_modify(rkps); - __rkpStream_pop_end(rkps, &rkps -> buff_scan); - __rkpStream_reset(rkps); - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - } - else if(rkps -> status == __rkpStream_sniffing_uaEnd) - { - if(debug) - printk("\t\tsniffing_uaEnd\n"); - if(rkps -> scan_uaBegin_p == 0) - rkps -> scan_uaBegin_p = rkpPacket_appBegin(rkpp); - __rkpStream_scan(rkps, rkpp); - if(debug) - { - if(rkps -> scan_uaBegin_matched == strlen(str_uaBegin)) - printk("\t\tuaBegin_matched.\n"); - if(rkps -> scan_uaBegin_p != 0) - printk("\t\tuaBegin_p matched.\n"); - if(rkps -> scan_uaEnd_matched == strlen(str_uaEnd)) - printk("\t\tuaEnd_matched.\n"); - if(rkps -> scan_headEnd_matched == strlen(str_headEnd)) - printk("\t\theadEnd_matched.\n"); - if(rkpPacket_psh(rkpp)) - printk("\t\tpsh.\n"); - } - if(rkps -> scan_uaEnd_matched < strlen(str_uaEnd)) - if(__rkpStream_num(rkps, rkps -> buff_scan) + 1 < len_ua) - if(!rkpPacket_psh(rkpp)) - { - __rkpStream_insert_end(rkps, &rkps -> buff_scan, rkpp); - rtn = NF_STOLEN; - } - else - { - if(verbose) - printk("half of ua found before psh.\n"); - __rkpStream_reset(rkps); - rkps -> status = __rkpStream_sniffing_uaBegin; - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - if(!rkpPacket_psh(rkpp)) - { - if(verbose) - printk("len_ua=%d maybe too small.\n", len_ua); - __rkpStream_reset(rkps); - rkps -> status = __rkpStream_waiting; - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - { - if(verbose) - printk("half of ua found before psh.\n"); - __rkpStream_reset(rkps); - rkps -> status = __rkpStream_sniffing_uaBegin; - rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); - rtn = NF_ACCEPT; - } - else - if(!rkpPacket_psh(rkpp)) + if(!rkpPacket_psh(rkpp)) + switch (rkps -> scan_status) { - __rkpStream_insert_end(rkps, &rkps -> buff_scan, rkpp); - __rkpStream_modify(rkps); - __rkpStream_pop_end(rkps, &rkps -> buff_scan); + case __rkpStream_scan_noFound: + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + break; + case __rkpStream_scan_uaBegin: + rkps -> status = __rkpStream_sniffing_uaEnd; + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + break; + case __rkpStream_scan_uaRealBegin: + rkpPacket_insert_end(&rkps -> buff_scan, rkpp); + rkps -> status = __rkpStream_sniffing_uaEnd; + rtn = NF_STOLEN; + break; + case __rkpStream_scan_uaEnd: + rkpMap_insert_end(&rkps -> map, rkpMap_new(rkps -> scan_uaBegin_seq, rkps -> scan_uaEnd_seq)); + rkpMap_modify(&rkps -> map, &rkpp); + __rkpStream_reset(rkps); + rkps -> status = __rkpStream_waiting; + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + break; + case __rkpStream_scan_uaGood: + case __rkpStream_scan_headEnd: __rkpStream_reset(rkps); rkps -> status = __rkpStream_waiting; rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); rtn = NF_ACCEPT; } - else + else + switch (rkps -> scan_status) { - __rkpStream_insert_end(rkps, &rkps -> buff_scan, rkpp); - __rkpStream_modify(rkps); - __rkpStream_pop_end(rkps, &rkps -> buff_scan); + case __rkpStream_scan_noFound: + case __rkpStream_scan_uaBegin: + case __rkpStream_scan_uaRealBegin: + case __rkpStream_scan_uaGood: + case __rkpStream_scan_headEnd: __rkpStream_reset(rkps); + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + break; + case __rkpStream_scan_uaEnd: + rkpMap_insert_end(&rkps -> map, rkpMap_new(rkps -> scan_uaBegin_seq, rkps -> scan_uaEnd_seq)); + rkpMap_modify(&rkps -> map, &rkpp); + __rkpStream_reset(rkps); + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + } + } + else if(rkps -> status == __rkpStream_sniffing_uaEnd) + { + if(debug) + printk("\t\tsniffing_uaEnd\n"); + __rkpStream_scan(rkps, rkpp); + if(debug) + { + if(rkps -> scan_status == __rkpStream_scan_noFound) + printk("\t\tnoFound\n"); + else if(rkps -> scan_status == __rkpStream_scan_uaBegin) + printk("\t\tuaBegin\n"); + else if(rkps -> scan_status == __rkpStream_scan_uaRealBegin) + printk("\t\tuaRealBegin\n"); + else if(rkps -> scan_status == __rkpStream_scan_uaEnd) + printk("\t\tuaEnd\n"); + else if(rkps -> scan_status == __rkpStream_scan_uaGood) + printk("\t\tuaGood\n"); + else if(rkps -> scan_status == __rkpStream_scan_headEnd) + printk("\t\theadEnd\n"); + if(rkpPacket_psh(rkpp)) + printk("\t\tpsh\n"); + } + if(!rkpPacket_psh(rkpp)) + switch (rkps -> scan_status) + { + case __rkpStream_scan_uaBegin: + case __rkpStream_scan_uaRealBegin: + if(rkpPacket_num(&rkps -> buff_scan) + 1 == len_ua) + { + printk("warning: len_ua may be too short.\n"); + __rkpStream_reset(rkps); + rkpPacket_sendl(&rkps -> buff_scan); + rkps -> status = __rkpStream_waiting; + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + } + else + { + rkpPacket_insert_end(&rkps -> buff_scan, rkpp); + rtn = NF_STOLEN; + } + break; + case __rkpStream_scan_uaEnd: + rkpMap_insert_end(&rkps -> map, rkpMap_new(rkps -> scan_uaBegin_seq, rkps -> scan_uaEnd_seq)); + rkpMap_modify(&rkps -> map, &rkps -> buff_scan); + rkpMap_modify(&rkps -> map, &rkpp); + __rkpStream_reset(rkps); + rkpPacket_sendl(&rkps -> buff_scan); + rkps -> status = __rkpStream_waiting; + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + break; + case __rkpStream_scan_uaGood: + __rkpStream_reset(rkps); + rkpPacket_sendl(&rkps -> buff_scan); + rkps -> status = __rkpStream_waiting; + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + break; + case __rkpStream_scan_noFound: + case __rkpStream_scan_headEnd: + break; + } + else + switch (rkps -> scan_status) + { + case __rkpStream_scan_uaBegin: + case __rkpStream_scan_uaRealBegin: + case __rkpStream_scan_uaGood: + __rkpStream_reset(rkps); + rkpPacket_sendl(&rkps -> buff_scan); rkps -> status = __rkpStream_sniffing_uaBegin; rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); rtn = NF_ACCEPT; + break; + case __rkpStream_scan_uaEnd: + rkpMap_insert_end(&rkps -> map, rkpMap_new(rkps -> scan_uaBegin_seq, rkps -> scan_uaEnd_seq)); + rkpMap_modify(&rkps -> map, &rkps -> buff_scan); + rkpMap_modify(&rkps -> map, &rkpp); + __rkpStream_reset(rkps); + rkpPacket_sendl(&rkps -> buff_scan); + rkps -> status = __rkpStream_sniffing_uaBegin; + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + break; + case __rkpStream_scan_noFound: + case __rkpStream_scan_headEnd: + break; } } // else if(rkps -> status == __rkpStream_waiting) @@ -347,7 +352,7 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct rkpPacket* rkpp) { if(debug) printk("\tdrop an disordered packet.\n"); - __rkpStream_pop_begin(rkps, &rkps -> buff_disordered); + rkpPacket_drop(rkpPacket_pop_begin(&rkps -> buff_disordered)); } // 如果序列号过大,结束循环 else if(rkpPacket_seq(rkps -> buff_disordered, rkps -> seq_offset) > __rkpStream_seq_desired(rkps)) @@ -360,7 +365,7 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct rkpPacket* rkpp) unsigned rtn; if(debug) printk("\texecute a disordered packet.\n"); - rkpp2 = __rkpStream_pop_begin(rkps, &rkps -> buff_disordered); + rkpp2 = rkpPacket_pop_begin(&rkps -> buff_disordered); rtn = rkpStream_execute(rkps, rkpp2); if(debug) { @@ -394,34 +399,50 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct rkpPacket* rkpp) int32_t __rkpStream_seq_desired(const struct rkpStream* rkps) { + if(debug) + printk("rkpStream_seq_desired\n"); struct rkpPacket* rkpp = rkps -> buff_scan; if(rkpp == 0) return 0; else - for(; ; rkpp = rkpp -> next) - if(rkpp -> next == 0) - return rkpPacket_seq(rkpp, rkps -> seq_offset) + rkpPacket_appLen(rkpp); - + { + for(; rkpp -> next != 0; rkpp = rkpp -> next); + return rkpPacket_seq(rkpp, rkps -> seq_offset) + rkpPacket_appLen(rkpp); + } } void __rkpStream_scan(struct rkpStream* rkps, struct rkpPacket* rkpp) { - unsigned char* p; - // 需要匹配的量包括:headEnd、uaBegin、uaEnd。分为两个阶段。 - // 第一个阶段是 uaBegin 没有匹配完的阶段,这时尝试匹配 uaBegin 和 headEnd。 - // 如果匹配完 headEnd,不进入下一阶段而结束;如果匹配完 uaBegin,进入下一阶段,这一阶段只匹配 uaEnd - for(p = rkpPacket_appBegin(rkpp); p != rkpPacket_appEnd(rkpp); p++) - { - if(rkps -> scan_uaBegin_matched < strlen(str_uaBegin)) + unsigned char* p = rkpPacket_appBegin(rkpp); + if(debug) + printk("rkpStream_scan\n"); + + // 需要匹配的字符串包括:headEnd、uaBegin、uaEnd、uaPreserve + // 开始这个函数时,scan_status 只可能是 noFound、uaBegin 或 uaRealBegin(这两个可以无差别对待) + // * noFound:扫描 uaBegin、headEnd,当匹配到其中一个时停下来开始决策 + // * uaBegin:如果已经到数据包末尾,则将状态设置为 uaBegin,写入 scan_uaBegin_seq,返回;否则,将状态设置为 uaRealBegin,写入 scan_uaBegin_seq,继续下个阶段的扫描 + // * headEnd:将状态设置为 headEnd,返回 + // * uaBegin 或 uaRealBegin:扫描 uaEnd、uaPreserve,匹配到其中一个时停下来开始决策 + // * uaEnd:将状态设置为 uaEnd,设置 scan_uaEnd_seq,返回 + // * uaPreserve:将状态设置为 uaGood,返回 + + if(rkps -> scan_status == __rkpStream_scan_noFound) + for(; p != rkpPacket_appEnd(rkpp); p++) { if(*p == str_uaBegin[rkps -> scan_uaBegin_matched]) { rkps -> scan_uaBegin_matched++; if(rkps -> scan_uaBegin_matched == strlen(str_uaBegin)) { - if(p + 1 != rkpPacket_appEnd(rkpp)) - rkps -> scan_uaBegin_p = p + 1; - continue; + if(p + 1 == rkpPacket_appEnd(rkpp)) + rkps -> scan_status = __rkpStream_scan_uaBegin; + else + rkps -> scan_status = __rkpStream_scan_uaRealBegin; + rkps -> scan_uaBegin_seq = rkpPacket_seq(rkpp, 0) + ((p + 1) - rkpPacket_appBegin(rkpp)); + if(debug) + printk("uaBegin_seq %u\n", rkps -> scan_uaBegin_seq); + p++; + break; } } else @@ -430,120 +451,54 @@ void __rkpStream_scan(struct rkpStream* rkps, struct rkpPacket* rkpp) { rkps -> scan_headEnd_matched++; if(rkps -> scan_headEnd_matched == strlen(str_headEnd)) + { + rkps -> scan_status = __rkpStream_scan_headEnd; return; + } } else rkps -> scan_headEnd_matched = 0; } - else + + if(rkps -> scan_status == __rkpStream_scan_uaBegin || rkps -> scan_status == __rkpStream_scan_uaRealBegin) + for(; p != rkpPacket_appEnd(rkpp); p++) { + unsigned i; if(*p == str_uaEnd[rkps -> scan_uaEnd_matched]) { rkps -> scan_uaEnd_matched++; if(rkps -> scan_uaEnd_matched == strlen(str_uaEnd)) { - int offset = p + 1 - rkpPacket_appBegin(rkpp); - // str_uaEnd 的末尾在现在的包中的偏移。如果小于等于 str_uaEnd 的长度,说明 ua 的实际结尾在上一个数据包;否则,在这个数据包。 - if(offset <= strlen(str_uaEnd)) - { - struct rkpPacket* i = rkps -> buff_scan; - while(i -> next != 0) - i = i -> next; - rkps -> scan_uaEnd_p = rkpPacket_appEnd(i) - (strlen(str_uaEnd) - offset); - } - else - rkps -> scan_uaEnd_p = p + 1 - strlen(str_uaEnd); + rkps -> scan_status = __rkpStream_scan_uaEnd; + rkps -> scan_uaEnd_seq = rkpPacket_seq(rkpp, 0) + ((p + 1) - rkpPacket_appBegin(rkpp)) - strlen(str_uaEnd); + if(debug) + printk("uaEnd_seq %u\n", rkps -> scan_uaEnd_seq); return; } } else rkps -> scan_uaEnd_matched = 0; + for(i = 0; i < n_str_preserve; i++) + { + if(*p == str_preserve[i][rkps -> scan_uaPreserve_matched[i]]) + { + rkps -> scan_uaPreserve_matched[i]++; + if(rkps -> scan_uaPreserve_matched[i] == strlen(str_preserve[i])) + { + rkps -> scan_status = __rkpStream_scan_uaGood; + return; + } + } + else + rkps -> scan_uaPreserve_matched[i] = 0; + } } - } } void __rkpStream_reset(struct rkpStream* rkps) { - struct rkpPacket* i; + if(debug) + printk("rkpStream_reset\n"); + rkps -> scan_status = __rkpStream_scan_noFound; rkps -> scan_headEnd_matched = rkps -> scan_uaBegin_matched = rkps -> scan_uaEnd_matched = 0; - rkps -> scan_uaBegin_p = rkps -> scan_uaEnd_p = 0; - for(i = rkps -> buff_scan; i != 0;) - { - struct rkpPacket* j = i -> next; - rkpPacket_send(i); - i = j; - } - rkps -> buff_scan = 0; -} -void __rkpStream_modify(struct rkpStream* rkps) -{ - unsigned char* p; - struct rkpPacket* rkpp; - unsigned replaced; - - // 匹配需要保留的 ua - if(n_str_preserve > 0) - { - unsigned* keyword_matched = (unsigned*)rkpMalloc(n_str_preserve * sizeof(unsigned)); - memset(keyword_matched, 0, n_str_preserve * sizeof(unsigned)); - p = rkps -> scan_uaBegin_p; - rkpp = rkps -> buff_scan; - while(p != rkps -> scan_uaEnd_p) - { - unsigned i; - for(i = 0; i < n_str_preserve; i++) - { - if(*p == str_preserve[i][keyword_matched[i]]) - keyword_matched[i]++; - else - keyword_matched[i] = 0; - if(keyword_matched[i] == strlen(str_preserve[i])) - { - rkpFree(keyword_matched); - return; - } - } - p++; - if(p == rkpPacket_appEnd(rkpp)) - { - rkpp = rkpp -> next; - if(rkpp == 0) - break; - else - p = rkpPacket_appBegin(rkpp); - } - } - rkpFree(keyword_matched); - } - - // 执行到这里,说明不是需要保留的 ua,接下来替换字符串 - p = rkps -> scan_uaBegin_p; - rkpp = rkps -> buff_scan; - replaced = 0; - while(p != rkps -> scan_uaEnd_p) - { - if(replaced < strlen(str_uaRkp)) - { - *p = str_uaRkp[replaced]; - replaced++; - } - else - *p = ' '; - p++; - if(p == rkpPacket_appEnd(rkpp)) - { - rkpp = rkpp -> next; - if(rkpp == 0) - break; - else - p = rkpPacket_appBegin(rkpp); - } - } - - // 计算校验和 - rkpp = rkps -> buff_scan; - while(rkpp != 0) - { - rkpPacket_csum(rkpp); - rkpp = rkpp -> next; - } + memset(rkps -> scan_uaPreserve_matched, 0, sizeof(unsigned) * n_str_preserve); }