From 3a1357f54c915033a31be6d4cdc94ab83647d801 Mon Sep 17 00:00:00 2001 From: chn <897331845@qq.com> Date: Mon, 23 Dec 2019 04:19:01 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E5=86=99=E5=95=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- README.md | 2 + src/common.h | 17 +- src/rkpPacket.h | 118 ++++++++++ src/rkpSettings.h | 14 +- src/rkpStream.h | 544 +++++++++++++++++----------------------------- 6 files changed, 344 insertions(+), 353 deletions(-) create mode 100644 src/rkpPacket.h diff --git a/Makefile b/Makefile index e6cfc53..958a846 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ define KernelPackage/rkp-ua SUBMENU:=Other modules TITLE:=rkp-ua FILES:=$(PKG_BUILD_DIR)/rkp-ua.ko - AUTOLOAD:=$(call AutoLoad, 99, rkp-ua) +# AUTOLOAD:=$(call AutoLoad, 99, rkp-ua) KCONFIG:= endef diff --git a/README.md b/README.md index f0a185c..536c28e 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ sniffing 状态下,收集包直到得到全部的 HTTP 头,修改后发出 另外,当一个新的连接的两个地址和两个端口与一个旧的连接都相同的时候,模块会将旧的连接覆盖掉。 +对重传一律不作处理。 + #### 假装面向对象 仿照 MBROLA 的设计,为了让代码容易整理,用面向对象的思路。每一个头文件即是一个类(本质上是一个结构体,和很多个以这个结构体的指针为第一个参数的函数)。`xxx` 类的函数都以 `xxx_` 开头。`xxx_new`、`xxx_del` 分别是 `xxx` 类的构造函数和析构函数。除了 `sk_buff` 中的数据,变量都以本机的字节序存储。 diff --git a/src/common.h b/src/common.h index 2df8048..4f1af1e 100644 --- a/src/common.h +++ b/src/common.h @@ -1,3 +1,4 @@ +#pragma once #include #include #include @@ -18,13 +19,25 @@ 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[9]; +void* rkpMalloc(unsigned size) +{ + void* p = kmalloc(size, GFP_KERNEL); + if(p == 0) + printk("rkp-ua: malloc failed.\n"); + return p; +} +void rkpFree(void* p) +{ + kfree(p); +} + time_t now(void) { - struct timespec* ts = kmalloc(sizeof(struct timespec), GFP_KERNEL); + struct timespec* ts = rkpMalloc(sizeof(struct timespec)); time_t rtn; getnstimeofday(ts); rtn = ts -> tv_sec; - kfree(ts); + rkpFree(p); #ifdef RKP_DEBUG printk("now %lu\n", ts -> tv_sec); #endif diff --git a/src/rkpPacket.h b/src/rkpPacket.h new file mode 100644 index 0000000..f2e1add --- /dev/null +++ b/src/rkpPacket.h @@ -0,0 +1,118 @@ +#pragma once +#include "common.h" + +struct rkpPacket +// 存储一个个数据包的类,完全被 rkpStream 包裹 +{ + struct rkpPacket *prev, *next; + struct sk_buff* skb; +}; + +struct rkpPacket* rkpPacket_new(struct sk_buff*); +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*); +u_int32_t rkpPacket_seq(struct rkpPacket*); +u_int32_t rkpPacket_ack(struct rkpPacket*); +bool rkpPacket_psh(struct rkpPacket*); + +bool rkpPacket_scan(struct rkpPacket*, unsigned char*, unsigned*); // 搜索指定字符串,已匹配的长度存入第三个参数,返回是否完全匹配到了 + +void rkpPacket_csum(struct rkpPacket*); + +struct rkpPacket* rkpPacket_new(struct sk_buff* skb) +{ +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_new start.\n"); +#endif + struct rkpPacket* p = rkpMalloc(sizeof(struct rkpPacket)); + if(p != 0) + { + p -> prev = p -> next = 0; + p -> skb = skb; + } + else + printk("rkp-ua: rkpPacket_new: malloc failed.\n"); +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_new end.\n"); +#endif + return p; +} +void rkpPacket_send(struct rkpPacket* p) +{ +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_send start.\n"); +#endif + if(dev_queue_xmit(p -> skb)) + { + printk("rkp-ua: rkpPacket_new: Send failed. Drop it.\n"); + kfree_skb(p -> skb); + } + rkpFree(p); +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_send end.\n"); +#endif +} +void rkpPacket_delete(struct rkpPacket* p) +{ +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_delete start.\n"); +#endif + rkpFree(p); +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_delete end.\n"); +#endif +} +void rkpPacket_drop(struct rkpPacket* p) +{ +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_drop start.\n"); +#endif + kfree_skb(p -> skb); + rkpFree(p); +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_drop end.\n"); +#endif +} + +unsigned char* rkpPacket_appBegin(struct rkpPacket* p) +{ + return ((unsigned char*)tcp_hdr(p -> skb)) + tcp_hdr(p -> skb) -> doff * 4; +} +unsigned char* rkpPacket_appEnd(struct rkpPacket* p) +{ + return ((unsigned char*)ip_hdr(p -> skb)) + ntohs(ip_hdr(p -> skb) -> tot_len); +} +unsigned rkpPacket_appLen(struct rkpPacket* p) +{ + return ntohs(ip_hdr(p -> skb) -> tot_len) - ip_hdr(p -> skb) -> ihl * 4 - tcp_hdr(p -> skb) -> doff * 4; +} +u_int32_t rkpPacket_seq(struct rkpPacket* p) +{ + return ntohl(tcp_hdr(p -> skb) -> seq); +} +u_int32_t rkpPacket_ack(struct rkpPacket* p) +{ + return ntohl(tcp_hdr(p -> skb) -> ack); +} + +void rkpPacket_csum(struct rkpPacket* p) +{ +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_csum start.\n"); +#endif + struct iphdr* iph = ip_hdr(p -> skb); + struct tcphdr* tcph = tcp_hdr(p -> skb); + tcph -> check = 0; + iph -> check = 0; + iph -> check = ip_fast_csum((unsigned char*)iph, iph -> ihl); + 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); +#ifdef RKP_DEBUG + printk("rkp-ua: rkpPacket_csum end.\n"); +#endif +} \ No newline at end of file diff --git a/src/rkpSettings.h b/src/rkpSettings.h index 4267690..f7f5cd5 100644 --- a/src/rkpSettings.h +++ b/src/rkpSettings.h @@ -1,3 +1,4 @@ +#pragma once #include "common.h" static bool mode_advanced = false; @@ -9,11 +10,9 @@ module_param_array(str_preserve, charp, &n_str_preserve, 0); static u_int32_t mark_capture = 0x100; module_param(mark_capture, uint, 0); -static u_int32_t mark_request = 0x200; -module_param(mark_request, uint, 0); -static u_int32_t mark_first = 0x400; +static u_int32_t mark_first = 0x200; module_param(mark_first, uint, 0); -static u_int32_t mark_preserve = 0x800; +static u_int32_t mark_preserve = 0x400; module_param(mark_preserve, uint, 0); static unsigned time_keepalive = 1200; @@ -51,13 +50,6 @@ bool rkpSettings_capture(const struct sk_buff* skb) return false; } } -bool rkpSettings_request(const struct sk_buff* skb) -{ - if(mode_advanced) - return (skb -> mark & mark_request) == mark_request; - else - return ntohs(tcp_hdr(skb) -> dest) == 80; -} bool rkpSettings_first(const struct sk_buff* skb) { if(mode_advanced) diff --git a/src/rkpStream.h b/src/rkpStream.h index 6db82c4..6ff9f42 100644 --- a/src/rkpStream.h +++ b/src/rkpStream.h @@ -1,32 +1,36 @@ +#pragma once #include "rkpSettings.h" +#include "rkpPacket.h" struct rkpStream +// 接管一个 TCP 流。忽略重传(一律放行)。因此,也不需要捕获来自服务端的包。 { enum { - rkpStream_sniffing, - rkpStream_waiting + __rkpStream_sniffing, + __rkpStream_waiting } status; u_int32_t id[3]; // 按顺序存储客户地址、服务地址、客户端口、服务端口,已经转换字节序 - struct sk_buff *buff, *buff_prev, *buff_next; // 都按照字节序排好了 - u_int32_t ack; // 服务端已经确认收到的最后一个字节的序列号。以后所有的相对序列号都是将这个序号视为零的相对序列号。 - u_int32_t seq; // 已经收到的最后一个字节的序列号。期待的序列号应该比它加1。 - time_t last_active; - bool scan_matched; - bool preserve; + struct rkpPacket *buff_scan, *buff_disordered; // 分别存储准备扫描的、因乱序而提前收到的数据包,都按照字节序排好了 + u_int32_t seq_offset; // 序列号的偏移。使得 buff_scan 中第一个字节的编号为零。 + time_t last_active; // 最后活动时间,用来剔除长时间不活动的流。 + unsigned scan_matched; // 记录现在已经匹配了多少个字节 struct rkpStream *prev, *next; }; -struct rkpStream* rkpStream_new(const struct sk_buff*); // 构造函数,得到的流的状态是捕获这个数据包之后的状态。内存不够时返回 0。 -void rkpStream_del(struct rkpStream*); // 析构函数 -bool rkpStream_belong(const struct rkpStream*, const struct sk_buff*); // 判断一个数据包是否属于一个流 -unsigned rkpStream_execute(struct rkpStream*, struct sk_buff*); // 处理一个数据包(假定包属于这个流) +struct rkpStream* rkpStream_new(const struct sk_buff*); // 由三次握手的第一个包构造一个 rkpSteam +void rkpStream_delete(struct rkpStream*); -void __rkpStream_refresh_ack(struct rkpStream*, u_int32_t); // 刷新确认序列号。第二个参数就是ack包中的确认号(绝对值)减一,表明已经确认到了哪个位置。会自动重新计算序列号的偏移,以及释放 buff_prev 中的多余数据包 +bool rkpStream_belongTo(const struct rkpStream*, const struct sk_buff*); // 判断一个数据包是否属于一个流 +unsigned rkpStream_execute(struct rkpStream*, struct sk_buff*); // 已知一个数据包属于这个流后,处理这个数据包 -unsigned char* __rkpStream_skb_appBegin(const struct sk_buff*); // 返回一个包的应用层数据起始位置 -u_int16_t __rkpStream_skb_appLen(const struct sk_buff*); // 返回一个包的应用层数据长度 -int32_t __rkpStream_skb_seq(u_int32_t, u_int32_t); // 返回一个序列号的相对序列号。两个参数分别为流的确认号、包的序列号(已经转换字节序)。可以为负。 +int32_t __rkpStream_seq_scanEnd(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*, unsigned char*); // 在包的应用层搜索 ua 头的结尾 +void __rkpStream_modify(struct rkpStream*); // 在已经收集到完整的 HTTP 头后,调用去按规则修改 buff_scan 中的包 void __rkpStream_skb_send(struct sk_buff*); // 发送一个数据包 struct sk_buff* __rkpStream_skb_copy(const struct sk_buff*); // 复制一个数据包 @@ -46,379 +50,272 @@ void __rkpStream_buff_execute_core(struct sk_buff**, u_int16_t, bool); // struct rkpStream* rkpStream_new(const struct sk_buff* skb) { - struct rkpStream* rkps = kmalloc(sizeof(struct rkpStream), GFP_KERNEL); +#ifdef RKP_DEBUG + printk("rkp-ua: rkpStream_new start.\n"); +#endif + struct rkpStream* rkps = rkpMalloc(sizeof(struct rkpStream)); const struct iphdr* iph = ip_hdr(skb); const struct tcphdr* tcph = tcp_hdr(skb); - if(rkps == 0) { - printk("rkp-ua::rkpStream::rkpStream_new: `kmalloc` failed, may caused by shortage of memory.\n"); + printk("rkp-ua: rkpStream_new: malloc failed, may caused by shortage of memory.\n"); return 0; } - rkps -> status = rkpStream_sniffing; + rkps -> status = __rkpStream_sniffing; rkps -> id[0] = ntohl(iph -> saddr); rkps -> id[1] = ntohl(iph -> daddr); rkps -> id[2] = (((u_int32_t)ntohs(tcph -> source)) << 16) + ntohs(tcph -> dest); - rkps -> buff = rkps -> buff_prev = rkps -> buff_next = 0; - rkps -> ack = ntohl(tcph -> seq) - 1; - rkps -> seq = 1; + rkps -> buff_scan = rkps -> buff_disordered = rkps -> buff_sent = 0; + rkps -> seq_offset = ntohl(skb -> seq) + 1; rkps -> last_active = now(); rkps -> scan_matched = 0; - rkps -> preserve = rkpSettings_preserve(skb); rkps -> prev = rkps -> next = 0; +#ifdef RKP_DEBUG + printk("rkp-ua: rkpStream_new end.\n"); +#endif return rkps; } -void rkpStream_del(struct rkpStream* rkps) +void rkpStream_delete(struct rkpStream* rkps) { - kfree_skb_list(rkps -> buff); - kfree_skb_list(rkps -> buff_prev); - kfree_skb_list(rkps -> buff_next); - kfree(rkps); +#ifdef RKP_DEBUG + printk("rkp-ua: rkpStream_delete start.\n"); +#endif + for(struct rkpPacket* p = rkps -> buff_scan; p != 0;) + { + struct rkpPacket* p2 = p; + p = p -> next; + rkpPacket_drop(p2); + } + for(struct rkpPacket* p = rkps -> buff_disordered; p != 0;) + { + struct rkpPacket* p2 = p; + p = p -> next; + rkpPacket_drop(p2); + } + for(struct rkpPacket* p = rkps -> buff_sent; p != 0;) + { + struct rkpPacket* p2 = p; + p = p -> next; + rkpPacket_delete(p2); + } + rkpFree(rkps); +#ifdef RKP_DEBUG + printk("rkp-ua: rkpStream_delete end.\n"); +#endif } + bool rkpStream_belong(const struct rkpStream* rkps, const struct sk_buff* skb) { #ifdef RKP_DEBUG - printk("rkpStream_belong:\n"); + printk("rkp-ua: rkpStream_belongTo start.\n"); printk("\tsyn %d ack %d\n", tcp_hdr(skb) -> syn, tcp_hdr(skb) -> ack); printk("\tsport %d dport %d\n", ntohs(tcp_hdr(skb) -> source), ntohs(tcp_hdr(skb) -> dest)); printk("\tsip %u dip %u\n", ntohl(ip_hdr(skb) -> saddr), ntohl(ip_hdr(skb) -> daddr)); printk("\trkpSettings_request %d\n", rkpSettings_request(skb)); printk("\tid %u %u %u", rkps -> id[0], rkps -> id[1], rkps -> id[2]); #endif + bool rtn; if(rkpSettings_request(skb)) { if(rkps -> id[0] != ntohl(ip_hdr(skb) -> saddr)) - return false; + rtn = false; if(rkps -> id[1] != ntohl(ip_hdr(skb) -> daddr)) - return false; + rtn = false; if(rkps -> id[2] != (((u_int32_t)ntohs(tcp_hdr(skb) -> source)) << 16) + ntohs(tcp_hdr(skb) -> dest)) - return false; - return true; + rtn = false; + rtn = true; } else { if(rkps -> id[0] != ntohl(ip_hdr(skb) -> daddr)) - { -#ifdef RKP_DEBUG - printk("\t 0 not match.\n"); -#endif - return false; - } + rtn = false; if(rkps -> id[1] != ntohl(ip_hdr(skb) -> saddr)) - { -#ifdef RKP_DEBUG - printk("\t 1 not match.\n"); -#endif - return false; - } + rtn = false; if(rkps -> id[2] != (((u_int32_t)ntohs(tcp_hdr(skb) -> dest)) << 16) + ntohs(tcp_hdr(skb) -> source)) - { -#ifdef RKP_DEBUG - printk("\t 2 not match.\n"); -#endif - return false; - } - return true; + rtn = false; + rtn = true; } +#ifdef RKP_DEBUG + printk("rkp-ua: rkpStream_belongTo end, will return %d.\n", rtn); +#endif + return rtn; } unsigned rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) // 不要害怕麻烦,咱们把每一种情况都慢慢写一遍。 { - int32_t seq; + struct rkpPacket* p = rkpPacket_new(skb); #ifdef RKP_DEBUG - printk("rkpStream_execute\n"); + printk("rkp-ua: rkpStream_execute start.\n"); #endif // 肯定需要更新时间 rkps -> last_active = now(); - // 服务端返回确认包的情况,更新一下确认号,返回 sccept。以后的情况,都是客户端发往服务端的了。 - if(!rkpSettings_request(skb)) + // 不携带应用层数据的情况。直接接受即可。以后的情况,都是含有应用层数据的包了。 + if(rkpPacket_appLen(p) == 0) { #ifdef RKP_DEBUG - printk("DEBUG0\n"); -#endif - int32_t seq = __rkpStream_skb_seq(rkps -> ack, ((unsigned)(ntohl(tcp_hdr(skb) -> ack_seq))) - 1); - if(seq > 0) - __rkpStream_refresh_ack(rkps, ((unsigned)(ntohl(tcp_hdr(skb) -> ack_seq))) - 1); - return NF_ACCEPT; - } - - // 不携带应用层数据的情况。除了首包,直接接受即可。以后的情况,都是含有应用层数据的包了。 - if(__rkpStream_skb_appLen(skb) == 0) - { -#ifdef RKP_DEBUG - printk("DEBUG1\n"); + printk("\tblank packet judged.\n"); #endif + rkpPacket_delete(p); return NF_ACCEPT; } - // 检查数据包是否是将来的数据包。如果是的话,需要放到 buff_next 等待处理。 - seq = __rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(skb) -> seq)); -#ifdef RKP_DEBUG - printk("seq %d\n", seq); -#endif - if(seq > rkps -> seq + 1) + // 接下来从小到大考虑数据包的序列号的几种情况 + // 已经发出的数据包,直接忽略 + if(int32_t(rkpPacket_seq(p) - rkps -> seq_offset) < 0) { #ifdef RKP_DEBUG - printk("DEBUG2\n"); + printk("\tsent packet judged.\n"); #endif - skb = __rkpStream_skb_copy(skb); - if(skb == 0) - return NF_ACCEPT; - __rkpStream_buff_retain_auto(&(rkps -> buff_next), __rkpStream_skb_copy(skb)); - return NF_DROP; - } - - // 检查数据包是否是已经被确认的数据包。应该不会出现这种情况(除了不带数据的 keep alive,但这已经考虑过了)。出现的话就把它丢掉吧。 - if(seq < 0) - { - printk("rkp-ua::rkpStream: Re-transmission of asked package. Drop it.\n"); - return NF_DROP; - } - - // 检查数据包是否是重传数据包。如果是的话,可能需要修改数据。然后,将它发出。接下来的情况,就一定是刚好是需要的序列号的情况了 - if(seq < rkps -> seq + 1) - { -#ifdef RKP_DEBUG - printk("DEBUG3\n"); - if(seq + __rkpStream_skb_appLen(skb) - 1 == rkps -> seq) - printk("Re-transmission of recent package."); -#endif - const struct sk_buff* skb_prev = __rkpStream_buff_find(rkps -> buff_prev, ntohl(tcp_hdr(skb) -> seq)); - if(skb_prev != 0 && tcp_hdr(skb_prev) -> seq == tcp_hdr(skb) -> seq) - // 存在相符的数据包。将数据拷贝过去。 - { -#ifdef RKP_DEBUG - printk("Found same packet.\n"); - unsigned char* temp = kmalloc(2048, GFP_KERNEL); - memset(temp, 0, 2048); - memcpy(temp, __rkpStream_skb_appBegin(skb), __rkpStream_skb_appLen(skb)); - printk("%s\n", temp); - kfree(temp); - if(!memcmp(__rkpStream_skb_appBegin(skb), __rkpStream_skb_appBegin(skb_prev), __rkpStream_skb_appLen(skb))) - printk("Fake Re-transmission."); -#endif - if(skb_ensure_writable(skb, __rkpStream_skb_appBegin(skb) + __rkpStream_skb_appLen(skb) - skb -> data)) - { - printk("rkp-ua::rkpStream::rkpStream_execute: Can not make skb writable, may caused by shortage of memory. Drop it.\n"); - return NF_DROP; - } - if(__rkpStream_skb_appLen(skb_prev) != __rkpStream_skb_appLen(skb)) - { - printk("rkp-ua::rkpStream::rkpStream_execute: Size of app data in re-transmission package and previous one not match. Drop it.\n"); - return NF_DROP; - } - memcpy(__rkpStream_skb_appBegin(skb), __rkpStream_skb_appBegin(skb_prev), __rkpStream_skb_appLen(skb_prev)); - __rkpStream_skb_csum(skb); - } + rkpPacket_delete(p); return NF_ACCEPT; } - - // 如果是在 sniffing 的情况下,那一定先扫描一下再说 - if(rkps -> status == rkpStream_sniffing) + // 已经放到 buff_scan 中的数据包,丢弃 + if(int32_t(rkpPacket_seq(p) - rkps -> seq_offset) < __rkpStream_seq_scanEnd(rkps)) { #ifdef RKP_DEBUG - printk("DEBUG4\n"); + printk("\tcaptured packet judged.\n"); #endif - u_int16_t scan = __rkpStream_data_scan(__rkpStream_skb_appBegin(skb), __rkpStream_skb_appLen(skb), - str_head_end, rkps -> scan_matched); - - if(scan & 0x1) - // 扫描找到了 HTTP 头的结尾,那么将这个数据包补到 buff 中,更新 seq,开始查找、替换、发出,然后根据情况设置状态,再考虑 buff_next 中的包,最后返回 STOLEN + rkpPacket_delete(p); + return NF_DROP; + } + // 恰好是 buff_scan 的后继数据包,这种情况比较麻烦,写到最后 + // 乱序导致还没接收到前继的数据包,放到 buff_disordered + if(int32_t(rkpPacket_seq(p) - rkps -> seq_offset) > __rkpStream_seq_scanEnd(rkps)) + { +#ifdef RKP_DEBUG + printk("\tdisordered packet judged.\n"); +#endif + __rkpStream_insert_auto(&(rkps -> buff_disordered), p); + return NF_STOLEN; + } + + // 接下来是恰好是 buff_scan 的后继数据包的情况,先分状态讨论,再一起考虑 buff_disordered 中的包 +#ifdef RKP_DEBUG + printk("\tdesired packet judged.\n"); +#endif + unsigned rtn; + // 如果是在 sniffing 的情况下,那一定先丢到 buff_scan 里,然后扫描一下看结果,重新设定状态 + if(rkps -> status == __rkpStream_sniffing) + { +#ifdef RKP_DEBUG + printk("\t\tsniffing.\n"); +#endif + // 丢到 buff_scan 里 + __rkpStream_insert_end(rkps, &(rkps -> buff_scan), p); + if(__rkpStream_scan(rkps, p, str_head_end)) // 扫描到了 { #ifdef RKP_DEBUG - printk("DEBUG5\n"); + printk("\t\t\thttp head end matched.\n"); #endif - struct sk_buff* skbp; - - skb = __rkpStream_skb_copy(skb); - if(skb == 0) - return NF_ACCEPT; - - // 追加到 buff 后面,更新 seq - __rkpStream_buff_retain_end(&(rkps -> buff), skb); - rkps -> seq = __rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb) - 1; - - // 查找、替换 - __rkpStream_buff_execute_core(&(rkps -> buff), scan >> 1, rkps -> preserve); - -#ifdef RKP_DEBUG - // return NF_ACCEPT; -#endif - - // 循环复制一份到 buff_prev 下面,同时发出 - skbp = rkps -> buff; - while(skbp != 0) + // 替换 ua + __rkpStream_modify(rkps); + // 发出数据包,注意最后一个不发,等会儿 accept 就好 + for(struct rkpPacket* p = rkps -> buff_scan; p != 0 && p -> next != 0;) { - struct sk_buff* skbp2 = skbp -> next; - __rkpStream_buff_retain_end(&(rkps -> buff_prev), __rkpStream_skb_copy(skbp)); - __rkpStream_skb_send(skbp); - skbp = skbp2; + struct rkpPacket* p2 = p; + p = p -> next; + rkps -> seq_offset = rkpPacket_seq(p2) + rkpPacket_appLen(p2); // 别忘了更新偏移 + rkpPacket_send(p2); } - rkps -> buff = 0; - - // 清空查找情况,重新设置状态 - rkps -> scan_matched = 0; - if(!(tcp_hdr(skb) -> psh)) - rkps -> status = rkpStream_waiting; - - // 考虑之前截留的数据包 - __rkpStream_buff_rejudge(rkps, &(rkps -> buff_next)); - - return NF_DROP; - } - else if(tcp_hdr(skb) -> psh) - // 如果没有找到却读到了 PUSH,这就比较迷了。打印一句警告,更新 seq,然后把截留的包都放行,然后考虑 buff_next 里的数据。 - { - struct sk_buff* skbp = rkps -> buff; - - // 打印警告 - printk("rkp-ua::rkpStream::rkpStream_execute: Find PSH before header ending found. Send without modification.\n"); - - // 更新 seq - rkps -> seq = __rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb) - 1; - - // 放行截留的包 - while(skbp != 0) - { - struct sk_buff* skbp2 = skbp -> next; - __rkpStream_skb_send(skbp); - skbp = skbp2; - } - rkps -> buff = 0; - - // 清空查找情况 - rkps -> scan_matched = 0; - - // 考虑之前截留的数据包 - __rkpStream_buff_rejudge(rkps, &(rkps -> buff_next)); - - return NF_ACCEPT; + rkps -> buff_scan = 0; + // 设定状态为等待 + rkps -> status = __rkpStream_waiting; + // accept + rtn = NF_ACCEPT; } + // 没有扫描到,那么 stolen else - // 没有找到结尾,也没有push。那么,将这个数据包补到 buff 中,更新 seq 和 查找状态,再考虑 buff_next 中的包,最后返回 STOLEN + { + if(rkpPacket_psh(p)) // 如果同时没有 psh,就偷走 + rtn = NF_STOLEN; +#ifdef RKP_DEBUG + printk("\t\t\thttp head end not matched.\n"); +#endif + } + // 处理一下 psh + if(rkpPacket_psh(p)) { #ifdef RKP_DEBUG - printk("DEBUG6\n"); + printk("\t\t\tpsh found.\n"); #endif + if(rkps -> buff_scan != 0) // 如果刚刚没有扫描到 http 结尾 + { +#ifdef RKP_DEBUG + printk("rkp-ua: rkpStream_execute: psh found before http head end.\n"); +#endif + for(struct rkpPacket* p = rkps -> buff_scan; p != 0 && p -> next != 0;) + { + struct rkpPacket* p2 = p; + p = p -> next; + rkps -> seq_offset = rkpPacket_seq(p2) + rkpPacket_appLen(p2); + rkpPacket_send(p2); + } + } + else // 如果刚刚扫描到了 + rkps -> status = __rkpStream_sniffing; - skb = __rkpStream_skb_copy(skb); - if(skb == 0) - return NF_ACCEPT; - - // 追加到 buff - __rkpStream_buff_retain_end(&(rkps -> buff), skb); - - // 更新 seq 和查找状态 - rkps -> seq = __rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb) - 1; - rkps -> scan_matched = scan >> 1; - - // 考虑 buff_next 中的包 - __rkpStream_buff_rejudge(rkps, &(rkps -> buff_next)); - - return NF_DROP; + // 只要有 psh,肯定接受 + rtn = NF_ACCEPT; } } - else - // 如果是在 waiting 的状态下,那么设置 seq 和状态,然后考虑 buff_next 中的包,然后返回 ACCEPT 就可以了 + else // waiting 的状态,检查 psh、设置序列号偏移、然后放行就可以了 { #ifdef RKP_DEBUG - printk("DEBUG7\n"); + printk("\t\tsniffing.\n"); #endif - // 设置 seq 和状态 - rkps -> seq = __rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb) - 1; - if(tcp_hdr(skb) -> psh) - rkps -> status = rkpStream_sniffing; - - // 考虑 buff_next - __rkpStream_buff_rejudge(rkps, &(rkps -> buff_next)); - - return NF_ACCEPT; + if(rkpPacket_psh(p)) + rkps -> status = __rkpStream_sniffing; + rtn = NF_ACCEPT; } -} -void __rkpStream_refresh_ack(struct rkpStream* rkps, u_int32_t ack) -{ - struct sk_buff* skbp; - - // 重新计算 ack 和 seq - rkps -> seq -= ack - rkps -> ack; - rkps -> ack = ack; - - // 丢弃 buff_prev 中已经确认收到的数据包 - skbp = rkps -> buff_prev; - while(skbp != 0 && __rkpStream_skb_seq(ack, ntohl(tcp_hdr(skbp) -> ack)) <= 0) + // 考虑 buff_disordered + while(rkps -> buff_disordered != 0) { - struct sk_buff* skbp2 = skbp -> next; - __rkpStream_skb_del(skbp); - skbp = skbp2; + if(rkpPacket_seq(rkps -> buff_disordered) - rkps -> seq_offset < __rkpStream_seq_scanEnd(rkps)) + // 序列号是已经发出去的,丢弃 + { + if(rkps -> buff_disordered -> next == 0) + { + rkpPacket_drop(rkps -> buff_disordered); + rkps -> buff_disordered = 0; + } + else + { + rkps -> buff_disordered = rkps -> buff_disordered -> next; + rkpPacket_drop(rkps -> buff_disordered -> prev); + rkps -> buff_disordered -> prev = 0; + } + } + // 如果序列号过大,结束循环 + else if(rkpPacket_seq(rkps -> buff_disordered) - rkps -> seq_offset > __rkpStream_seq_scanEnd(rkps)) + break; + // 如果序列号恰好,把它从链表中取出,然后像刚刚抓到的包那样去执行 + else + { + // 将包从链表中取出 + struct rkpPacket* p2 = rkps -> buff_disordered; + if(rkps -> buff_disordered -> next == 0) + rkps -> buff_disordered = 0; + else + { + rkps -> buff_disordered = rkps -> buff_disordered -> next; + rkps -> buff_disordered -> prev = 0; + } + // 执行 + unsigned rtn = rkpStream_execute(rkps, p2 -> skb); + if(rtn == NF_ACCEPT) + rkpPacket_send(p2); + else if(rtn == NF_DROP) + rkpPacket_drop(p2); + else if(rtn == NF_STOLEN) + rkpPacket_delete(p2); + } + } + + return rtn; } - rkps -> buff_prev = skbp; -} - -unsigned char* __rkpStream_skb_appBegin(const struct sk_buff* skb) -{ - return ((unsigned char*)tcp_hdr(skb)) + tcp_hdr(skb) -> doff * 4; -} - -u_int16_t __rkpStream_skb_appLen(const struct sk_buff* skb) -{ - return ntohs(ip_hdr(skb) -> tot_len) - ip_hdr(skb) -> ihl * 4 - tcp_hdr(skb) -> doff * 4; -} - -int32_t __rkpStream_skb_seq(u_int32_t ack, u_int32_t seq) -{ - return (int32_t)(seq - ack); -} - -void __rkpStream_skb_send(struct sk_buff* skb) -{ - if(dev_queue_xmit(skb)) - printk("rkp-ua: Send failed.\n"); -} - -struct sk_buff* __rkpStream_skb_copy(const struct sk_buff* skb) -{ - struct sk_buff* rtn = skb_copy(skb, GFP_KERNEL); - if(rtn == 0) - printk("rkp-ua::rkpStream::__rkpStream_skb_copy: `skb_copy` failed, may caused by shortage of memory."); - -#ifdef RKP_DEBUG - printk("__rkpStream_skb_copy:\n"); - printk("\tcheck if parameter equals.\n"); - printk("\tskb -> dev %d\n", skb -> dev == rtn -> dev); - printk("\tskb -> pkt_type %d\n", skb -> pkt_type == rtn -> pkt_type); - printk("\tskb -> protocol %d\n", skb -> protocol == rtn -> protocol); - printk("\tskb -> ip_summed %d\n", skb -> ip_summed == rtn -> ip_summed); - printk("\tskb -> priority %d\n", skb -> priority == rtn -> priority); - printk("\tskb -> csum %d\n", skb -> csum == rtn -> csum); - printk("\tethh -> h_dest %d\n", eth_hdr(skb) -> h_dest == eth_hdr(rtn) -> h_dest); - printk("\tethh -> h_source %d\n", eth_hdr(skb) -> h_source == eth_hdr(rtn) -> h_source); - printk("\tethh -> h_proto %d\n", eth_hdr(skb) -> h_proto == eth_hdr(rtn) -> h_proto); -#endif - - // 链路层数据还需要手动复制一下,我也不知道这是怎么个设计 - memcpy(eth_hdr(rtn), eth_hdr(skb), sizeof(unsigned char) * 2 * ETH_ALEN + sizeof(__be16)); - - return skb_copy(skb, GFP_KERNEL); -} -void __rkpStream_skb_del(struct sk_buff* skb) -{ - kfree_skb(skb); -} -void __rkpStream_skb_csum(struct sk_buff* skb) -{ - struct iphdr* iph = ip_hdr(skb); - struct tcphdr* tcph = tcp_hdr(skb); -#ifdef RKP_DEBUG - printk("__rkpStream_skb_csum iph -> tot_len %d skb -> len %d", ntohs(iph -> tot_len), skb -> len); -#endif - tcph -> check = 0; - iph -> check = 0; - iph -> check = ip_fast_csum((unsigned char*)iph, iph -> ihl); - skb -> csum = skb_checksum(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, skb -> csum); } u_int16_t __rkpStream_data_scan(const unsigned char* data, u_int16_t data_len, const unsigned char* target, u_int8_t matched) @@ -500,38 +397,7 @@ void __rkpStream_buff_retain_auto(struct sk_buff** buff, struct sk_buff* skb) skb -> prev = p; } } -void __rkpStream_buff_rejudge(struct rkpStream* rkps, struct sk_buff** buff) -{ - while(*buff != 0) - { - int32_t seq = __rkpStream_skb_seq(rkps -> ack, ntohl(tcp_hdr(*buff) -> seq)); - if(seq <= rkps -> seq) - // 过期的skb,虽然应该不会出现这样的情况 - { - struct sk_buff* skb2 = (*buff) -> next; - __rkpStream_skb_del(*buff); - *buff = skb2; - } - else if(seq == rkps -> seq + 1) - { - unsigned rtn; - struct sk_buff* skb2; - // 将它从链表中取出 - if((*buff) -> next != 0) - (*buff) -> next -> prev = 0; - skb2 = *buff; - *buff = (*buff) -> next; - - // 执行之 - rtn = rkpStream_execute(rkps, skb2); - if(rtn == NF_ACCEPT) - __rkpStream_skb_send(skb2); - else if(rtn == NF_DROP) - __rkpStream_skb_del(skb2); - } - } -} struct sk_buff* __rkpStream_buff_find(const struct sk_buff* skb, u_int32_t seq) { if(skb == 0)