diff --git a/.gitignore b/.gitignore index 600d2d3..c7d0251 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.vscode \ No newline at end of file +.vscode +*.log \ No newline at end of file diff --git a/Makefile b/Makefile index 958a846..6cc07ea 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ include $(INCLUDE_DIR)/package.mk EXTRA_CFLAGS:= \ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \ $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ - -DVERSION="\"\\\"$(PKG_RELEASE)\\\"\"" --verbose + -DVERSION="\"\\\"$(PKG_RELEASE)\\\"\"" --verbose -DRKP_DEBUG MAKE_OPTS:=$(KERNEL_MAKE_FLAGS) \ SUBDIRS="$(PKG_BUILD_DIR)" \ diff --git a/src/common.h b/src/common.h index 4f1af1e..f0aabb8 100644 --- a/src/common.h +++ b/src/common.h @@ -13,6 +13,7 @@ #include #include #include +#include const static unsigned char* str_ua_begin = "User-Agent: "; const static unsigned char* str_ua_end = "\r\n"; @@ -37,7 +38,7 @@ time_t now(void) time_t rtn; getnstimeofday(ts); rtn = ts -> tv_sec; - rkpFree(p); + rkpFree(ts); #ifdef RKP_DEBUG printk("now %lu\n", ts -> tv_sec); #endif diff --git a/src/rkp-ua.c b/src/rkp-ua.c index a8ac9ba..8188865 100644 --- a/src/rkp-ua.c +++ b/src/rkp-ua.c @@ -2,7 +2,7 @@ static struct nf_hook_ops nfho; static struct rkpManager* rkpm; -static time_t last_flush; +static DEFINE_MUTEX(lock); unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { @@ -24,25 +24,15 @@ unsigned int hook_funcion(void *priv, struct sk_buff *skb, const struct nf_hook_ printk("rkp-ua: Captured %d packages.\n", n_skb_captured); n_skb_captured_lastPrint *= 2; } - - if(rtn == NF_DROP_ERR(1)) - { - printk("rkp-ua: Crashed.\n"); - crashed = 1; - rkpManager_del(rkpm); - rkpm = 0; - return NF_STOLEN; - } - else - return rtn; + return rtn; } static int __init hook_init(void) { int ret; + mutex_init(&lock); - rkpm = rkpManager_new(); - last_flush = now(); + rkpm = rkpManager_new(&lock); memcpy(str_ua_rkp, "RKP/", 4); memcpy(str_ua_rkp + 4, VERSION, 2); @@ -61,8 +51,8 @@ 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: mode_advanced=%c, mark_capture=0x%x, mark_request=0x%x, mark_first=0x%x, mark_preserve=0x%x.\n", - 'n' + mode_advanced * ('y' - 'n'), mark_capture, mark_request, mark_first, mark_preserve); + 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: str_preserve:\n"); for(ret = 0; ret < n_str_preserve; ret++) printk("\t%s\n", str_preserve[ret]); @@ -73,7 +63,8 @@ static int __init hook_init(void) static void __exit hook_exit(void) { if(rkpm != 0) - rkpManager_del(rkpm); + rkpManager_delete(rkpm); + mutex_destroy(&lock); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) nf_unregister_net_hook(&init_net, &nfho); diff --git a/src/rkpManager.h b/src/rkpManager.h index 46ec9c5..8d6f43c 100644 --- a/src/rkpManager.h +++ b/src/rkpManager.h @@ -1,52 +1,60 @@ +#pragma once #include "rkpStream.h" struct rkpManager { - struct rkpStream** data; // 按照首包的两端口之和的低 8 位放置 + struct rkpStream* data[256]; // 按照首包的两端口之和的低 8 位放置 + time_t last_active; + struct mutex* lock; // 线程锁,这个需要外部静态地生成后,把指针传进来 }; -struct rkpManager* rkpManager_new(void); // 构造函数 -void rkpManager_del(struct rkpManager*); // 析构函数 +struct rkpManager* rkpManager_new(struct mutex*); +void rkpManager_delete(struct rkpManager*); -u_int8_t rkpManager_execute(struct rkpManager*, struct sk_buff*); // 处理一个数据包。返回值为 rkpStream_execute 的返回值。 -void rkpManager_refresh(struct rkpManager*); // 清理过时的流 +u_int8_t rkpManager_execute(struct rkpManager*, struct sk_buff*); // 处理一个数据包。返回值为 rkpStream_execute 的返回值。 +void rkpManager_refresh(struct rkpManager*); // 清理过时的流 -struct rkpManager* rkpManager_new(void) +void __rkpManager_lock(struct rkpManager*); +void __rkpManager_unlock(struct rkpManager*); + +struct rkpManager* rkpManager_new(struct mutex* lock) { - struct rkpManager* rkpm = kmalloc(sizeof(struct rkpManager) + sizeof(struct rkpStream*) * 256, GFP_KERNEL); + struct rkpManager* rkpm = rkpMalloc(sizeof(struct rkpStream)); if(rkpm == 0) - { - printk("rkp-ua::rkpManager::rkpStream_new: `kmalloc` failed, may caused by shortage of memory.\n"); return 0; - } - rkpm -> data = (void*)rkpm + sizeof(struct rkpManager); memset(rkpm -> data, 0, sizeof(struct rkpStream*) * 256); + rkpm -> lock = lock; + mutex_init(rkpm -> lock); return rkpm; } -void rkpManager_del(struct rkpManager* rkpm) +void rkpManager_delete(struct rkpManager* rkpm) { + __rkpManager_lock(rkpm); unsigned i; for(i = 0; i < 256; i++) { - struct rkpStream *rkps = rkpm -> data[i]; + struct rkpStream* rkps = rkpm -> data[i]; while(rkps != 0) { struct rkpStream *rkps2 = rkps -> next; - rkpStream_del(rkps); + rkpStream_delete(rkps); rkps = rkps2; } } - kfree(rkpm); + __rkpManager_unlock(rkpm); + rkpFree(rkpm); } u_int8_t rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb) { #ifdef RKP_DEBUG - printk("rkpManager_execute\n"); + printk("rkp-ua: rkpManager_execute start.\n"); printk("\tsyn %d ack %d\n", tcp_hdr(skb) -> syn, tcp_hdr(skb) -> ack); printk("\tsport %d dport %d\n", tcp_hdr(skb) -> source, tcp_hdr(skb) -> dest); printk("\tid %d\n", (ntohs(tcp_hdr(skb) -> source) + ntohs(tcp_hdr(skb) -> dest)) & 0xFF); #endif + __rkpManager_lock(rkpm); + rkpm -> last_active = now(); if(rkpSettings_first(skb)) // 新增加一个流或覆盖已经有的流 { @@ -57,14 +65,11 @@ u_int8_t rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb) printk("\nAdd a stream id=%u.\n", id); #endif if(rkps_new == 0) - { - printk("rkp-ua::rkpStream::rkpStream_new: `kmalloc` failed, may caused by shortage of memory.\n"); - return NF_DROP; - } + return NF_ACCEPT; // 查找可能的重复的流并删除 while(rkps != 0) - if(rkpStream_belong(rkps, skb)) + if(rkpStream_belongTo(rkps, skb)) { printk("Found same stream %u.\n", id); if(rkps -> prev != 0) @@ -73,7 +78,8 @@ u_int8_t rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb) rkps -> next -> prev = rkps -> prev; if(rkps == rkpm -> data[id]) rkpm -> data[id] = rkps -> next; - rkpStream_del(rkps); + rkpStream_delete(rkps); + rkps = rkpm -> data[id]; break; } else @@ -97,10 +103,10 @@ u_int8_t rkpManager_execute(struct rkpManager* rkpm, struct sk_buff* skb) u_int8_t id = (ntohs(tcp_hdr(skb) -> source) + ntohs(tcp_hdr(skb) -> dest)) & 0xFF; struct rkpStream* rkps = rkpm -> data[id]; #ifdef RKP_DEBUG - printk("rkpStream_belong %d\n", (int)rkpStream_belong(rkps, skb)); + printk("rkpStream_belong %d\n", (int)rkpStream_belongTo(rkps, skb)); #endif while(rkps != 0) - if(rkpStream_belong(rkps, skb)) + if(rkpStream_belongTo(rkps, skb)) return rkpStream_execute(rkps, skb); else rkps = rkps -> next; @@ -126,10 +132,19 @@ void rkpManager_refresh(struct rkpManager* rkpm) rkps -> next -> prev = rkps -> prev; if(rkps == rkpm -> data[i]) rkpm -> data[i] = rkps -> next; - rkpStream_del(rkps); + rkpStream_delete(rkps); rkps = rkps2; } else rkps = rkps -> next; } +} + +void __rkpManager_lock(struct rkpManager* rkpm) +{ + mutex_lock(rkpm -> lock); +} +void __rkpManager_unlock(struct rkpManager* rkpm) +{ + mutex_unlock(rkpm -> lock); } \ No newline at end of file diff --git a/src/rkpPacket.h b/src/rkpPacket.h index f2e1add..641fc45 100644 --- a/src/rkpPacket.h +++ b/src/rkpPacket.h @@ -16,13 +16,12 @@ 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*); +int32_t rkpPacket_seq(struct rkpPacket*); +int32_t rkpPacket_ack(struct rkpPacket*); bool rkpPacket_psh(struct rkpPacket*); -bool rkpPacket_scan(struct rkpPacket*, unsigned char*, unsigned*); // 搜索指定字符串,已匹配的长度存入第三个参数,返回是否完全匹配到了 - void rkpPacket_csum(struct rkpPacket*); +bool rkpPacket_makeWriteable(struct rkpPacket*); struct rkpPacket* rkpPacket_new(struct sk_buff* skb) { @@ -91,14 +90,18 @@ 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) +int32_t rkpPacket_seq(struct rkpPacket* p) { return ntohl(tcp_hdr(p -> skb) -> seq); } -u_int32_t rkpPacket_ack(struct rkpPacket* p) +int32_t rkpPacket_ack(struct rkpPacket* p) { return ntohl(tcp_hdr(p -> skb) -> ack); } +bool rkpPacket_psh(struct rkpPacket* rkpp) +{ + return tcp_hdr(rkpp -> skb) -> psh; +} void rkpPacket_csum(struct rkpPacket* p) { @@ -110,9 +113,23 @@ void rkpPacket_csum(struct rkpPacket* p) 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); + 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); #ifdef RKP_DEBUG printk("rkp-ua: rkpPacket_csum end.\n"); #endif +} + +bool rkpPacket_makeWriteable(struct rkpPacket* rkpp) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) + if(skb_ensure_writable(rkpp -> skb, rkpPacket_appEnd(rkpp) - (unsigned char*)rkpp -> skb -> data) || rkpp -> skb -> data == 0) +#else + if(!skb_make_writable(rkpp -> skb, rkpPacket_appEnd(rkpp)- (unsigned char*)rkpp -> skb -> data) || rkpp -> skb -> data == 0) +#endif + { + printk("rkp-ua: rkpPacket_makeWriteable: failed.\n"); + return false; + } + return true; } \ No newline at end of file diff --git a/src/rkpSettings.h b/src/rkpSettings.h index f7f5cd5..1a05c5b 100644 --- a/src/rkpSettings.h +++ b/src/rkpSettings.h @@ -1,27 +1,24 @@ #pragma once #include "common.h" -static bool mode_advanced = false; -module_param(mode_advanced, bool, 0); +static bool autocapture = true; +module_param(autocapture, bool, 0); static char* str_preserve[128]; static unsigned n_str_preserve = 0; module_param_array(str_preserve, charp, &n_str_preserve, 0); -static u_int32_t mark_capture = 0x100; +_Static_assert(sizeof(int) == 4, "int is not 4 bit."); +static unsigned mark_capture = 0x100; module_param(mark_capture, uint, 0); -static u_int32_t mark_first = 0x200; +static unsigned mark_first = 0x200; module_param(mark_first, uint, 0); -static u_int32_t mark_preserve = 0x400; -module_param(mark_preserve, uint, 0); static unsigned time_keepalive = 1200; module_param(time_keepalive, uint, 0); bool rkpSettings_capture(const struct sk_buff*); -bool rkpSettings_request(const struct sk_buff*); bool rkpSettings_first(const struct sk_buff*); -bool rkpSettings_preserve(const struct sk_buff*); bool rkpSettings_capture(const struct sk_buff* skb) { @@ -31,10 +28,10 @@ bool rkpSettings_capture(const struct sk_buff* skb) return false; #endif - if(mode_advanced) + if(!autocapture) { #ifdef RKP_DEBUG - printk("\tadvanced return %d", (skb -> mark & mark_capture) == mark_capture); + printk("\tadvanced return %d", (skb -> mark & mark_capture) == mark_capture); #endif return (skb -> mark & mark_capture) == mark_capture; } @@ -42,25 +39,19 @@ bool rkpSettings_capture(const struct sk_buff* skb) { if(ip_hdr(skb) -> protocol != IPPROTO_TCP) return false; - else if(ntohs(tcp_hdr(skb) -> dest) == 80) - return true; - else if(ntohs(tcp_hdr(skb) -> source) == 80 && tcp_hdr(skb) -> ack) - return true; - else + else if(ntohs(tcp_hdr(skb) -> dest) != 80) return false; + else if((ntohl(ip_hdr(skb) -> saddr) & 0xFFFF0000) != (192 << 24) + (168 << 16) + || (ntohl(ip_hdr(skb) -> daddr) & 0xFFFF0000) == (192 << 24) + (168 << 16)) + return false; + else + return true; } } bool rkpSettings_first(const struct sk_buff* skb) { - if(mode_advanced) + if(!autocapture) return (skb -> mark & mark_first) == mark_first; else return tcp_hdr(skb) -> syn && !tcp_hdr(skb) -> ack; -} -bool rkpSettings_preserve(const struct sk_buff* skb) -{ - if(mode_advanced) - return (skb -> mark & mark_preserve) == mark_preserve; - else - return true; } \ No newline at end of file diff --git a/src/rkpStream.h b/src/rkpStream.h index 6ff9f42..2f1015a 100644 --- a/src/rkpStream.h +++ b/src/rkpStream.h @@ -29,25 +29,9 @@ 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 头的结尾 +bool __rkpStream_scan(struct rkpStream*, struct rkpPacket*); // 在包的应用层搜索 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*); // 复制一个数据包 -void __rkpStream_skb_del(struct sk_buff*); // 删除一个数据包 -void __rkpStream_skb_csum(struct sk_buff*); // 重新计算 tcp 和 ip 的校验和 - -u_int16_t __rkpStream_data_scan(const unsigned char*, u_int16_t, const unsigned char*, u_int8_t); // 在指定字符串中扫描子字符串。返回值最低位表示是否完整地找到,其余 15 位表示匹配的长度(如果没有完整地找到)或子串结束时相对于起始时的位置 -void __rkpStream_data_replace(unsigned char*, u_int16_t, const unsigned char*, u_int16_t); // 替换字符串。最后一个参数表明已经替换了多少个字节。其它参数与前者类似。 - -void __rkpStream_buff_retain_end(struct sk_buff**, struct sk_buff*); // 将一个数据包置入数据包链的末尾 -void __rkpStream_buff_retain_auto(struct sk_buff**, struct sk_buff*); // 将一个数据包置入数据包链的合适位置 -void __rkpStream_buff_rejudge(struct rkpStream*, struct sk_buff**); // 重新判定数据包链中的每个数据包 -struct sk_buff* __rkpStream_buff_find(const struct sk_buff*, u_int32_t); -// 在一个已经按照序列号排序的数据包链中寻找序列号相符的包。如果没有相符的包,就返回最后一个序列号比要求的小的包。如果没有这样的包,就返回 0。第二个参数是要查找的序列号(绝对值,已转换字节序) - -void __rkpStream_buff_execute_core(struct sk_buff**, u_int16_t, bool); // 最核心的步骤,集齐头部后被调用。搜索、替换。参数分别为:数据包链表、最后一个包中 http 头最后一个字节的位置、是否保留指定 ua - struct rkpStream* rkpStream_new(const struct sk_buff* skb) { #ifdef RKP_DEBUG @@ -65,8 +49,8 @@ struct rkpStream* rkpStream_new(const struct sk_buff* skb) 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_scan = rkps -> buff_disordered = rkps -> buff_sent = 0; - rkps -> seq_offset = ntohl(skb -> seq) + 1; + rkps -> buff_scan = rkps -> buff_disordered = 0; + rkps -> seq_offset = ntohl(tcp_hdr(skb) -> seq) + 1; rkps -> last_active = now(); rkps -> scan_matched = 0; rkps -> prev = rkps -> next = 0; @@ -80,61 +64,37 @@ void rkpStream_delete(struct rkpStream* rkps) #ifdef RKP_DEBUG printk("rkp-ua: rkpStream_delete start.\n"); #endif - for(struct rkpPacket* p = rkps -> buff_scan; p != 0;) + struct rkpPacket* p; + for(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;) + for(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) +bool rkpStream_belongTo(const struct rkpStream* rkps, const struct sk_buff* skb) { #ifdef RKP_DEBUG 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)) - rtn = false; - if(rkps -> id[1] != ntohl(ip_hdr(skb) -> daddr)) - rtn = false; - if(rkps -> id[2] != (((u_int32_t)ntohs(tcp_hdr(skb) -> source)) << 16) + ntohs(tcp_hdr(skb) -> dest)) - rtn = false; - rtn = true; - } - else - { - if(rkps -> id[0] != ntohl(ip_hdr(skb) -> daddr)) - rtn = false; - if(rkps -> id[1] != ntohl(ip_hdr(skb) -> saddr)) - rtn = false; - if(rkps -> id[2] != (((u_int32_t)ntohs(tcp_hdr(skb) -> dest)) << 16) + ntohs(tcp_hdr(skb) -> source)) - rtn = false; - rtn = true; - } + bool rtn = rkps -> id[0] == ntohl(ip_hdr(skb) -> saddr) + && rkps -> id[1] == ntohl(ip_hdr(skb) -> daddr) + && rkps -> id[2] == (((u_int32_t)ntohs(tcp_hdr(skb) -> source)) << 16) + ntohs(tcp_hdr(skb) -> dest); #ifdef RKP_DEBUG printk("rkp-ua: rkpStream_belongTo end, will return %d.\n", rtn); #endif @@ -163,7 +123,7 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) // 接下来从小到大考虑数据包的序列号的几种情况 // 已经发出的数据包,直接忽略 - if(int32_t(rkpPacket_seq(p) - rkps -> seq_offset) < 0) + if(rkpPacket_seq(p) - rkps -> seq_offset < 0) { #ifdef RKP_DEBUG printk("\tsent packet judged.\n"); @@ -172,7 +132,7 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) return NF_ACCEPT; } // 已经放到 buff_scan 中的数据包,丢弃 - if(int32_t(rkpPacket_seq(p) - rkps -> seq_offset) < __rkpStream_seq_scanEnd(rkps)) + if(rkpPacket_seq(p) - rkps -> seq_offset < __rkpStream_seq_scanEnd(rkps)) { #ifdef RKP_DEBUG printk("\tcaptured packet judged.\n"); @@ -182,12 +142,12 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) } // 恰好是 buff_scan 的后继数据包,这种情况比较麻烦,写到最后 // 乱序导致还没接收到前继的数据包,放到 buff_disordered - if(int32_t(rkpPacket_seq(p) - rkps -> seq_offset) > __rkpStream_seq_scanEnd(rkps)) + if(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); + __rkpStream_insert_auto(rkps, &(rkps -> buff_disordered), p); return NF_STOLEN; } @@ -204,7 +164,7 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) #endif // 丢到 buff_scan 里 __rkpStream_insert_end(rkps, &(rkps -> buff_scan), p); - if(__rkpStream_scan(rkps, p, str_head_end)) // 扫描到了 + if(__rkpStream_scan(rkps, p)) // 扫描到了 { #ifdef RKP_DEBUG printk("\t\t\thttp head end matched.\n"); @@ -212,7 +172,8 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) // 替换 ua __rkpStream_modify(rkps); // 发出数据包,注意最后一个不发,等会儿 accept 就好 - for(struct rkpPacket* p = rkps -> buff_scan; p != 0 && p -> next != 0;) + struct rkpPacket* p; + for(p = rkps -> buff_scan; p != 0 && p -> next != 0;) { struct rkpPacket* p2 = p; p = p -> next; @@ -245,7 +206,8 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) #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* p; + for(p = rkps -> buff_scan; p != 0 && p -> next != 0;) { struct rkpPacket* p2 = p; p = p -> next; @@ -315,242 +277,294 @@ unsigned rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb) } return rtn; - } } -u_int16_t __rkpStream_data_scan(const unsigned char* data, u_int16_t data_len, const unsigned char* target, u_int8_t matched) +int32_t __rkpStream_seq_scanEnd(struct rkpStream* rkps) { - const unsigned char* p = data; - while(p - data != data_len) - { - if(*p == target[matched]) - matched++; - else - matched = 0; - if(matched == strlen(target)) - return (((u_int16_t)(p - data) << 1)) | 0x1; - else - p++; - } - return matched << 1; -} -void __rkpStream_data_replace(unsigned char* data, u_int16_t data_len, const unsigned char* target, u_int16_t modified) -{ - while(modified < strlen(target) && data_len > 0) - { - *data = target[modified]; - data++; - data_len--; - modified++; - } - if(data_len > 0) - memset(data, ' ', data_len); -} - -void __rkpStream_buff_retain_end(struct sk_buff** buff, struct sk_buff* skb) -{ - struct sk_buff* p = *buff; - if(p == 0) - { - *buff = skb; - skb -> next = 0; - skb -> prev = 0; - } - else - { - while(p -> next != 0) - p = p -> next; - p -> next = skb; - skb -> next = 0; - skb -> prev = p; - } -} -void __rkpStream_buff_retain_auto(struct sk_buff** buff, struct sk_buff* skb) -{ - struct sk_buff* p = __rkpStream_buff_find(*buff, ntohl(tcp_hdr(skb) -> seq)); - if(p == 0) - { - skb -> prev = 0; - skb -> next = *buff; - *buff = skb; - if(skb -> next != 0) - skb -> next -> prev = skb; - } - else if(ntohl(tcp_hdr(p) -> seq) == ntohl(tcp_hdr(skb) -> seq)) - { - if(p -> prev != 0) - p -> prev -> next = skb; - if(p -> next != 0) - p -> next -> prev = skb; - skb -> prev = p -> prev; - skb -> next = p -> next; - if(*buff == p) - *buff = skb; - __rkpStream_skb_del(p); - } - else - { - if(p -> next != 0) - p -> next -> prev = skb; - skb -> next = p -> next; - p -> next = skb; - skb -> prev = p; - } -} - -struct sk_buff* __rkpStream_buff_find(const struct sk_buff* skb, u_int32_t seq) -{ - if(skb == 0) + struct rkpPacket* rkpp = rkps -> buff_scan; + if(rkpp == 0) return 0; else - { - while(skb -> next != 0 && __rkpStream_skb_seq(seq, ntohl(tcp_hdr(skb -> next) -> seq)) <= 0) - skb = (const struct sk_buff*)skb -> next; - return (struct sk_buff*)skb; - } + for(; ; rkpp = rkpp -> next) + if(rkpp -> next == 0) + return rkpPacket_seq(rkpp) - rkps -> seq_offset + rkpPacket_appLen(rkpp); + } -void __rkpStream_buff_execute_core(struct sk_buff** buff, u_int16_t last_pos, bool preserve) -// 扫描是否有 ua,然后扫描 ua 中是否有匹配的字符串,并且进行修改 +void __rkpStream_insert_auto(struct rkpStream* rkps, struct rkpPacket** buff, struct rkpPacket* p) { - u_int16_t rtn; - struct sk_buff* p; - unsigned i; - - struct sk_buff *skb_ua_begin, *skb_ua_end; - u_int16_t pos_ua_begin, pos_ua_end; - #ifdef RKP_DEBUG - printk("__rkpStream_buff_execute_core\n"); - printk("\tlast_pos %u\n", last_pos); - printk("\tpreserve %d\n", preserve); - printk("\tstart find ua start.\n"); + printk("rkp-ua: __rkpStream_insert_auto start.\n"); #endif - - // 寻找 ua 开始的位置 - for(p = *buff, rtn = 0; p != 0; p = p -> next) + // 如果链表是空的,那么就直接加进去 + if(*buff == 0) { #ifdef RKP_DEBUG - printk("\tfind a packet.\n"); + printk("rkp-ua: __rkpStream_insert_auto: empty buff.\n"); #endif - if(p -> next == 0) - rtn = __rkpStream_data_scan(__rkpStream_skb_appBegin(p), last_pos + 1, str_ua_begin, rtn >> 1); - else - rtn = __rkpStream_data_scan(__rkpStream_skb_appBegin(p), __rkpStream_skb_appLen(p), str_ua_begin, rtn >> 1); - if(rtn & 0x1) - break; + *buff = p; + p -> prev = p -> next = 0; } - if(rtn & 0x1) - // 找到了 + // 又或者,要插入的包需要排到第一个,或者和第一个序列号重复了 + else if(rkpPacket_seq(*buff) - rkps -> seq_offset >= rkpPacket_seq(p) - rkps -> seq_offset) { -#ifdef RKP_DEBUG - printk("\tfound.\n"); -#endif - skb_ua_begin = p; - pos_ua_begin = (rtn >> 1) + 1; - } - else - // 没找到 - { -#ifdef RKP_DEBUG - printk("\tfound.\n"); -#endif - return; - } - - // 寻找 ua 结束的位置 - for(rtn = 0; p != 0; p = p -> next) - { - if(p == skb_ua_begin) + if(rkpPacket_seq(*buff) - rkps -> seq_offset == rkpPacket_seq(p) - rkps -> seq_offset) { - rtn = __rkpStream_data_scan(__rkpStream_skb_appBegin(p) + pos_ua_begin, __rkpStream_skb_appLen(p) - pos_ua_begin, str_ua_end, rtn >> 1); - // 这时得到的 rtn 是相对于扫描开始处的位置,因此如果确认扫描到了结尾,就需要再加上相对于应用层开始处的偏移 - if(rtn & 0x01) - rtn += pos_ua_begin << 1; +#ifdef RKP_DEBUG + printk("rkp-ua: __rkpStream_insert_auto: same seq. Drop it.\n"); +#endif + rkpPacket_drop(p); } else - rtn = __rkpStream_data_scan(__rkpStream_skb_appBegin(p), __rkpStream_skb_appLen(p), str_ua_end, rtn >> 1); - if(rtn & 0x1) - break; + { + (*buff) -> prev = p; + p -> next = *buff; + p -> prev = 0; + *buff = p; + } } - if(!(rtn & 0x01)) + // 接下来寻找最后一个序列号不比 p 大的包,插入到它的后面或者丢掉。 + else { - printk("rkp-ua::rkpStream::__rkpStream_buff_execute_core: UA end not found. Accept without modification.\n"); - return; + 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; + } } - // 肯定是可以找到结束位置的。 - // 如果找到的结束位置在靠近应用层数据开头的位置,那么真实的结束位置应该在上一个数据包 - if((rtn >> 1) < strlen(str_ua_end)) +#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) { - skb_ua_end = p -> prev; - pos_ua_end = __rkpStream_skb_appLen(skb_ua_end) - (strlen(str_ua_end) - (rtn >> 1) - 1) - 1; + *buff = p; + p -> next = p -> prev = 0; } else { - skb_ua_end = p; - pos_ua_end = (rtn >> 1) - strlen(str_ua_end); + 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 +} - // 检查 ua 是否需要忽略,如果需要忽略就忽略 - if(preserve) - for(i = 0; i < n_str_preserve; i++) +bool __rkpStream_scan(struct rkpStream* rkps, struct rkpPacket* rkpp) +{ +#ifdef RKP_DEBUG + printk("rkp-ua: __rkpStream_scan start.\n"); +#endif + unsigned char* p; + for(p = rkpPacket_appBegin(rkpp); p != rkpPacket_appEnd(rkpp); p++) + { + if(*p == str_head_end[rkps -> scan_matched]) + rkps -> scan_matched++; + else + rkps -> scan_matched = 0; + if(rkps -> scan_matched == strlen(str_head_end)) { - for(p = skb_ua_begin, rtn = 0;;p = p -> next) + 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; + } + } +#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_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; + + // 匹配 "User-Agent: " 的阶段 + 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++) + { + // 检查匹配 http 头结尾的情况 + if(*p == str_head_end[head_end_matched]) + head_end_matched++; + else + head_end_matched = 0; + if(head_end_matched == strlen(str_head_end)) { - const unsigned char* scan_begin; - u_int16_t scan_len; - if(p == skb_ua_begin) - scan_begin = __rkpStream_skb_appBegin(p) + pos_ua_begin; +#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++; + else + ua_begin_matched = 0; + if(ua_end_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 - scan_begin = __rkpStream_skb_appBegin(p); - if(p == skb_ua_end) - scan_len = (__rkpStream_skb_appBegin(p) + pos_ua_end) - scan_begin + 1; - else - scan_len = (__rkpStream_skb_appBegin(p) + __rkpStream_skb_appLen(p) - 1) - scan_begin + 1; - rtn = __rkpStream_data_scan(scan_begin, scan_len, str_preserve[i], rtn >> 1); - if(rtn & 0x1) - return; - if(p == skb_ua_end) - break; + p++; + // 将结果记录进去 + ua_begin_rkpp = rkpp; + ua_begin_p = p; + break; } } - -#ifdef RKP_DEBUG - printk("\tstr_ua_rkp %s\n", str_ua_rkp); - printk("\tskb_ua_end - skb_ua_begin %d\n", skb_ua_end - skb_ua_begin); - printk("\tpos_ua_end %d pos_ua_begin %d\n", pos_ua_end, pos_ua_begin); - // return; -#endif + } - // 替换 ua - for(p = skb_ua_begin, rtn = 0;;p = p -> next) + // 匹配 "\r\n" 和需要忽略的关键字的阶段 + keyword_matched = rkpMalloc(n_str_preserve * sizeof(unsigned)); + memset(keyword_matched, 0, n_str_preserve * sizeof(unsigned)); + for(;rkpp != 0 && ua_end_matched != strlen(str_ua_end); rkpp = rkpp -> next) { - unsigned char* replace_begin; - u_int16_t replace_len; - if(skb_ensure_writable(p, __rkpStream_skb_appBegin(p) + __rkpStream_skb_appLen(p) - p -> data) != 0) + unsigned char* p; + for(p = ua_begin_p; p != rkpPacket_appEnd(rkpp); p++) { - printk("rkp-ua::rkpStream::__rkpStream_buff_execute_core: Can not make skb writable, may caused by shortage of memory. Ignore it.\n"); - return; + // 检查匹配 "\r\n" 的情况 + if(*p == str_head_end[ua_end_matched]) + ua_end_matched++; + 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)) + { + 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; + // 记得删掉不用的内存 + rkpFree(keyword_matched); + break; + } + + // 检查匹配需要忽略的关键字的情况 + 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])) + { +#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; + } + } + } + } + + // 已经获得了所需要的信息并且确认 ua 需要替换,然后替换 ua 的阶段 + // 先全部 writeable + for(rkpp = ua_begin_rkpp; ; rkpp = rkpp -> next) + { + if(rkpp == ua_begin_rkpp && rkpp == ua_end_rkpp) + { + unsigned temp = ua_begin_p - rkpPacket_appBegin(rkpp); + if(!rkpPacket_makeWriteable(rkpp)) + return; + ua_end_p = rkpPacket_appBegin(rkpp) + temp + (ua_end_p - ua_begin_p); + ua_begin_p = rkpPacket_appBegin(rkpp) + temp; + break; + } + else if(rkpp == ua_begin_rkpp) + { + unsigned temp = ua_begin_p - rkpPacket_appBegin(rkpp); + if(!rkpPacket_makeWriteable(rkpp)) + return; + ua_begin_p = rkpPacket_appBegin(rkpp) + temp; + } + else if(rkpp == ua_end_rkpp) + { + unsigned temp = ua_end_p - rkpPacket_appBegin(rkpp); + if(!rkpPacket_makeWriteable(rkpp)) + return; + ua_end_p = rkpPacket_appBegin(rkpp) + temp; + break; } - if(p == skb_ua_begin) - replace_begin = __rkpStream_skb_appBegin(p) + pos_ua_begin; else - replace_begin = __rkpStream_skb_appBegin(p); - if(p == skb_ua_end) - replace_len = (__rkpStream_skb_appBegin(p) + pos_ua_end) - replace_begin + 1; + if(!rkpPacket_makeWriteable(rkpp)) + return; + } + // 然后放心大胆地替换字符串 + for(rkpp = ua_begin_rkpp; ; rkpp = rkpp -> next) + { + unsigned char* p; + if(rkpp == ua_begin_rkpp) + p = ua_begin_p; else - replace_len = (__rkpStream_skb_appBegin(p) + __rkpStream_skb_appLen(p) - 1) - replace_begin + 1; -#ifdef RKP_DEBUG - printk("\treplace_begin - appBegin %d\n", replace_begin - __rkpStream_skb_appBegin(p)); - printk("\treplace_len %d\n", replace_len); -#endif - __rkpStream_data_replace(replace_begin, replace_len, str_ua_rkp, rtn); -#ifdef RKP_DEBUG - printk("\tafter replace, data is %c%c%c%c%c\n", replace_begin[0], replace_begin[1], replace_begin[2], replace_begin[3], replace_begin[4]); -#endif - __rkpStream_skb_csum(p); - rtn += replace_len; - if(p == skb_ua_end) + 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; } -} \ No newline at end of file + // 重新计算校验和 + for(rkpp = ua_begin_rkpp; rkpp != 0 && rkpp -> prev != ua_end_rkpp; rkpp = rkpp -> next) + rkpPacket_csum(rkpp); +}