Celium

Celium 是一个自托管的 mesh 组网软件:每台机器拿到一个稳定的虚拟 IP,能在网络允许 的地方直连、在打不通的地方自动走中继,而身份、访问策略和命名都放在你自己控制的 服务器上。

它由三部分组成,边界很清楚:

部分谁来实现现状
数据面引擎(WireGuard、打洞、中继、用户态协议栈)直接用 Tailscale 的开源 Go 实现(tailscale.com可行性已验证engine/tsengine 用 Celium 自己的控制面驱动他们的引擎,直连与中继两条路径都跑通;迁移计划见 docs/MIGRATION.md
协调服务器 + 账号体系Celium 自己的已完成并测试
多平台客户端Celium 自己的桌面/服务端已可用;移动端待建

账号不外包。 没有 OAuth、没有第三方登录,注册就是你自己的服务器上多一行记录。 详见 docs/ACCOUNTS.md

$ curl -sX POST https://control.example.com/api/register \
    -d '{"username":"alice","password":"correct-horse-1"}'
$ curl -sX POST https://control.example.com/api/node-keys \
    -H "Authorization: Bearer $TOKEN" -d '{"description":"laptop","preauthorized":true}'
$ celium up --control-url=https://control.example.com --auth-key=celiumkey-...
$ celium status
web-1  macOS  direct  198.51.100.7:41641  12s ago   1.2 MB / 340 kB
db-1   Linux  relay   hkg                 3s ago    88 kB  / 12 kB

平台

平台形态状态
Linuxceliumd 守护进程 + celium CLI,真实 TUN 接口可用(需要 root 建接口)
macOS同上,utun 接口可用
Windows同上核心可交叉编译(已验证),TUN 后端待接
Androidgomobile 绑定同一份 Go 核心 + VpnService待建
iOSgomobile 绑定同一份 Go 核心 + NEPacketTunnelProvider待建
鸿蒙需单独评估(HarmonyOS NEXT 无官方 Go 运行时)待评估

移动端的主要工作量不在 Go,而在平台入口:手机不允许普通 App 建 TUN 设备,必须由 系统的受管组件(Android VpnService / iOS NEPacketTunnelProvider)把文件描述符交给 核心。详见 docs/CLIENTS.md

桌面/服务端用 Go 原生跑,移动端计划用 gomobile同一份核心打包进去——不是 重写一遍协议栈,而是让手机和电脑跑同一套入网、打洞、加密代码,这样"手机登录 Celium 和电脑登录 Celium 可以互联"就是自然的,而不是需要对齐的两套实现。

账号体系(已完成)

Account --拥有--> User --拥有--> Node
   |                |
   |                +-- ACL 规则写的就是它
   +-- 登录、签发节点密钥、邀请他人
  • 第一个注册的账号自动成为管理员(否则部署无法管理)。
  • 之后的账号凭邀请码加入(默认一次性,可设次数与有效期)。
  • 用户可以为自己名下的机器签发节点密钥,机器用它入网;节点归属于签发者。
  • 会话令牌只以 SHA-256 落盘,密码用 bcrypt(cost 12),登录失败按「用户名+来源地址」

限速,改密码/停用账号会立刻注销会话。

完整 API 与安全取舍见 docs/ACCOUNTS.md

架构

协调服务器只做四件事:认证机器、分配地址、下发策略、充当兜底中继的目录。它 持有任何能解密业务流量的密钥——被攻破的后果是"策略被篡改",而不是"流量被读取"。 完整设计见 docs/ARCHITECTURE.md

  • 控制通道:HTTPS 上的 HTTP Upgrade + Noise IK 握手,Noise 静态密钥由机器密钥

确定性派生,因此握手本身即完成设备认证;客户端 pin 控制公钥。

  • 节点证书:节点密钥由控制密钥签名,对端可以离线验证身份,建连时无需回查服务器。
  • 数据面:WireGuard,端到端加密;中继只转发密文。
  • 打洞:disco 消息与数据走同一个 UDP socket(NAT 映射属于 socket),端到端认证。

构建与测试

make build          # bin/celium、bin/celiumd、bin/celium-control
make test           # 单元测试
make e2e            # 端到端:真实控制面 + 真实中继 + 真实节点 + 真实流量

纯 Go,无 cgo,无需代码生成。gvisor.dev/gvisorgo.mod 中被钉住:更新的版本 里有一个测试文件会让依赖方无法编译,升级前请先确认 go build ./... 仍然通过。

当前状态与限制

已经过端到端验证tstest/ 中的测试会真的起服务器、中继和节点):

  • 自有账号注册/登录/邀请 → 签发节点密钥 → 节点入网 → 跨节点真实 TCP 流量
  • 直连打洞成功后自动从"中继"切到"直连"
  • 纯中继路径可用(用于双方都在硬 NAT 后的情况)
  • ACL 生效:默认拒绝,放行规则真的放行,拒绝规则真的拒绝
  • 一个节点下线后,对端地图里立刻标记为离线
  • 守护进程先启动、之后 up 的路径(这条曾经是坏的)

尚未完成或未验证

  • 引擎迁移:可行性已验证(engine/tsengine),迁移清单与风险见

docs/MIGRATION.md。在迁移完成前,仓库里两套实现同时在 (自研的与 Tailscale 的),最终要删掉一套。迁移的验收标准是现有端到端套件全部 通过,而不是"能编译"。

  • 子网路由与出口节点:路由的宣告、审批、下发已完成,TUN 模式的转发与 SNAT

路径没有被自动化测试覆盖。

  • 移动端客户端尚未开始。
  • tailnet lock(把可信签名密钥集合钉死)未实现:被攻破的协调服务器可以添加节点。
  • 密钥轮换只在节点启动时发生,没有运行中的定时轮换。
  • 中继每个区域单点,区域间可互联,但区域内部没有多中继故障转移。
  • Windows 的 TUN 后端未实现(用户态数据面在 Windows 上理论可用,未验证)。
  • DNS 只在 TUN 模式接管宿主解析器;用户态模式下宿主的 DNS 不动(否则会把整台

机器的解析打死),MagicDNS 由进程内解析提供。

仓库结构

types/                 密钥、控制协议类型、运行时网络视图、偏好
control/controlhttp    Noise 加密的控制通道
control/controlclient  客户端:注册、netmap 长轮询、状态折叠
controlplane           协调服务器:注册表、地址分配、ACL 编译、账号、管理 API
derp                   中继协议、服务端与客户端
disco                  端点发现与打洞
wgengine               WireGuard 数据面、netmap 翻译、ACL 执行
wgengine/magicsock     端点管理:直连优先、中继兜底
net/tun                真实 TUN 设备与路由(macOS、Linux)
net/netstack           用户态数据面(gVisor),无需特权
net/dns                MagicDNS 与宿主 DNS 配置
net/packet             IP 解析与编译后的 ACL
net/socks5             用户态模式的出口代理
ipn/local              本地后端:把控制面、数据面、DNS、ACL 接到一起
ipn/ipnserver          CLI 与之通信的本地 API
ipn/state              机器密钥、节点密钥、偏好持久化
cli, cmd               三个二进制
tstest                 端到端测试
engine                 数据面迁移到 Tailscale 实现的验证与结论
docs                   架构、账号、引擎迁移与结论