我有一个网络客户端卡在recvfrom
不受我控制的服务器中,经过24小时后,可能永远不会响应。该程序处理了大量数据,所以我不想杀死它;我希望它放弃当前的连接并继续。 (如果recvfrom
返回EOF或-1,它将正确执行。)我已经尝试了几个不同的程序,声称能够通过伪造RST来断开陈旧的TCP通道(tcpkill
,{{1} },cutter
);没有任何影响,该计划仍然停留在killcx
。我也尝试过关闭网络接口;再一次,没有效果。
在我看来,应该是一种在socket-API级别强制断开而不伪造网络数据包的方法。我不介意可怕的黑客攻击,包括手工挖掘内核数据结构;这是灾难恢复的情况。有什么建议吗?
(为清楚起见,此处涉及的TCP频道根据recvfrom
处于ESTABLISHED状态。)
答案 0 :(得分:4)
我不介意可怕的黑客
这就是你要说的。我猜测你尝试的工具不起作用,因为他们嗅到流量以获得可接受的ACK号来终止连接。没有交通流量,他们无法掌握它。
以下是您可以尝试的事项:
如果这些工具失败了,你仍然可以做到。制作一个简单的python脚本并使用scapy,为每个序列号发送一个RST
段,其中包含正确的4元组(端口和地址)。最多有40亿(假设一个不错的窗口实际上更少 - 你可以使用ss -i
免费找到窗口。)
让内核模块获取TCP套接字列表:查找sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[i].chain)
识别您的受害者sk
此时您可以密切访问您的套接字。所以
您可以在其上致电tcp_reset
或tcp_disconnect
。您将无法直接致电tcp_reset
(因为它没有EXPORT_SYMBOL
),但您应该能够模仿它:它调用的大部分功能都会被导出
或者您可以从tcp_sk(sk)
获取预期的ACK号码并使用scapy
直接伪造RST数据包
这是我用来打印已建立的套接字的函数 - 我在一段时间之前从内核中搜集了一些碎片:
#include <net/inet_hashtables.h>
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
#define NIPQUAD_FMT "%u.%u.%u.%u"
extern struct inet_hashinfo tcp_hashinfo;
/* Decides whether a bucket has any sockets in it. */
static inline bool empty_bucket(int i)
{
return hlist_nulls_empty(&tcp_hashinfo.ehash[i].chain);
}
void print_tcp_socks(void)
{
int i = 0;
struct inet_sock *inet;
/* Walk hash array and lock each if not empty. */
printk("Established ---\n");
for (i = 0; i <= tcp_hashinfo.ehash_mask; i++) {
struct sock *sk;
struct hlist_nulls_node *node;
spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, i);
/* Lockless fast path for the common case of empty buckets */
if (empty_bucket(i))
continue;
spin_lock_bh(lock);
sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[i].chain) {
if (sk->sk_family != PF_INET)
continue;
inet = inet_sk(sk);
printk(NIPQUAD_FMT":%hu ---> " NIPQUAD_FMT
":%hu\n", NIPQUAD(inet->inet_saddr),
ntohs(inet->inet_sport), NIPQUAD(inet->inet_daddr),
ntohs(inet->inet_dport));
}
spin_unlock_bh(lock);
}
}
你应该可以将它弹出一个简单的“Hello World”模块,在输入后,在dmesg
中你会看到套接字(很像ss
或netstat
)。< / p>
答案 1 :(得分:1)