diff --git a/.gitignore b/.gitignore index c7d0251..b51b07e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode -*.log \ No newline at end of file +*.log +debug \ No newline at end of file diff --git a/src/common.h b/src/common.h index cb3e8ce..9876445 100644 --- a/src/common.h +++ b/src/common.h @@ -15,10 +15,10 @@ #include #include -const static unsigned char* str_ua_begin = "User-Agent: "; -const static unsigned char* str_ua_end = "\r\n"; -const static unsigned char* str_head_end = "\r\n\r\n"; -static unsigned char str_ua_rkp[16]; +const static unsigned char* str_uaBegin = "User-Agent: "; +const static unsigned char* str_uaEnd = "\r\n"; +const static unsigned char* str_headEnd = "\r\n\r\n"; +static unsigned char str_uaRkp[16]; void* rkpMalloc(unsigned size) { diff --git a/src/rkp-ua.c b/src/rkp-ua.c index 7c958bc..7dde3d7 100644 --- a/src/rkp-ua.c +++ b/src/rkp-ua.c @@ -6,15 +6,11 @@ static struct rkpManager* rkpm; unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { unsigned rtn; - static bool crashed = false; static unsigned n_skb_captured = 0, n_skb_captured_lastPrint = 1; if(!rkpSettings_capture(skb)) return NF_ACCEPT; -#ifdef RKP_DEBUG - printk("hook_function captured a packet.\n"); -#endif rtn = rkpManager_execute(rkpm, skb); n_skb_captured++; @@ -23,9 +19,6 @@ unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct nf_hook_ printk("rkp-ua: Captured %d packets.\n", n_skb_captured); n_skb_captured_lastPrint *= 2; } -#ifdef RKP_DEBUG - printk("hook_function end.\n"); -#endif return rtn; } @@ -35,9 +28,9 @@ static int __init hook_init(void) rkpm = rkpManager_new(); - memcpy(str_ua_rkp, "RKP/", 4); - memcpy(str_ua_rkp + 4, VERSION, 2); - memcpy(str_ua_rkp + 6, ".0", 3); + memcpy(str_uaRkp, "RKP/", 4); + memcpy(str_uaRkp + 4, VERSION, 2); + memcpy(str_uaRkp + 6, ".0", 3); nfho.hook = hook_funcion; nfho.pf = NFPROTO_IPV4; @@ -52,12 +45,12 @@ static int __init hook_init(void) printk("rkp-ua: Started, version %s\n", VERSION); printk("rkp-ua: nf_register_hook returnd %d.\n", ret); - printk("rkp-ua: autocapture=%c, mark_capture=0x%x, mark_first=0x%x.\n", - 'n' + autocapture * ('y' - 'n'), mark_capture, mark_first); + printk("rkp-ua: autocapture=%c, mark_capture=0x%x\n", + 'n' + autocapture * ('y' - 'n'), mark_capture); printk("rkp-ua: str_preserve: %d\n", n_str_preserve); for(ret = 0; ret < n_str_preserve; ret++) printk("\t%s\n", str_preserve[ret]); - printk("str_ua_rkp: %s\n", str_ua_rkp); + printk("str_ua_rkp: %s\n", str_uaRkp); return 0; } diff --git a/src/rkpManager.h b/src/rkpManager.h index f569e2d..564c421 100644 --- a/src/rkpManager.h +++ b/src/rkpManager.h @@ -20,7 +20,7 @@ void __rkpManager_unlock(struct rkpManager*, unsigned long); struct rkpManager* rkpManager_new(void) { - struct rkpManager* rkpm = rkpMalloc(sizeof(struct rkpManager)); + struct rkpManager* rkpm = (struct rkpManager*)rkpMalloc(sizeof(struct rkpManager)); if(rkpm == 0) return 0; memset(rkpm -> data, 0, sizeof(struct rkpStream*) * 256); @@ -57,68 +57,58 @@ int 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; + } __rkpManager_lock(rkpm, &flag); rtn = __rkpManager_execute(rkpm, rkpp); + if(debug) + { + if(rtn == NF_ACCEPT) + printk("returned NF_ACCEPT.\n"); + else if(rtn == NF_DROP) + printk("returned NF_DROP.\n"); + else if(rtn == NF_STOLEN) + printk("returned NF_STOLEN.\n"); + } __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) { -#ifdef RKP_DEBUG - printk("rkp-ua: rkpManager_execute start.\n"); - printk("\tsyn %d\n", rkpPacket_syn(rkpp)); - printk("\tsport %d dport %d\n", rkpPacket_sport(rkpp), rkpPacket_dport(rkpp)); - printk("\tid %d\n", rkpp -> sid); -#endif - struct rkpStream *rkps, *rkps_new; // 搜索是否有符合条件的流 for(rkps = rkpm -> data[rkpp -> sid]; rkps != 0; rkps = rkps -> next) if(rkpStream_belongTo(rkps, rkpp)) // 找到了,执行即可 - { -#ifdef RKP_DEBUG - printk("__rkpManager_execute: found target stream.\n"); -#endif return rkpStream_execute(rkps, rkpp); - } // 如果运行到这里的话,那就是没有找到了,新建一个流再执行 -#ifdef RKP_DEBUG - printk("__rkpManager_execute: target stream not found, create a new one. \n"); -#endif rkps_new = rkpStream_new(rkpp); if(rkps_new == 0) return NF_ACCEPT; if(rkpm -> data[rkpp -> sid] == 0) - { -#ifdef RKP_DEBUG - printk("rkpManager_execute: add a new stream %d to an empty list.\n", id); -#endif rkpm -> data[rkpp -> sid] = rkps_new; - } else { -#ifdef RKP_DEBUG - printk("rkpManager_execute: add a new stream %d to an unempty list.\n", id); -#endif rkpm -> data[rkpp -> sid] -> prev = rkps_new; rkps_new -> next = rkpm -> data[rkpp -> sid]; rkpm -> data[rkpp -> sid] = rkps_new; } - return rkpStream_execute(rkps_new, skb); + return rkpStream_execute(rkps_new, rkpp); } void __rkpManager_refresh(unsigned long param) { unsigned i; unsigned long flag; - struct rkpManager*& rkpm = (struct rkpManager*)param; -#ifdef RKP_DEBUG - printk("__rkpManager_refresh start.\n"); -#endif + struct rkpManager* rkpm = (struct rkpManager*)param; __rkpManager_lock(rkpm, &flag); for(i = 0; i < 256; i++) { @@ -145,9 +135,6 @@ void __rkpManager_refresh(unsigned long param) rkpm -> timer.expires = jiffies + time_keepalive * HZ; add_timer(&rkpm -> timer); __rkpManager_unlock(rkpm, flag); -#ifdef RKP_DEBUG - printk("__rkpManager_refresh end.\n"); -#endif } void __rkpManager_lock(struct rkpManager* rkpm, unsigned long* flagp) diff --git a/src/rkpMap.h b/src/rkpMap.h new file mode 100644 index 0000000..20876a3 --- /dev/null +++ b/src/rkpMap.h @@ -0,0 +1,15 @@ +#pragma once +#include "common.h" +#include "rkpPacket.h" + +struct rkpMap +{ + int32_t left, right; + struct rkpMap *prev, *next; +}; + +struct rkpMap* rkpMap_new(int32_t, int32_t); +void rkpMap_delete(int32_t, int32_t); + +unsigned char rkpMap_map(int32_t); +void rkpMap_modify(struct rkpPacket*); diff --git a/src/rkpPacket.h b/src/rkpPacket.h index 4218a27..db02b4d 100644 --- a/src/rkpPacket.h +++ b/src/rkpPacket.h @@ -15,21 +15,34 @@ void rkpPacket_send(struct rkpPacket*); void rkpPacket_delete(struct rkpPacket*); void rkpPacket_drop(struct rkpPacket*); -unsigned char* rkpPacket_appBegin(struct rkpPacket*); -unsigned char* rkpPacket_appEnd(struct rkpPacket*); -unsigned rkpPacket_appLen(struct rkpPacket*); -int32_t rkpPacket_seq(struct rkpPacket*); -int32_t rkpPacket_ack(struct rkpPacket*); -u_int32_t rkpPacket_sip(struct rkpPacket*); -u_int32_t rkpPacket_dip(struct rkpPacket*); -u_int32_t rkpPacket_sport(struct rkpPacket*); -u_int32_t rkpPacket_dport(struct rkpPacket*); -bool rkpPacket_psh(struct rkpPacket*); -bool rkpPacket_syn(struct rkpPacket*); +unsigned char* rkpPacket_appBegin(const struct rkpPacket*); +unsigned char* rkpPacket_appEnd(const struct rkpPacket*); +unsigned rkpPacket_appLen(const struct rkpPacket*); +int32_t rkpPacket_seq(const struct rkpPacket*, const int32_t); +int32_t rkpPacket_ack(const struct rkpPacket*, const int32_t); +u_int32_t rkpPacket_sip(const struct rkpPacket*); +u_int32_t rkpPacket_dip(const struct rkpPacket*); +u_int16_t rkpPacket_sport(const struct rkpPacket*); +u_int16_t rkpPacket_dport(const struct rkpPacket*); +bool rkpPacket_psh(const struct rkpPacket*); +bool rkpPacket_syn(const struct rkpPacket*); void rkpPacket_csum(struct rkpPacket*); bool __rkpPacket_makeWriteable(struct rkpPacket*); +void rkpPacket_makeOffset(const struct rkpPacket*, int32_t*); + +void rkpPacket_insert_auto(struct rkpPacket**, struct rkpPacket*, int32_t offset); // 在指定链表中插入一个包,自动根据序列号确定插入的位置 +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*); // 返回指定链表中包的数目 + +void rkpPacket_sendl(struct rkpPacket**); +void rkpPacket_deletel(struct rkpPacket**); +void rkpPacket_dropl(struct rkpPacket**); + struct rkpPacket* rkpPacket_new(struct sk_buff* skb) { struct rkpPacket* rkpp = rkpMalloc(sizeof(struct rkpPacket)); @@ -46,7 +59,7 @@ struct rkpPacket* rkpPacket_new(struct sk_buff* skb) rkpFree(rkpp); return 0; } - return p; + return rkpp; } void rkpPacket_send(struct rkpPacket* p) { @@ -67,60 +80,60 @@ void rkpPacket_drop(struct rkpPacket* p) rkpFree(p); } -unsigned char* rkpPacket_appBegin(struct rkpPacket* p) +unsigned char* rkpPacket_appBegin(const struct rkpPacket* p) { return ((unsigned char*)tcp_hdr(p -> skb)) + tcp_hdr(p -> skb) -> doff * 4; } -unsigned char* rkpPacket_appEnd(struct rkpPacket* p) +unsigned char* rkpPacket_appEnd(const struct rkpPacket* p) { return ((unsigned char*)ip_hdr(p -> skb)) + ntohs(ip_hdr(p -> skb) -> tot_len); } -unsigned rkpPacket_appLen(struct rkpPacket* p) +unsigned rkpPacket_appLen(const struct rkpPacket* p) { return ntohs(ip_hdr(p -> skb) -> tot_len) - ip_hdr(p -> skb) -> ihl * 4 - tcp_hdr(p -> skb) -> doff * 4; } -int32_t rkpPacket_seq(struct rkpPacket* p) +int32_t rkpPacket_seq(const struct rkpPacket* p, const int32_t offset) { - return ntohl(tcp_hdr(p -> skb) -> seq); + return (int32_t)ntohl(tcp_hdr(p -> skb) -> seq) - offset; } -int32_t rkpPacket_ack(struct rkpPacket* p) +int32_t rkpPacket_ack(const struct rkpPacket* p, const int32_t offset) { - return ntohl(tcp_hdr(p -> skb) -> ack); + return (int32_t)ntohl(tcp_hdr(p -> skb) -> ack) - offset; } -u_int32_t rkpPacket_sip(struct rkpPacket* rkpp) +u_int32_t rkpPacket_sip(const struct rkpPacket* rkpp) { return ntohl(ip_hdr(rkpp -> skb) -> saddr); } -u_int32_t rkpPacket_dip(struct rkpPacket* rkpp) +u_int32_t rkpPacket_dip(const struct rkpPacket* rkpp) { return ntohl(ip_hdr(rkpp -> skb) -> daddr); } -u_int16_t rkpPacket_sport(struct rkpPacket* rkpp) +u_int16_t rkpPacket_sport(const struct rkpPacket* rkpp) { return ntohs(tcp_hdr(rkpp -> skb) -> source); } -u_int32_t rkpPacket_dport(struct rkpPacket* rkpp) +u_int16_t rkpPacket_dport(const struct rkpPacket* rkpp) { return ntohs(tcp_hdr(rkpp -> skb) -> dest); } -bool rkpPacket_psh(struct rkpPacket* rkpp) +bool rkpPacket_psh(const struct rkpPacket* rkpp) { return tcp_hdr(rkpp -> skb) -> psh; } -bool rkpPacket_syn(struct rkpPacket* rkpp) +bool rkpPacket_syn(const struct rkpPacket* rkpp) { return tcp_hdr(rkpp -> skb) -> syn; } -void rkpPacket_csum(struct rkpPacket* p) +void rkpPacket_csum(struct rkpPacket* rkpp) { - struct iphdr* iph = ip_hdr(p -> skb); - struct tcphdr* tcph = tcp_hdr(p -> skb); + struct iphdr* iph = ip_hdr(rkpp -> skb); + struct tcphdr* tcph = tcp_hdr(rkpp -> skb); tcph -> check = 0; iph -> check = 0; iph -> check = ip_fast_csum((unsigned char*)iph, iph -> ihl); - p -> skb -> csum = skb_checksum(p -> skb, iph -> ihl * 4, ntohs(iph -> tot_len) - iph -> ihl * 4, 0); - tcph -> check = csum_tcpudp_magic(iph -> saddr, iph -> daddr, ntohs(iph -> tot_len) - iph -> ihl * 4, IPPROTO_TCP, p -> skb -> csum); + rkpp -> skb -> csum = skb_checksum(rkpp -> skb, iph -> ihl * 4, ntohs(iph -> tot_len) - iph -> ihl * 4, 0); + tcph -> check = csum_tcpudp_magic(iph -> saddr, iph -> daddr, ntohs(iph -> tot_len) - iph -> ihl * 4, IPPROTO_TCP, rkpp -> skb -> csum); } bool __rkpPacket_makeWriteable(struct rkpPacket* rkpp) @@ -135,4 +148,142 @@ bool __rkpPacket_makeWriteable(struct rkpPacket* rkpp) return false; } return true; +} + +void rkpPacket_makeOffset(const struct rkpPacket* rkpp, int32_t* offsetp) +{ + *offsetp = rkpPacket_seq(rkpp, 0) + rkpPacket_appLen(rkpp); +} + +void rkpPacket_insert_auto(struct rkpPacket** buff, struct rkpPacket* rkpp, int32_t offset) +{ + // 如果链表是空的,那么就直接加进去 + 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 的包,插入到它的后面。 + else + { + struct rkpPacket* rkpp2 = *buff; + while(rkpp2 -> next != 0 && rkpPacket_seq(rkpp2 -> next, offset) < rkpPacket_seq(rkpp, offset)) + rkpp2 = rkpp2 -> next; + rkpp -> next = rkpp2 -> next; + rkpp -> prev = rkpp2; + if(rkpp -> next != 0) + rkpp -> next -> prev = rkpp; + rkpp2 -> next = rkpp; + } +} +void rkpPacket_insert_begin(struct rkpPacket** buff, struct rkpPacket* rkpp) +{ + if(*buff == 0) + { + *buff = rkpp; + rkpp -> next = rkpp -> prev = 0; + } + else + { + (*buff) -> prev = rkpp; + rkpp -> next = *buff; + *buff = 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; + while(rkpp2 -> next != 0) + rkpp2 = rkpp2 -> next; + rkpp2 -> next = rkpp; + rkpp -> prev = rkpp2; + rkpp -> next = 0; + } +} +struct rkpPacket* rkpPacket_pop_begin(struct rkpPacket** buff) +{ + struct rkpPacket* rkpp = *buff; + if(rkpp -> next == 0) + *buff = 0; + else + { + *buff = rkpp -> next; + rkpp -> next = 0; + (*buff) -> prev = 0; + } + return rkpp; +} +struct rkpPacket* rkpPacket_pop_end(struct rkpPacket** buff) +{ + struct rkpPacket* rkpp = *buff; + while(rkpp -> next != 0) + rkpp = rkpp -> next; + if(rkpp == *buff) + *buff = 0; + else + { + rkpp -> prev -> next = 0; + rkpp -> prev = 0; + } + return rkpp; +} +unsigned rkpPacket_num(const struct rkpPacket* buff) +{ + unsigned n = 0; + const struct rkpPacket* rkpp = buff; + while(rkpp != 0) + { + rkpp = rkpp -> next; + n++; + } + return n; +} + +void rkpPacket_sendl(struct rkpPacket** rkppl) +{ + struct rkpPacket *rkpp = *rkppl, *rkpp2; + while(rkpp != 0) + { + rkpp2 = rkpp -> next; + rkpPacket_send(rkpp); + rkpp = rkpp2; + } + *rkppl = 0; +} +void rkpPacket_deletel(struct rkpPacket** rkppl) +{ + struct rkpPacket *rkpp = *rkppl, *rkpp2; + while(rkpp != 0) + { + rkpp2 = rkpp -> next; + rkpPacket_delete(rkpp); + rkpp = rkpp2; + } + *rkppl = 0; +} +void rkpPacket_dropl(struct rkpPacket** rkppl) +{ + struct rkpPacket *rkpp = *rkppl, *rkpp2; + while(rkpp != 0) + { + rkpp2 = rkpp -> next; + rkpPacket_drop(rkpp); + rkpp = rkpp2; + } + *rkppl = 0; } \ No newline at end of file diff --git a/src/rkpSettings.h b/src/rkpSettings.h index f7c712a..65bf8c5 100644 --- a/src/rkpSettings.h +++ b/src/rkpSettings.h @@ -17,6 +17,8 @@ static unsigned len_ua = 2; module_param(len_ua, uint, 0); static bool verbose = false; module_param(verbose, bool, 0); +static bool debug = false; +module_param(debug, bool, 0); bool rkpSettings_capture(const struct sk_buff*); diff --git a/src/rkpStream.h b/src/rkpStream.h index 8181454..e60a3c7 100644 --- a/src/rkpStream.h +++ b/src/rkpStream.h @@ -7,54 +7,55 @@ struct rkpStream { enum { - __rkpStream_sniffing_uaBegin, // 正在寻找 http 头的结尾或者 ua 的开始,这时 buff_scan 中不应该有包 - __rkpStream_sniffing_uaEnd, // 已经找到 ua,正在寻找它的结尾,buff_scan 中可能有包 - __rkpStream_waiting // 已经找到 ua 的结尾或者 http 头的结尾并且还没有 psh,接下来的包都直接放行 + __rkpStream_sniffing_uaBegin, // 正在寻找 http 头的结尾或者 ua 的开始,这时 buff_scan 中不应该有包 + __rkpStream_sniffing_uaEnd, // 已经找到 ua,正在寻找它的结尾,buff_scan 中可能有包 + __rkpStream_waiting // 已经找到 ua 的结尾或者 http 头的结尾并且还没有 psh,接下来的包都直接放行 } status; - u_int32_t id[3]; // 按顺序存储客户地址、服务地址、客户端口、服务端口,已经转换字节序 + u_int32_t id[3]; // 按顺序存储客户地址、服务地址、客户端口、服务端口,已经转换字节序 struct rkpPacket *buff_scan, *buff_disordered; // 分别存储准备扫描的、因乱序而提前收到的数据包,都按照序号排好了 - u_int32_t seq_offset; // 序列号的偏移。使得 buff_scan 中第一个字节的编号为零。 - bool active; // 是否仍然活动,超过一定时间不活动的流会被销毁 - unsigned scan_httpEnd_matched, scan_uaBegin_matched, scan_uaEnd_matched; // 记录现在已经匹配了多少个字节,由 __rkpStream_scan 设置 - unsigned char *scan_uaBegin_p, *scan_uaEnd_p; // 在扫描到相关信息后,将信息填写到这里 + int32_t seq_offset; // 序列号的偏移。使得 buff_scan 中第一个字节的编号为零。 + 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 rkpStream *prev, *next; }; -struct rkpStream* rkpStream_new(const struct rkpPacket*); // 构造一个 rkpSteam +struct rkpStream* rkpStream_new(const struct rkpPacket*); void rkpStream_delete(struct rkpStream*); bool rkpStream_belongTo(const struct rkpStream*, const struct rkpPacket*); // 判断一个数据包是否属于一个流 -unsigned rkpStream_execute(struct rkpStream*, struct rkpPacket*); // 已知一个数据包属于这个流后,处理这个数据包 +unsigned rkpStream_execute(struct rkpStream*, struct rkpPacket*); // 已知一个数据包属于这个流后,处理这个数据包 -int32_t __rkpStream_seq_scanEnd(struct rkpStream*); // 返回 buff_scan 中最后一个数据包的后继的第一个字节的序列号 +int32_t __rkpStream_seq_desired(const struct rkpStream*); // 返回 buff_scan 中最后一个数据包的后继的第一个字节的相对序列号 -void __rkpStream_insert_auto(struct rkpStream*, struct rkpPacket**, struct rkpPacket*); // 在指定链表中插入一个节点 -void __rkpStream_insert_end(struct rkpStream*, struct rkpPacket**, struct rkpPacket*); - -bool __rkpStream_scan(struct rkpStream*, struct rkpPacket*); // 对一个最新的包进行扫描 +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 = rkpMalloc(sizeof(struct rkpStream)); + struct rkpStream* rkps; + if(debug) + printk("rkpStream_new\n"); + rkps = (struct rkpStream*)rkpMalloc(sizeof(struct rkpStream)); if(rkps == 0) return 0; 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 = ntohl(tcp_hdr(skb) -> seq); + rkps -> seq_offset = rkpPacket_seq(rkpp, 0); rkps -> active = true; - rkps -> scan_httpEnd_matched = rkps -> scan_uaBegin_matched = rkps -> scan_uaEnd_matched = 0; + rkps -> scan_headEnd_matched = rkps -> scan_uaBegin_matched = rkps -> scan_uaEnd_matched = 0; rkps -> scan_uaBegin_p = rkps -> scan_uaEnd_p = 0; rkps -> prev = rkps -> next = 0; - if(verbose) - printk("rkpStream_new\n"); return rkps; } void rkpStream_delete(struct rkpStream* rkps) { struct rkpPacket* rkpp; - for(rkpp = rkps -> buff_scan; p != 0;) + if(debug) + printk("rkpStream_delete\n"); + for(rkpp = rkps -> buff_scan; rkpp != 0;) { struct rkpPacket* rkpp2 = rkpp; rkpp = rkpp -> next; @@ -67,8 +68,6 @@ void rkpStream_delete(struct rkpStream* rkps) rkpPacket_drop(rkpp2); } rkpFree(rkps); - if(verbose) - printk("rkpStream_delete\n"); } bool rkpStream_belongTo(const struct rkpStream* rkps, const struct rkpPacket* rkpp) @@ -79,208 +78,329 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct rkpPacket* rkpp) // 不要害怕麻烦,咱们把每一种情况都慢慢写一遍。 // 以下假定:包是客户端发到服务端的,并且带有应用层数据 { - if(verbose) + if(debug) printk("rkp-ua: rkpStream_execute start, judging...\n"); - // 肯定需要更新时间 + // 肯定需要更新活动情况 rkps -> active = true; // 接下来从小到大考虑数据包的序列号的几种情况 // 已经发出的数据包,直接忽略 - if(rkpPacket_seq(rkpp) - rkps -> seq_offset < 0) + if(rkpPacket_seq(rkpp, rkps -> seq_offset) < 0) { - if(verbose) + 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"); return NF_ACCEPT; } // 已经放到 buff_scan 中的数据包,丢弃 - if(rkpPacket_seq(rkpp) - rkps -> seq_offset < __rkpStream_seq_scanEnd(rkps)) + if(rkpPacket_seq(rkpp, rkps -> seq_offset) < __rkpStream_seq_desired(rkps)) { - if(verbose) + if(debug) printk("\tThe packet with same seq has been captured, return NF_DROP.\n"); return NF_DROP; } // 恰好是 buff_scan 的后继数据包,这种情况比较麻烦,写到最后 // 乱序导致还没接收到前继的数据包,放到 buff_disordered - if(rkpPacket_seq(rkpp) - rkps -> seq_offset > __rkpStream_seq_scanEnd(rkps)) + if(rkpPacket_seq(rkpp, rkps -> seq_offset) > __rkpStream_seq_desired(rkps)) { - if(verbose) + if(debug) printk("\tThe packet is disordered, return NF_STOLEN.\n"); - Stream_insert_auto(rkps, &(rkps -> buff_disordered), rkpp); + __rkpStream_insert_auto(rkps, &rkps -> buff_disordered, rkpp); return NF_STOLEN; } // 接下来是恰好是 buff_scan 的后继数据包的情况,先分状态讨论,再一起考虑 buff_disordered 中的包 - if(rkpPacket_seq(p) - rkps -> seq_offset == __rkpStream_seq_scanEnd(rkps)) + // if(rkpPacket_seq(rkpp, rkps -> seq_offset) == __rkpStream_seq_desired(rkps)) + if(true) { // 因为一会儿可能还需要统一考虑 buff_disordered 中的包,因此不直接 return,将需要的返回值写到这里,最后再 return unsigned rtn; + if(debug) + printk("\tThe packet is desired one, further judging.\n"); + // 接下来分析几种情况 - // * sniffing_uaBegin 状态下,先扫描这个数据包,再看情况处理,因此不再单独写出。 + // * sniffing_uaBegin 状态下,先扫描这个数据包,再看情况处理 // 需要考虑的方面有: - // * 是否扫描到了 uaBgin,通过 uaBegin_matched 是否与 str_uaBgin 长度相等判断 - // * 在扫描到了 uaBgin 的前提下,是否扫描到了 uaEnd,通过 uaEnd_matched 是否与 str_uaEnd 长度相等判断 - // * 在扫描到了 uaBgin 的前提下,是否得到了 ua 的开头位置。这是因为,可能一个数据包的结尾恰好是 `User-Agent: `,结果扫描到了 uaBegin 但是 ua 的开头在下一个数据包。通过 uaBegin_p 是否为非零值判断 - // * 是否扫描到了 headEnd,这三个通过对比 matched 来确定,通过 headEnd_matched 是否与 str_headEnd 长度相等判断 + // * 是否扫描到了 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、,没有 psh。状态切换为 sniffing_uaEnd,更新 seq_offset,返回 NF_ACCEPT; - // 3. 扫描到了 uaBegin、uaEnd,没有 psh - // * sniffing 状态下,没有读到 http 头的结尾,但是有设置 psh - // * waiting 状态下 + // 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。 + // * waiting 状态下,如果有 psh,则将状态切换为 sniffing_uaBegin,否则不切换;然后更新 seq_offset,返回 NF_ACCEPT 即可。 -#ifdef RKP_DEBUG - printk("\tdesired packet judged.\n"); - rkpPacket_makeWriteable(p); - unsigned char* temp = rkpMalloc((rkpPacket_appLen(p) + 1) * sizeof(unsigned char)); - memcpy(temp, rkpPacket_appBegin(p), rkpPacket_appLen(p)); - temp[rkpPacket_appLen(p)] = 0; - printk("\tcontent length: %d\n", rkpPacket_appLen(p)); - printk("\tpacket content: %s\n", temp); - // printk("\tpacket content in int:"); - // for(rtn = 0; rtn < rkpPacket_appLen(p); rtn++) - // printk("%d\n", rkpPacket_appBegin(p)[rtn]); - rtn = NF_STOLEN; - printk("\n"); - rkpFree(temp); -#endif - // 如果是在 sniffing 的情况下,那一定先丢到 buff_scan 里,然后扫描一下看结果 - if(rkps -> status == __rkpStream_sniffing) + if(rkps -> status == __rkpStream_sniffing_uaBegin) { -#ifdef RKP_DEBUG - printk("\t\tsniffing.\n"); -#endif - // 作任何应用层的读取和写入之前,都需要 writeable,而只有这种情况需要做。 - rkpPacket_makeWriteable(p); - // 丢到 buff_scan 里,记得一会儿如果要 accept,还要拿出来,以及更新序列号 - __rkpStream_insert_end(rkps, &rkps -> buff_scan, p); - if(__rkpStream_scan(rkps, p)) // 扫描到了 http 头的结尾 + if(debug) + printk("\t\tsniffing_uaBegin\n"); + __rkpStream_scan(rkps, rkpp); + if(debug) { -#ifdef RKP_DEBUG - printk("\t\t\thttp head end matched.\n"); -#endif - // 替换 ua - __rkpStream_modify(rkps); - // 发出数据包,注意最后一个不发,等会儿 accept 就好 - struct rkpPacket* p2; - for(p2 = rkps -> buff_scan; p2 != 0 && p2 -> next != 0;) - { - struct rkpPacket* p3 = p2; - p2 = p2 -> next; - // rkps -> seq_offset = rkpPacket_seq(p2) + rkpPacket_appLen(p2); 不需要更新偏移,因为最后一个包等会儿 accept 的时候会更新 - rkpPacket_send(p2); - } - // 如果没有 psh,设定状态为等待 - if(!rkpPacket_psh(p)) - rkps -> status = __rkpStream_waiting; - // 将最后一个包再拿出来,将链表清空,更新偏移,以及把用不到的删掉 - rkps -> buff_scan = 0; - p -> prev = 0; - rkps -> seq_offset = rkpPacket_seq(p) + rkpPacket_appLen(p); - rkpPacket_delete(p); - // accept - rtn = NF_ACCEPT; + 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"); } - // 没有扫描到但是有 psh,同样要全部发出并 accept - else if(rkpPacket_psh(p)) - { -#ifdef RKP_DEBUG - printk("rkp-ua: rkpStream_execute: psh found before http head end.\n"); -#endif - // 发出数据包,注意最后一个不发,等会儿 accept 就好 - struct rkpPacket* p2; - for(p2 = rkps -> buff_scan; p2 != 0 && p2 -> next != 0;) - { - struct rkpPacket* p3 = p2; - p2 = p2 -> next; - // rkps -> seq_offset = rkpPacket_seq(p2) + rkpPacket_appLen(p2); 不需要更新偏移,因为最后一个包等会儿 accept 的时候会更新 - rkpPacket_send(p2); - } - // 将最后一个包再拿出来,将链表清空,更新偏移,以及把用不到的删掉 - rkps -> buff_scan = 0; - p -> prev = 0; - rkps -> seq_offset = rkpPacket_seq(p) + rkpPacket_appLen(p); - rkpPacket_delete(p); - // accept - rtn = NF_ACCEPT; - } - // 没有扫描到也没有 psh,偷走就好了,不需要任何操作 + 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) { -#ifdef RKP_DEBUG - printk("rkp-ua: rkpStream_execute: head end not found.\n"); -#endif + 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"); } - } - else // waiting 的状态,检查 psh、设置序列号偏移、然后放行就可以了 - { -#ifdef RKP_DEBUG - printk("\t\twaiting.\n"); -#endif - rkps -> seq_offset = rkpPacket_seq(p) + rkpPacket_appLen(p); - if(rkpPacket_psh(p)) - rkps -> status = __rkpStream_sniffing; - rkpPacket_delete(p); - rtn = NF_ACCEPT; - } - - // 考虑 buff_disordered - while(rkps -> buff_disordered != 0) - { - if(rkpPacket_seq(rkps -> buff_disordered) - rkps -> seq_offset < __rkpStream_seq_scanEnd(rkps)) - // 序列号是已经发出去的,丢弃 - { - if(rkps -> buff_disordered -> next == 0) + 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)) { - rkpPacket_drop(rkps -> buff_disordered); - rkps -> buff_disordered = 0; + __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 { - rkps -> buff_disordered = rkps -> buff_disordered -> next; - rkpPacket_drop(rkps -> buff_disordered -> prev); - rkps -> buff_disordered -> prev = 0; + __rkpStream_insert_end(rkps, &rkps -> buff_scan, rkpp); + __rkpStream_modify(rkps); + __rkpStream_pop_end(rkps, &rkps -> buff_scan); + __rkpStream_reset(rkps); + rkps -> status = __rkpStream_sniffing_uaBegin; + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; } + } + // else if(rkps -> status == __rkpStream_waiting) + else + { + if(debug) + { + printk("\t\tsniffing_uaBegin\n"); + if(rkpPacket_psh(rkpp)) + printk("\t\tpsh.\n"); + } + if(rkpPacket_psh(rkpp)) + rkps -> status = __rkpStream_sniffing_uaBegin; + rkpPacket_makeOffset(rkpp, &rkps -> seq_offset); + rtn = NF_ACCEPT; + } + + // 接下来考虑乱序的包 + while(rkps -> buff_disordered != 0) + { + // 序列号是已经发出去的,丢弃 + if(rkpPacket_seq(rkps -> buff_disordered, rkps -> seq_offset) < __rkpStream_seq_desired(rkps)) + { + if(debug) + printk("\tdrop an disordered packet.\n"); + __rkpStream_pop_begin(rkps, &rkps -> buff_disordered); } // 如果序列号过大,结束循环 - else if(rkpPacket_seq(rkps -> buff_disordered) - rkps -> seq_offset > __rkpStream_seq_scanEnd(rkps)) + else if(rkpPacket_seq(rkps -> buff_disordered, rkps -> seq_offset) > __rkpStream_seq_desired(rkps)) break; // 如果序列号恰好,把它从链表中取出,然后像刚刚抓到的包那样去执行 else { // 将包从链表中取出 - struct rkpPacket* p2 = rkps -> buff_disordered; - if(rkps -> buff_disordered -> next == 0) - rkps -> buff_disordered = 0; - else + struct rkpPacket* rkpp2; + unsigned rtn; + if(debug) + printk("\texecute a disordered packet.\n"); + rkpp2 = __rkpStream_pop_begin(rkps, &rkps -> buff_disordered); + rtn = rkpStream_execute(rkps, rkpp2); + if(debug) { - rkps -> buff_disordered = p2 -> next; - rkps -> buff_disordered -> prev = 0; - p2 -> next = 0; + if(rtn == NF_ACCEPT) + printk("\t\treturn NF_ACCEPT.\n"); + else if(rtn == NF_DROP) + printk("\t\treturn NF_DROP.\n"); + else if(rtn == NF_STOLEN) + printk("\t\treturn NF_STOLEN.\n"); } - // 执行 - unsigned rtn = rkpStream_execute(rkps, p2 -> skb); if(rtn == NF_ACCEPT) - rkpPacket_send(p2); + rkpPacket_send(rkpp2); else if(rtn == NF_DROP) - rkpPacket_drop(p2); - else if(rtn == NF_STOLEN) - rkpPacket_delete(p2); + rkpPacket_drop(rkpp2); + else if(rtn == NF_STOLEN); } } + if(debug) + { + if(rtn == NF_ACCEPT) + printk("\treturn NF_ACCEPT.\n"); + else if(rtn == NF_DROP) + printk("\treturn NF_DROP.\n"); + else if(rtn == NF_STOLEN) + printk("\treturn NF_STOLEN.\n"); + } return rtn; } } -int32_t __rkpStream_seq_scanEnd(struct rkpStream* rkps) +int32_t __rkpStream_seq_desired(const struct rkpStream* rkps) { struct rkpPacket* rkpp = rkps -> buff_scan; if(rkpp == 0) @@ -288,253 +408,95 @@ int32_t __rkpStream_seq_scanEnd(struct rkpStream* rkps) else for(; ; rkpp = rkpp -> next) if(rkpp -> next == 0) - return rkpPacket_seq(rkpp) - rkps -> seq_offset + rkpPacket_appLen(rkpp); + return rkpPacket_seq(rkpp, rkps -> seq_offset) + rkpPacket_appLen(rkpp); } -void __rkpStream_insert_auto(struct rkpStream* rkps, struct rkpPacket** buff, struct rkpPacket* p) +void __rkpStream_scan(struct rkpStream* rkps, struct rkpPacket* rkpp) { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_insert_auto start.\n"); -#endif - // 如果链表是空的,那么就直接加进去 - if(*buff == 0) - { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_insert_auto: empty buff.\n"); -#endif - *buff = p; - p -> prev = p -> next = 0; - } - // 又或者,要插入的包需要排到第一个,或者和第一个序列号重复了 - else if(rkpPacket_seq(*buff) - rkps -> seq_offset >= rkpPacket_seq(p) - rkps -> seq_offset) - { - if(rkpPacket_seq(*buff) - rkps -> seq_offset == rkpPacket_seq(p) - rkps -> seq_offset) - { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_insert_auto: same seq. Drop it.\n"); -#endif - rkpPacket_drop(p); - } - else - { - (*buff) -> prev = p; - p -> next = *buff; - p -> prev = 0; - *buff = p; - } - } - // 接下来寻找最后一个序列号不比 p 大的包,插入到它的后面或者丢掉。 - else - { - struct rkpPacket* p2 = *buff; - while(p2 -> next != 0 && rkpPacket_seq(p2 -> next) - rkps -> seq_offset <= rkpPacket_seq(p) - rkps -> seq_offset) - p2 = p2 -> next; - if(rkpPacket_seq(p2) - rkps -> seq_offset == rkpPacket_seq(p) - rkps -> seq_offset) - { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_insert_auto: same seq. Drop it.\n"); -#endif - rkpPacket_drop(p); - } - else - { - p -> next = p2 -> next; - p -> prev = p2; - if(p -> next != 0) - p -> next -> prev = p; - p2 -> next = p; - } - } -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_insert_auto end.\n"); -#endif -} -void __rkpStream_insert_end(struct rkpStream* rkps, struct rkpPacket** buff, struct rkpPacket* p) -{ -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_insert_end start.\n"); -#endif - if(*buff == 0) - { - *buff = p; - p -> next = p -> prev = 0; - } - else - { - struct rkpPacket* p2 = *buff; - while(p2 -> next != 0) - p2 = p2 -> next; - p2 -> next = p; - p -> prev = p2; - p -> next = 0; - } -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_insert_end end.\n"); -#endif -} - -bool __rkpStream_scan(struct rkpStream* rkps, struct rkpPacket* rkpp) -{ -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_scan start.\n"); -#endif unsigned char* p; + // 需要匹配的量包括:headEnd、uaBegin、uaEnd。分为两个阶段。 + // 第一个阶段是 uaBegin 没有匹配完的阶段,这时尝试匹配 uaBegin 和 headEnd。 + // 如果匹配完 headEnd,不进入下一阶段而结束;如果匹配完 uaBegin,进入下一阶段,这一阶段只匹配 uaEnd for(p = rkpPacket_appBegin(rkpp); p != rkpPacket_appEnd(rkpp); p++) { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_scan matching %c.\n", *p); -#endif - if(*p == str_head_end[rkps -> scan_matched]) - rkps -> scan_matched++; - else - rkps -> scan_matched = 0; - if(rkps -> scan_matched == strlen(str_head_end)) + if(rkps -> scan_uaBegin_matched < strlen(str_uaBegin)) { - rkps -> scan_matched = 0; -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_scan: head end found.\n"); - printk("rkp-ua: __rkpStream_scan end.\n"); -#endif - return true; + 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; + } + } + else + rkps -> scan_uaBegin_matched = 0; + if(*p == str_headEnd[rkps -> scan_headEnd_matched]) + { + rkps -> scan_headEnd_matched++; + if(rkps -> scan_headEnd_matched == strlen(str_headEnd)) + return; + } + else + rkps -> scan_headEnd_matched = 0; + } + else + { + 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); + return; + } + } + else + rkps -> scan_uaEnd_matched = 0; } } -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_scan: head end not found.\n"); - printk("rkp-ua: __rkpStream_scan end.\n"); -#endif - return false; +} +void __rkpStream_reset(struct rkpStream* rkps) +{ + struct rkpPacket* i; + 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) { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify start.\n"); -#endif - unsigned ua_begin_matched = 0, ua_end_matched = 0, head_end_matched = 0, *keyword_matched, ua_relplaced = 0; - unsigned char *ua_begin_p, *ua_end_p; - struct rkpPacket *ua_begin_rkpp, *ua_end_rkpp, *rkpp = rkps -> buff_scan; + unsigned char* p; + struct rkpPacket* rkpp; + unsigned replaced; - // 匹配 "User-Agent: " 的阶段 -#ifdef RKP_DEBUG - printk("matching User-Agent: \n"); -#endif - for(;rkpp != 0 && ua_begin_matched != strlen(str_ua_begin); rkpp = rkpp -> next) - { - unsigned char* p; - for(p = rkpPacket_appBegin(rkpp); p != rkpPacket_appEnd(rkpp); p++) - { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: matching %c.\n", *p); -#endif - // 检查匹配 http 头结尾的情况 - if(*p == str_head_end[head_end_matched]) - { - head_end_matched++; -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: head end matched.\n"); -#endif - } - else - head_end_matched = 0; - if(head_end_matched == strlen(str_head_end)) - { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: ua not found.\n"); - printk("rkp-ua: __rkpStream_scan end.\n"); -#endif - return; - } - - // 检查匹配 "User-Agent: " 的情况 - if(*p == str_ua_begin[ua_begin_matched]) - { - ua_begin_matched++; -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: ua begin matched.\n"); -#endif - } - else - ua_begin_matched = 0; - if(ua_begin_matched == strlen(str_ua_begin)) - { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: ua found.\n"); -#endif - // 如果是这个包中最后一个字节了,那么跳到下一个包的第一个字节;否则,移动到下一个字节 - if(p == rkpPacket_appEnd(rkpp) - 1) - { - rkpp = rkpp -> next; - p = rkpPacket_appBegin(rkpp); - } - else - p++; - // 将结果记录进去 - ua_begin_rkpp = rkpp; - ua_begin_p = p; - break; - } - } - } - - // 匹配 "\r\n" 和需要忽略的关键字的阶段 -#ifdef RKP_DEBUG - printk("matching \\r\\n\n"); -#endif + // 匹配需要保留的 ua if(n_str_preserve > 0) { - keyword_matched = rkpMalloc(n_str_preserve * sizeof(unsigned)); + unsigned* keyword_matched = (unsigned*)rkpMalloc(n_str_preserve * sizeof(unsigned)); memset(keyword_matched, 0, n_str_preserve * sizeof(unsigned)); - } - for(rkpp = ua_begin_rkpp; rkpp != 0 && ua_end_matched != strlen(str_ua_end); rkpp = rkpp -> next) - { - unsigned char* p; - if(rkpp == ua_begin_rkpp) - p = ua_begin_p; - else - p = rkpPacket_appBegin(rkpp); - for(; p != rkpPacket_appEnd(rkpp); p++) + p = rkps -> scan_uaBegin_p; + rkpp = rkps -> buff_scan; + while(p != rkps -> scan_uaEnd_p) { - // 检查匹配 "\r\n" 的情况 -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: matching %c.\n", *p); -#endif - if(*p == str_ua_end[ua_end_matched]) - { - ua_end_matched++; -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: ua end matched.\n"); -#endif - } - else - ua_end_matched = 0; - if(ua_end_matched == strlen(str_ua_end)) - { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: ua end found.\n"); -#endif - // 如果在某个包的开头几个字节匹配结束(即 ua 实际上全部位于上一个包),就返回去 - if(p + 1 - rkpPacket_appBegin(rkpp) <= strlen(str_ua_end)) - { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: move to last packet.\n"); -#endif - unsigned temp = strlen(str_ua_end) - (p + 1 - rkpPacket_appBegin(rkpp)); // str_ua_end 位于上一个包中的长度 - rkpp = rkpp -> prev; - p = rkpPacket_appEnd(rkpp) - temp; - } - // 否则,回退到 ua 结束的位置 - else - p += 1 - strlen(str_ua_end); - // 记录结果 - ua_end_rkpp = rkpp; - ua_end_p = p; - // 记得删掉不用的内存 - if(n_str_preserve > 0) - rkpFree(keyword_matched); - break; - } - - // 检查匹配需要忽略的关键字的情况 unsigned i; for(i = 0; i < n_str_preserve; i++) { @@ -544,44 +506,52 @@ void __rkpStream_modify(struct rkpStream* rkps) keyword_matched[i] = 0; if(keyword_matched[i] == strlen(str_preserve[i])) { -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: keyword %s matched.\n", str_preserve[i]); - printk("rkp-ua: __rkpStream_scan end.\n"); -#endif 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); } } - // 已经获得了所需要的信息并且确认 ua 需要替换,然后替换 ua 的阶段 - // 已经全部 writeable,可以放心大胆地替换字符串 -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: ua modify start.\n"); -#endif - for(rkpp = ua_begin_rkpp; ; rkpp = rkpp -> next) + // 计算校验和 + rkpp = rkps -> buff_scan; + while(rkpp != 0) { - unsigned char* p; - if(rkpp == ua_begin_rkpp) - p = ua_begin_p; - else - p = rkpPacket_appBegin(rkpp); - for(; p != rkpPacket_appEnd(rkpp) && p != ua_end_p; p++) - { - if(ua_relplaced < strlen(str_ua_rkp)) - *p = str_ua_rkp[ua_relplaced]; - else - *p = ' '; - ua_relplaced++; - } - if(rkpp == ua_end_rkpp) - break; - } - // 重新计算校验和 -#ifdef RKP_DEBUG - printk("rkp-ua: __rkpStream_modify: skb checksum start.\n"); -#endif - for(rkpp = ua_begin_rkpp; rkpp != 0 && rkpp -> prev != ua_end_rkpp; rkpp = rkpp -> next) rkpPacket_csum(rkpp); + rkpp = rkpp -> next; + } }