写了个 Go 库:在 TCP 应用协议开始前做认证,也支持端口敲门 - V2EX
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
UG4anS3JspYD

写了个 Go 库:在 TCP 应用协议开始前做认证,也支持端口敲门

  •  
  •   UG4anS3JspYD 7h 12m ago 522 views

    最近整理了一个 Go 库,叫 libknock 。

    它解决的问题比较窄: 有些 TCP 服务不太想让随机连接直接打到应用协议解析层,比如内部管理端口、agent/collector 、私有 RPC 、gRPC 服务、自定义 TCP 协议之类。

    传统做法一般是:

    • 直接暴露 TCP 端口,让 TLS / HTTP / gRPC / 业务协议自己处理
    • 前面再套一层 proxy / gateway
    • 靠防火墙、VPN 、内网环境隔离
    • 或者用 port knocking 临时放行来源 IP

    libknock 的思路是把这类能力做成 Go 里的底层网络库,放在 net.Listener / net.Dialer 这一层。

    服务端大概是:

    ln, _ := net.Listen("tcp", ":9000") ln = libknock.WrapListener(ln, knockCfg) for { conn, err := ln.Accept() if err != nil { return err } go handleConn(conn) } 

    客户端大概是:

    d := libknock.Dialer{ Base: &net.Dialer{}, Config: knockCfg, } conn, err := d.DialContext(ctx, "tcp", "example.com:9000") 

    连接建立后,客户端先发一个 binary auth frame 。服务端验证 client secret 、timestamp 、nonce 、replay cache ,通过以后才把一个干净的 net.Conn 交给上层程序。

    也就是说,上层协议不用知道 libknock 存在。 如果后面是 TLS ,TLS 看到的还是正常 ClientHello ;如果后面是自定义 TCP 协议,业务 handler 看到的就是自己的业务首包。

    除了 TCP 前置认证,也可以组合 port knocking / firewall gate:

    client -> knock -> temporary allow / session -> TCP connect -> TCP pre-auth -> application protocol 

    不过它不是传统意义上的“端口敲门工具”。port knocking 只是可选的一层 gate ;核心还是 Go 程序可嵌入的 TCP pre-application authentication SDK 。

    主要特性:

    • Go 原生 net.Listener / net.Dialer 包装
    • TCP 建连后、应用协议开始前认证
    • binary auth frame
    • client secret 校验
    • timestamp window
    • nonce replay 防护
    • 认证失败默认直接关闭连接
    • 不解析、不修改上层应用协议
    • 可用于普通 TCP 、自定义二进制协议、TLS 、HTTP 、gRPC
    • 可选 port knocking / firewall gate / relay gateway

    适合的场景大概是:

    • 内部管理端口
    • agent / collector 长连接
    • 私有 RPC / gRPC 服务
    • 自定义 TCP 协议
    • 数据采集、边缘节点、运维控制面
    • 不想让应用协议析器直接面对随机 TCP 输入的服务

    不适合的场景:

    • 想要开箱即用保护任意未改造二进制程序,这种更适合 relay/gateway
    • 想替代 TLS / mTLS / 业务鉴权
    • 想做 VPN 或完整隧道
    • 只想要一个传统 knockd 替代品

    现在还在早期阶段,主要想看看有没有人对这种“TCP pre-application authentication + optional port knocking”的组合有类似需求。

    仓库地址: https://github.com/libknock/libknock

    欢迎拍砖,尤其是 Go API 设计、net.Conn 包装方式、port knocking 和 TCP auth 的边界、安全默认值这几块。

    3 replies    2026-05-18 21:01:50 +08:00
    povsister
        1
    povsister  
       6h 55m ago via iPhone
    我们在生产环境遇到过有 bug 应用创建 slow tcp 和半开连接,导致目标应用 oom 。所以有没有什么能在 ip 层防御的,不进协议栈的那种
    lesismal
        2
    lesismal  
       5h 39m ago
    我之前有写个自己用着玩的,如果只是简单的握手、tcp 连接后先发个密码、校验就可以了,但是后续流量防不住流量监控、如果流量加密则不需要刚开始的握手阶段密码校验了,所以只做了加密,但是支持用户自己传入 Listen 、Dial:
    https://github.com/lesismal/pipe

    另外,握手阶段简单密码校验,前阵子刚好有这个需求,懒得自己写,发给 AI ,AI 几分钟就完整实现了一层 wrapper ,几十行代码,并且一把过:
    https://gist.github.com/lesismal/2f7f1fbec4c73282f19124b2cb6c1254
    lesismal
        3
    lesismal  
       5h 25m ago
    AI 太强了,去年中 sonnet 4.0 还是 4.1 之后,我就基本放弃自己手写了、但去年还偶尔自己写一点点。

    之前觉得 golang 如果用标准库 sql 要手写很多 for 循环,根据 sql 语句生成 golang 代码的库涉及到复杂业务逻辑中间夹杂很多 sql 的,修改之类的也是很麻烦,sqlx 、ent 以及那几个 orm 库过于嗦而且很多没必要的东西增加学习成本而且性能、隐藏细节带来的工程问题远大于 orm 之类的所谓便利性,即使其他语言我也是抵制使用 orm 这类脏东西的(小项目谁爱用都 ok ,因为没有瓶颈)。
    其实标准库 sql 包主要就是需要手写 for 循环 rows scan 这块麻烦,binding 搞好就轻松的多,所以自己搞了个 https://github.com/lesismal/sqlw ,以前自己用这个。

    但是 AI 来了,AI 不怕手写 for rows scan 这些的麻烦,所以现在我连自己的 sqlw 都不用了,全丢给 AI ,代码我也不 review ,让 AI 自己加适当的日志、监控各种,然后让 AI 自己分析慢日志之类的进行优化。剩下的就是自己测试一些不容易被 AI 自动化发现的问题、然后反馈给 AI 让它修复和优化。

    最近一些人吐槽 bun 换 rust ,infoq 文章评论区里,infoq 的人竟然还用 viber coding 之前的方式去评价不可能那么快合并到主分支这相当于九品芝麻官里李总管那句“你用前朝的尚方宝剑斩本朝的官”,结果第二天就合并了。

    反正,我大概至少 8 、9 个月没有自己写过代码了。因为会聪明反被聪明误、自己觉得自己行非要瞎鼓捣然后耽误自己使用 AI 进步速度、也耽误自己和 AI 的配合度。

    让 AI 飞吧。
    About     Help     Advertise     Blog     API     FAQ     Solana     1094 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 47ms UTC 18:27 PVG 02:27 LAX 11:27 JFK 14:27
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86