爱意满满的作品展示区。
dushixiang
6.64D

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

  •  
  •   dushixiang ·
    dushixiang · Oct 29, 2020 · 2793 views
    This topic created in 2069 days ago, the information mentioned may be changed or developed.

    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 replies    2020-11-02 10:00:01 +08:00
    barathrum
        1
    barathrum  
       Oct 29, 2020
    iptables 有 reject-with tcp-reset,怎么就不能阻断已经建立的 tcp 连接了。
    est
        2
    est  
       Oct 29, 2020
    还有第五种方案,找到他们的 socket fileno,然后 close 掉。2333
    dushixiang
        3
    dushixiang  
    OP
       Oct 29, 2020
    @barathrum 主动试一下你就知道了
    dushixiang
        4
    dushixiang  
    OP
       Oct 29, 2020
    @est 听说这个命令也可以 rm -rf /* 哈哈
    DoctorCat
        5
    DoctorCat  
       Nov 2, 2020   ❤️ 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  
       Nov 2, 2020 via Android
    @DoctorCat 很好很暴力
    dushixiang
        7
    dushixiang  
    OP
       Nov 2, 2020 via iPhone
    @DoctorCat 🐂🍺啊
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   936 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 21:49 · PVG 05:49 · LAX 14:49 · JFK 17:49
    ♥ Do have faith in what you're doing.