V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
FreeEx
V2EX  ›  分享创造

tcpkill 在 go 语言下的实现和增强

  •  
  •   FreeEx ·
    dushixiang · 2020-10-29 13:04:33 +08:00 · 2202 次点击
    这是一个创建于 1265 天前的主题,其中的信息可能已经有所发展或是发生改变。

    tcpwall

    当我们想要阻止某些 TCP 连接的建立,在 Linux 平台上有一个很好的解决方案iptables,但是对那些已经建立的 tcp 连接,iptables 就不能做到随心所欲的阻断了。

    我在互联网上检索的时候发现了tcpkill这个工具,tcpkill 是一个网络分析工具集dsniff中的一个小工具。在 Linux 上可以直接通过 dsniff 包安装,使用方式也非常简单。

    通过测试我发现 tcpkill 在执行命令之后并不会立刻阻断 tcp 连接,而是等待有数据传输时,才会阻断,因此在执行完命令之后程序并不会主动退出,而是需要通过***Ctrl+C***来退出,这对于某些想要通过程序来调用的脚本小子(例如我)来说简直是个灾难。

    如何阻断一个已经建立的 tcp 连接?

    阻断一个已经建立的 tcp 连接通常有这几种方案:

    1. 服务端主动断开
    2. 客户端主动断开
    3. 拔掉网线(时间要超过 tcp 超时时间)
    4. 伪造 RST 数据包发送给服务端和客户端让它们主动断开( tcpkill 就是这么做的)

    前三种局限性太大,只能用第 4 种了。

    如何实现伪造 RST 数据报文包?

    GoPacket 是 go 基于libpcap构建的一个库,可以通过旁路的方式接收一份数据包的拷贝。因此我们可以很方便捕获到正在通信的 tcp 数据报文。通过数据报文,我们可以获取到通信双方的 MAC 地址,IP 和端口号,以及 ACK 号等,这些都是伪造数据包必不可少的。

    在学习了tcpkill的源码之后,我使用 go 开发了一个增强版的tcpwalltcpwall不仅可以实现和tcpkill同样的基于 ip 或端口监听到指定数据报文之后伪造 RST 数据报文来阻断 tcp 连接,也可以通过源 ip 源端口,目的 ip 目的端口来主动发送 SYN 数据报文包来诱导那些没有数据的 tcp 连接发送 ACK 数据报文包以获取源 MAC 、目的 MAC 和 ACK 号,并且可以通过指定参数让程序等待一段时间后主动退出。

    如何使用

    阻断指定 IP 和端口的 TCP 连接(不关心是源或者目的)

    tcpwall -i {interface} -host {host} -port {port}
    

    阻断指定源 IP 和源端口的 TCP 连接

    tcpwall -i {interface} -shost {src_host} -sport {src_port}
    

    阻断指定目的 IP 和目的端口的 TCP 连接

    tcpwall -i {interface} -dhost {dst_host} -dport {dst_port}
    

    阻断指定源 IP 、源端口、目的 IP 、目的端口的 TCP 连接(会主动向双方发送 SYN 数据报文包)

    tcpwall -i {interface} -shost {src_host} -sport {src_port} -dhost {dst_host} -dport {dst_port}
    

    其他

    • -timeout 时间(秒)指定等待多久之后退出程序

    项目地址 https://github.com/dushixiang/tcpwall

    7 条回复    2020-11-02 10:00:01 +08:00
    barathrum
        1
    barathrum  
       2020-10-29 14:03:30 +08:00
    iptables 有 reject-with tcp-reset,怎么就不能阻断已经建立的 tcp 连接了。
    est
        2
    est  
       2020-10-29 14:04:46 +08:00
    还有第五种方案,找到他们的 socket fileno,然后 close 掉。2333
    FreeEx
        3
    FreeEx  
    OP
       2020-10-29 15:04:52 +08:00
    @barathrum 主动试一下你就知道了
    FreeEx
        4
    FreeEx  
    OP
       2020-10-29 15:06:19 +08:00
    @est 听说这个命令也可以 rm -rf /* 哈哈
    DoctorCat
        5
    DoctorCat  
       2020-11-02 02:48:02 +08:00   ❤️ 4
    认同 @est 一行命令 close socket fd

    s=(`lsof -i tcp:8000 | sed -n "2, 1p" | awk '{print($4, $2)}'`) && sockfd=(`echo $s | awk '{print($1)}'`);pid=(`echo $s | awk '{print($2)}'`) && yes | gdb -ex 'call close($sockfd)' -ex 'quit' -p $pid
    est
        6
    est  
       2020-11-02 09:17:39 +08:00 via Android
    @DoctorCat 很好很暴力
    FreeEx
        7
    FreeEx  
    OP
       2020-11-02 10:00:01 +08:00 via iPhone
    @DoctorCat 🐂🍺啊
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5486 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:15 · PVG 17:15 · LAX 02:15 · JFK 05:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.