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

用 Rust 实现的端口敲门工具: Knock

  •  
  •   timothyye · 87 天前 · 3264 次点击
    这是一个创建于 87 天前的主题,其中的信息可能已经有所发展或是发生改变。

    周末想用最近学的 Rust 来练手一下,于是参考一个很古老的 C 语言实现的端口敲门程序 knock,用 Rust 实现了一个版本。

    Port Knocking 是一种网络安全技术,通过对服务器上的一系列预定义端口进行特定顺序的“敲门”(即发送数据包)来触发服务器上的一种反应,通常是打开一个原本关闭的端口,从而允许发起敲门序列的客户端建立连接。这种方法的优点在于,对外界而言,受保护的服务端口在没有接收到正确的敲门序列之前都是不可见的,从而增加了系统的安全性。

    这个工具分为客户端和服务器端两部分:

    服务器端 (knockd): 在服务器上运行,负责监听预设的一系列端口上的敲门尝试。当它检测到来自同一 IP 的特定序列时,会执行配置文件中定义的命令,如修改防火墙规则来允许来自该 IP 的连接。

    客户端 (knock-cli): 用于发起敲门序列。用户可以通过客户端配置文件指定目标服务器地址和敲门的端口序列。执行敲门动作后,如果服务器端正确识别了敲门序列,客户端的 IP 地址将被允许访问原本隐藏或受限的服务。

    项目地址: https://github.com/TimothyYe/knock

    欢迎 Star 和贡献 Pull Request.

    33 条回复    2024-03-05 17:36:20 +08:00
    Autonomous
        1
    Autonomous  
       87 天前
    支持一下,如果能用 docker 部署就更好了
    timothyye
        2
    timothyye  
    OP
       87 天前
    @Autonomous 因为这个程序需要监听系统的网络接口,容器里面应该也是可以的,我还没试过。可以的话我打包一个镜像。
    HiramWong
        3
    HiramWong  
       87 天前
    零信任的概念
    oneisall8955
        4
    oneisall8955  
       87 天前 via Android
    有意思
    8520ccc
        5
    8520ccc  
       87 天前 via iPhone
    感谢分享,另外有个小意见

    实现一个密钥加密是不是更好?

    防止重放攻击?
    timothyye
        6
    timothyye  
    OP
       87 天前
    @Autonomous 已经支持 docker 部署了,具体方法在 README 文件里面
    ETiV
        7
    ETiV  
       87 天前 via iPhone   ❤️ 1
    这图感觉像是在竖中指…然后中指前面肿了
    lovestudykid
        8
    lovestudykid  
       87 天前
    有点意思,但是为什么一定要用客户端呢?
    Geo200
        9
    Geo200  
       87 天前
    本地运行是否一定要容器呢?只是学习的话有没有更快本地运行的方法?
    timothyye
        10
    timothyye  
    OP
       87 天前 via Android
    @lovestudykid 不用也可以的,可以按照端口顺序连续用 telnet 去连接,用客户端方便的地方是可以配置多个规则,只要记住常用的规则名称就可以使用了。
    timothyye
        11
    timothyye  
    OP
       87 天前 via Android
    @Geo200 可以本地修改好配置文件直接运行 knockd
    timothyye
        12
    timothyye  
    OP
       87 天前 via Android
    @ETiV 有才,这个图其实是 GPT 帮我生成的
    a1210968738
        13
    a1210968738  
       87 天前 via Android
    是不是也可以考虑通过 HTTPS 协议搞个简单的管理页面( basic 鉴权保证安全性),支持列出当前白名单列表,支持单个添加和移除,以及批量移除。
    timothyye
        14
    timothyye  
    OP
       87 天前
    @a1210968738 你说的这个白名单是直接添加到 iptables 的客户端 IP 的白名单?
    Autonomous
        15
    Autonomous  
       87 天前 via iPhone
    @timothyye 应该是没问题的,我的 fail2ban 也是在 docker 容器内,用的 host 模式
    fenglangjuxu
        16
    fenglangjuxu  
       87 天前 via iPhone
    类似对暗号
    timothyye
        17
    timothyye  
    OP
       87 天前
    @Autonomous #15 嗯,是这样的,host 模式,然后启动的时候需要给容器一些特殊的权限。
    timothyye
        18
    timothyye  
    OP
       87 天前
    @fenglangjuxu 是这样的,这个概念 Wikipedia 上有详细的介绍 https://en.wikipedia.org/wiki/Port_knocking
    Motorola3
        19
    Motorola3  
       87 天前
    有意思 好奇实现逻辑是什么样的
    敲门是走 80/443 然后通过对应的密码 然后系统再去打开对应的端口吗
    timothyye
        20
    timothyye  
    OP
       87 天前
    @Motorola3 实现逻辑就是服务端程序监听网卡的原始流量包,根据配置文件中被配置为敲门的端口,过滤出客户端 IP ,当一个客户端连续按照顺序连接这些敲门端口的时候,就可以匹配到对应的规则了,然后后端程序会去执行规则配置好的操作 iptables 的命令,打开被保护的 SSH ,或者其他端口。并且这个端口通过 iptables 命令设置成只允许这个敲门的客户端的 IP 去连接。由于服务端是过滤网卡的数据包,所以不需要监听任何端口,也不占用任何端口。

    敲门不是走 80/443 ,是服务端程序直接监听网卡的数据包。
    Motorola3
        21
    Motorola3  
       87 天前
    @timothyye 那这样的话是不是 vps 没法用这个呀 vps 似乎不像是 ECS 有独立的网卡
    timothyye
        22
    timothyye  
    OP
       87 天前
    @Motorola3 #21 有的,一般就是 VPS 里面绑定公网 IP 那个网卡,你可以用 ifconfig 看看。我测试这个服务端就是用的 VPS
    a1210968738
        23
    a1210968738  
       86 天前 via Android
    @timothyye 是的
    timothyye
        24
    timothyye  
    OP
       86 天前 via Android
    @a1210968738 这样的话相当于封装了个 iptables 的网页版的功能?
    xianzhe
        25
    xianzhe  
       86 天前 via Android
    感觉五楼的疑问有道理,怎么防止流量重放攻击?
    timothyye
        26
    timothyye  
    OP
       86 天前 via Android
    @8520ccc @xianzhe 不过按照现在的实现,服务端检查客户端的敲门行为是在 TCP 握手的第一阶段,客户端向服务器发送一个 SYN (同步)数据包的时候,这样服务端不用去监听任何端口,也不用占用任何端口。至于如果这种 TCP 握手的包被记录下来重放的话,那应该是防范不了。不过这里提到的密钥加密是指要加密这种 SYN 的数据包吗?

    其实如果就算通过流量重放敲门正确打开了服务端的端口,比如 ssh 端口,ssh 本身也有自己的保护和认证。这种端口敲门主要的场景还是防止互联网上大批量的端口扫描和密码暴力猜解的行为。
    iqoo
        27
    iqoo  
       86 天前
    命令行版的用在特定用户的场合可以,如果是给公共用户使用就有些麻烦,得下载一个敲门工具。

    之前做了个网页版的演示,直接用 JS 发 UDP 包敲门: https://www.etherdream.com/port-knocking/
    iqoo
        28
    iqoo  
       86 天前
    可以在这个基础上加强一下,前后端都用 rust 实现。前端编译成 wasm 生成敲门认证串,后端用同一套算法解串,成功后把 ip 加到 ipset 白名单里。
    a1210968738
        29
    a1210968738  
       86 天前 via Android
    @timothyye 对,这样不需要额外的客户端,实用性和易用性都好很多
    timothyye
        30
    timothyye  
    OP
       86 天前
    @iqoo #27 这样的话服务端需要先监听某个端口来获取网页的 UDP 包?
    看来设计的理念有点不同,我是希望服务端不监听和占用任何端口
    iqoo
        31
    iqoo  
       86 天前
    @timothyye 不用监听。配个 iptables 策略直接把包从内核转到用户态就可以。或者用 libpcap 抓符合条件的包也可以,目标端口可以任意。
    timothyye
        32
    timothyye  
    OP
       86 天前
    @timothyye #30 学习了
    matate
        33
    matate  
       85 天前
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4947 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 09:25 · PVG 17:25 · LAX 02:25 · JFK 05:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.