Files
xmurp-ua/src/rkpStream.h
2019-11-01 20:24:08 +08:00

262 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "common.h"
struct rkpStream
{
u_int8_t enum
{
__rkpStream_sniffing,
__rkpStream_waiting
} status;
u_int32_t id[3]; // 按顺序存储客户地址、服务地址、客户端口、服务端口,已经转换字节序
struct sk_buff *buff, *buff_prev, *buff_next;
u_int32_t seq_ack; // 下一个服务端确认收到的字节的序列号。以后所有的序列号都是以这个为基准的相对序列号。
u_int32_t seq; // 下一个期待收到的序列号。
time_t last_active;
u_int8_t scan_matched;
u_int8_t win_preserve;
struct rkpStream* next;
};
struct rkpStream* rkpStream_new(struct sk_buff*); // 构造函数,得到的流的状态是捕获这个数据包之前的状态。内存不够时返回 0。
void rkpStream_del(struct rkpStream*); // 析构函数
u_int8_t rkpStream_belong(struct rkpStream*, struct sk_buff*); // 判断一个数据包是否属于一个流
u_int8_t rkpStream_execute(struct rkpStream*, struct sk_buff*); // 处理一个数据包(假定包属于这个流)
void __rkpStream_refresh_ack(struct rkpStream*, u_int32_t); // 刷新确认序列号。第二个参数就是即将设定的确认号。会自动重新计算序列号的偏移,以及释放 buff_prev 中的多余数据包
unsigned char* __rkpStream_skb_appStart(struct sk_buff*); // 返回一个包的应用层数据起始位置
u_int16_t __rkpStream_skb_appLen(struct sk_buff*); // 返回一个包的应用层数据长度
int32_t __rkpStream_skb_seq(u_int32_t, u_int32_t); // 返回一个序列号的相对序列号。两个参数分别为流的确认号、包的序列号(已经转换字节序)。
void __rkpStream_skb_send(struct sk_buff*); // 发送一个数据包
struct sk_buff* __rkpStream_skb_copy(struct sk_buff*); // 复制一个数据包
void __rkpStream_skb_del(struct sk_buff*); // 删除一个数据包
u_int16_t __rkpStream_data_scan(unsigned char*, u_int16_t, unsigned char*, u_int8_t); // 在指定字符串中扫描子字符串。返回值最低位表示是否完整地找到,其余 15 位表示匹配的长度(如果没有完整地找到)或子串结束时相对于起始时的位置
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**); // 重新判定数据包链中的每个数据包
void __rkpStream_buff_del(struct sk_buff**); // 删除数据包链
struct sk_buff* __rkpStream_buff_find(struct sk_buff*, u_int32_t);
// 在一个已经按照序列号排序的数据包链中寻找序列号相符的包。如果没有相符的包,就返回最后一个序列号比要求的小的包。如果没有这样的包,就返回 0。第二个参数是要查找的序列号绝对值已转换字节序
void __rkpStream_buff_execute_core(struct sk_buff**, u_int16_t); // 最核心的步骤。集齐头部后,搜索、替换。
struct rkpStream* rpStream_new(struct sk_buff* skb)
{
struct rkpStream* rkps = kmalloc(sizeof(struct rkpStream), GFP_KERNEL);
struct iphdr* iph = ip_hdr(skb);
struct tcphdr* tcph = tcp_hdr(skb);
if(rkps == 0)
return rkps;
rkps -> status = rkpStream::__rkpStream_sniffing;
rkps -> id[0] = ntohl(iph -> saddr);
rkps -> id[1] = ntohl(iph -> daddr);
rkps -> id[2] = (((u_int32_t)ntohs(tcph -> sport)) << 16 ) + ntohs(tcph -> dport);
rkps -> buff = rkps -> buff_prev = rkps -> buff_next = 0;
rkps -> seq_ack = ntohl(tcph -> seq);
rkps -> seq = 1;
rkps -> last_active = now();
rkps -> scan_matched = 0;
rkps -> win_preserve = rkpSettings_winPreserve(skb);
rkps -> next = 0;
return rkps;
}
void rkpStream_del(struct rkpStream* rkps)
{
__rkpStream_buff_del(&(rkps -> buff));
__rkpStream_buff_del(&(rkps -> buff_prev));
__rkpStream_buff_del(&(rkps -> buff_next));
kfree(rkps);
}
u_int8_t rkpStream_belong(struct rkpStream* rkps, struct sk_buff* skb)
{
if(rkpSettings_request(skb))
{
if(rkps -> id[0] != ntohl(ip_hdr(skb) -> saddr))
return 0;
if(rkps -> id[1] != ntohl(ip_hdr(skb) -> daddr))
return 0;
if(rkps -> id[2] != ntohs(tcp_hdr(skb) -> sport) << 16 + ntohs(tcp_hdr(skb) -> dport);
return 0;
return 1;
}
else
{
if(rkps -> id[0] != ntohl(ip_hdr(skb) -> daddr))
return 0;
if(rkps -> id[1] != ntohl(ip_hdr(skb) -> saddr))
return 0;
if(rkps -> id[2] != ntohs(tcp_hdr(skb) -> dport) << 16 + ntohs(tcp_hdr(skb) -> sport);
return 0;
return 1;
}
}
u_int8_t rkpStream_execute(struct rkpStream* rkps, struct sk_buff* skb)
// 不要害怕麻烦,咱们把每一种情况都慢慢写一遍。
{
int32_t seq;
// 肯定需要更新时间
rkps -> last_active = now();
// 服务端返回确认包的情况,更新一下确认号,返回 sccept。以后的情况都是客户端发往服务端的了。
if(!rkpSettings_request(skb))
{
int32_t seq = __rkpStream_skb_seq(rkps -> seq_ack, ntohl(tcp_hdr(skb) -> ack_seq));
if(seq > 0)
char __rkpStream_refresh_ack(rkps, ntohl(tcp_hdr(skb) -> ack_seq));
return NF_ACCEPT;
}
// 不携带应用层数据的情况。直接接受即可。以后的情况,都是含有应用层数据的包了。
if(__rkpStream_skb_appLen(skb) == 0)
return NF_ACCEPT;
// 检查数据包是否是将来的数据包。如果是的话,需要放到 buff_next 等待处理。
seq = __rkpStream_skb_seq(rkps -> seq_ack, ntohl(tcp_hdr(skb) -> seq));
if(seq > rkps -> seq)
{
__rkpStream_buff_retain_auto(rkps -> buff_next, skb);
return NF_STOLEN;
}
// 检查数据包是否是已经被确认的数据包。应该不会出现这种情况。出现的话就把它丢掉吧。
if(seq < 0)
{
printk("rkp-ua::rkpStream: Re-transmission of asked package. Drop it.\n");
return NF_DROP;
}
// 检查数据包是否是重传数据包。如果是的话,可能需要修改数据。然后,将它发出。接下来的情况,就一定是刚好是需要的序列号的情况了
if(seq < rkps -> seq)
{
struct sk_buff* skb_prev = __rkpStream_buff_find(rkps -> buff_prev, ntohl(skb -> seq));
if(skb_prev != 0 && tcp_hdr(skb_prev) -> seq == tcp_hdr(skb) -> seq)
// 存在相符的数据包。将数据拷贝过去。
{
if(skb_ensure_writable(skb, __rkpStream_skb_appStart(skb) - skb -> data + __rkpStream_skb_appLen(skb)))
{
printk("rkp-ua::rkpStream::rkpStream_execute: Can not make skb writable, may caused by leasing memory. Drop it.\n");
return NF_DROP;
}
memcpy(__rkpStream_skb_appStart(skb), __rkpStream_skb_appStart(skb_prev), __rkpStream_skb_appLen(skb_prev));
}
return NF_ACCEPT;
}
// 如果是在 sniffing 的情况下,那一定先扫描一下再说
if(rkps -> status == __rkpStream_sniffing)
{
u_int16_t scan = __rkpStream_data_scan(__rkpStream_skb_appStart(skb), __rkpStream_skb_appLen(skb),
str_end, rkps -> scan_matched);
if(scan & 0x1)
// 扫描找到了 HTTP 头的结尾,那么将这个数据包补到 buff 中,更新 seq开始查找、替换、发出然后根据情况设置状态再考虑 buff_next 中的包,最后返回 STOLEN
{
struct sk_buff* skbp = rkps -> buff;
// 追加到 buff 后面
__rkpStream_buff_retain_end(&(rkps -> buff), skb);
rkps -> seq = __rkpStream_skb_seq(rkps -> ack_seq, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb);
// 查找、替换
__rkpStream_buff_execute_core(&(rkps -> buff), scan >> 1);
// 循环复制一份到 buff_prev 下面,同时发出
while(skbp != 0)
{
struct sk_buff* skbp2 = skbp -> next;
__rkpStream_buff_retain_end(rkps -> buff_prev, __rkpStream_skb_copy(skbp));
__rkpStream_skb_send(skbp);
skbp = skbp2;
}
// 清空查找情况,重新设置状态
rkps -> scan_length = 0;
if(!(tcp_hdr(skb) -> psh))
rkps -> status = waiting;
// 考虑之前截留的数据包
__rkpStream_buff_rejudge(rkps, &(skps -> buff_prev));
return NF_STOLEN;
}
else if(tcp_hdr(skb) -> psh)
// 如果没有找到却读到了 PUSH这就比较迷了。打印一句警告更新 seq然后把截留的包都放行然后考虑 buff_prev 里的数据。
{
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_seq, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb);
// 放行截留的包
while(skbp != 0)
{
struct sk_buff* skbp2 = skbp -> next;
__rkpStream_skb_send(skbp);
skbp = skbp2;
}
// 清空查找情况
rkps -> scan_length = 0;
// 考虑之前截留的数据包
__rkpStream_buff_rejudge(rkps, &(skps -> buff_prev));
return NF_ACCEPT;
}
else
// 没有找到结尾也没有push。那么将这个数据包补到 buff 中,更新 seq 和 查找状态,再考虑 buff_next 中的包,最后返回 STOLEN
{
// 追加到 buff
__rkpStream_buff_retain_end(rkps -> buff, skb);
// 更新 seq 和查找状态
rkps -> seq = __rkpStream_skb_seq(rkps -> ack_seq, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb);
rkps -> matched_length = scan >> 1;
// 考虑 buff_next 中的包
__rkpStream_buff_rejudge(rkps, &(skps -> buff_prev));
return NF_STOLEN;
}
}
else
// 如果是在 waiting 的状态下,那么设置 seq 和状态,然后考虑 buff_next 中的包,然后返回 ACCEPT 就可以了
{
// 设置 seq 和状态
rkps -> seq = __rkpStream_skb_seq(rkps -> ack_seq, ntohl(tcp_hdr(skb) -> seq)) + __rkpStream_skb_appLen(skb);
if(tcp_hdr(skb) -> psh)
rkps -> status = sniffing;
// 考虑 buff_next
__rkpStream_buff_rejudge(rkps, &(skps -> buff_prev));
return NF_ACCEPT;
}
}
void __rkpStream_refresh_ack(struct rkpStream* rkps, u_int32_t ack)
{
struct sk_buff* skbp;
// 重新计算 seq 偏移
rkps -> seq -= ack - rkps -> seq_ack;
// 丢弃 buff_prev 中已经确认收到的数据包
skbp = rkps -> buff_prev;
while(skbp != 0)
}
u_int16_t __rkpStream_dataLen(strct sk_buff* skb)
{
return ntohs(ip_hdr(skb) -> tot_len) - ip_hdr(skb) -> ihl * 4 - tcp_hdr(skb) -> doff * 4;
}