少年,你知道tcp kill吗?
版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc
1.序言
有些读者在访问云服务器或者跳板机的时候,可能会发现如果一段时间不使用客户端,连接就自动断开了。
为什么要这么做呢?以跳板机举例,跳板机有时候被称作堡垒机,它类似于一个封闭的房子所开的窗户。跳板机负有身份验证,授权控制,安全审计等义务。
对机房内部任何主机的访问,都必须要访问跳板机。因此每个client都要与跳板机建立连接,跳板机的资源有限,所以通常会定期对闲置的client进行清理。
2.怎样清理空闲连接?
TCP协议header中有一个RST标识。
RST一般出现于异常情况,归类为 对端的端口不可用 和 socket提前关闭。
只需要向连接中任意一方发送带有RST标识的TCP包就可以迫使连接断开
但是需要注意的是,接收方收到RST包,首先会看下TCP包的seq是否合法,即seq是否在合法接收窗口范围内。如果不在范围内,这个RST包就会被丢弃。
2.1 获取合法的Seq
经过上面的分析,我们已经现在的问题是如何获取一个合法的Seq。仔细观察TCP header,
Acknowledgment Number
表示sender
期待的下一个序列号(Seq).Window
表示sender
还能够接收的数据大小
[Ack, Ack + Window] 一定是合法的Seq范围
通过抓包,并计算就可以得到一个Sender所能接受的Seq,从而成功的发起一次RST攻击。
2.2 Challenge Ack
但是如果这个连接非常空闲,一直无法抓到数据包怎么办?根据参考资料1的介绍,我们还可以使用Challenge Ack。使用任意的Seq,伪造一个带有SYN标识的TCP包,receiver
会发送带有正确Ack的Ack包给sender
, 这样我们也能快速获得合法的Seq。萌叔在项目vearne/grpcreplay 中也使用了这个技术。
3.网络工具Tcpkill
社区已经有开源工具tcpkill可以使用
3.1安装
Centos
sudo yum -y install dsniff
Ubuntu
sudo apt install dsniff
3.2 用法
tcpkill [-i interface] [-1..9] expression
-
第1个参数 -i 指定网卡设备
-
第2个参数指定强度
-
第3个参数
expression
是libcap抓包使用的过滤器expression
的写法与tcpdump命令中expression
的写法相同
3.3 常用命令
杀死来源端口或目标端口== 35001的连接
tcpkill −9 port 35001
杀死来自www.google.com的连接
tcpkill −9 host www.google.com
3.4 源码
tcpkill 源码可从参考资料4中下载,非常简单,一共不到200行。
由于接收方会自动丢弃不在接收窗口范围内的TCP包(通过seq判断)。在一个繁忙的TCP连接上,接收窗口的范围变化的非常快,因此可能多次重发,才能确保有一个TCP包落在接收方的接收窗口内。
Opt_severity
越大,沿着seq增大的方向重试次数越多。
void tcp_rst_loop(pcap_t *pd, int sock){
for (;;) {
if ((pkt = (char *)pcap_next(pd, &pkthdr)) != NULL) { // 按照expression捕获网络包
// Opt_severity 就是第2个参数,即强度
for (i = 0; i < Opt_severity; i++) {
// 发送带有RST标志的TCP包
seq = ack + (i * win);
tcp->th_seq = htonl(seq); // 设置seq
...
if (libnet_write_ip(sock, buf, sizeof(buf)) < 0)
warn("write_ip");
}
}
}
}
后记
2024年09月18日,golang也有对应的的tcpkill开源实现dushixiang/tcpwall
参考资料
3.Tcpkill
4.dsniff
5.TCP滑动窗口