


















最近整理了一个 Go 库,叫 libknock 。
它解决的问题比较窄: 有些 TCP 服务不太想让随机连接直接打到应用协议解析层,比如内部管理端口、agent/collector 、私有 RPC 、gRPC 服务、自定义 TCP 协议之类。
传统做法一般是:
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 。
主要特性:
net.Listener / net.Dialer 包装适合的场景大概是:
不适合的场景:
现在还在早期阶段,主要想看看有没有人对这种“TCP pre-application authentication + optional port knocking”的组合有类似需求。
仓库地址: https://github.com/libknock/libknock
欢迎拍砖,尤其是 Go API 设计、net.Conn 包装方式、port knocking 和 TCP auth 的边界、安全默认值这几块。
1 povsister 5 月 18 日 via iPhone我们在生产环境遇到过有 bug 应用创建 slow tcp 和半开连接,导致目标应用 oom 。所以有没有什么能在 ip 层防御的,不进协议栈的那种 |
3 lesismal 5 月 18 日AI 太强了,去年中 sonnet 4.0 还是 4.1 之后,我就基本放弃自己手写了、但去年还偶尔自己写一点点。 之前觉得 golang 如果用标准库 sql 要手写很多 for 循环,根据 sql 语句生成 golang 代码的库涉及到复杂业务逻辑中间夹杂很多 sql 的,修改之类的也是很麻烦,sqlx 、ent 以及那几个 orm 库过于啰嗦而且很多没必要的东西增加学习成本而且性能、隐藏细节带来的工程问题远大于 orm 之类的所谓便利性,即使其他语言我也是抵制使用 orm 这类脏东西的(小项目谁爱用都 ok ,因为没有瓶颈)。 但是 AI 来了,AI 不怕手写 for rows scan 这些的麻烦,所以现在我连自己的 sqlw 都不用了,全丢给 AI ,代码我也不 review ,让 AI 自己加适当的日志、监控各种,然后让 AI 自己分析慢日志之类的进行优化。剩下的就是自己测试一些不容易被 AI 自动化发现的问题、然后反馈给 AI 让它修复和优化。 最近一些人吐槽 bun 换 rust ,infoq 文章评论区里,infoq 的人竟然还用 viber coding 之前的方式去评价不可能那么快合并到主分支——这相当于九品芝麻官里李总管那句“你用前朝的尚方宝剑斩本朝的官”,结果第二天就合并了。 反正,我大概至少 8 、9 个月没有自己写过代码了。因为会聪明反被聪明误、自己觉得自己行非要瞎鼓捣然后耽误自己使用 AI 进步速度、也耽误自己和 AI 的配合度。 让 AI 飞吧。 |
5 UG4anS3JspYD 5 月 19 日@povsister 这个点要分两层看。 如果目标是“不进入应用协议解析层”,这类 listener/dialer wrapper 可以做到:连接进来后必须先过 auth frame ,没过就很快 close ,上层 HTTP/gRPC/自定义协议 handler 不会看到这条连接。 但如果目标是“不进内核 TCP 协议栈 / 不占 SYN backlog / 不占 fd”,那就不是 Go 里的 net.Listener 能解决的了,需要放到更前面,比如 nftables/iptables 、connlimit/hashlimit 、SYN cookies/SYNPROXY ,或者更靠前的 eBPF/XDP 。 libknock 里可选的 knock + firewall gate 主要就是想覆盖这一类场景:默认 protected port 由防火墙 DROP ,只有 knock 通过后才临时 allow 。这样随机连接不会打到应用 listener 。Auth-only 模式则不解决半开连接和 fd 消耗,只解决“不让未认证流量进入应用协议”。 |
6 bv 5 月 19 日基于 net.Conn 透明包装了一层 pre-payload ,和 proxy-protocol 协议手法类似。 |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。