Erebus: 一个无根用户态 VPN 代理
Erebus 在受限环境中实现无根 VPN 连接
Erebus 是一个用户态 VPN 代理,允许用户在不需要 root 权限或修改宿主机网络栈的情况下建立 VPN 连接。通过在单个进程中完全实现 OpenVPN 协议和 TCP/IP 协议栈,Erebus 绕过了对内核 tun/tap 接口和路由表修改的需求,使其成为 CI runner、沙箱和非特权容器等无法使用 sudo 权限环境的理想选择。
架构:将 VPN 协议栈移至用户态
Erebus 使用其内部逻辑取代了传统的基于内核的路由和 TCP 处理。该工具唯一需要的系统权限是打开标准网络套接字的能力。
数据流
当发起请求时,数据遵循以下路径:
- 本地 HTTP 客户端:客户端应用程序指向本地 Erebus 代理。
- HTTP 代理:Erebus 接收并转发请求。
- 用户态 TCP/IP 协议栈:该进程通过手动构建和解析 IPv4、TCP 和 ICMP 数据包来实现。
- 加密:使用 OpenVPN 静态密钥(wire format v1)协议对数据包进行加密,并应用 HMAC 和数据包 ID。
- 传输:加密后的数据作为 UDP 数据报或 TCP 帧发送到 OpenVPN 服务器。
核心功能与能力
无根操作
Erebus 不需要 sudo 权限,不需要设置脚本,也不会触及宿主机的接口、路由或 DNS 设置。它可以作为一个标准的用户进程启动和停止。
可选流量路由
连接是显式的而非系统级的。用户必须将特定应用程序指向本地代理,以通过 VPN 路由流量。
- 出站:本地 HTTP/1.x 代理将请求转发到 VPN 上的资源。
- 入站:端口转发可实现本地服务与 VPN 对端之间的双向暴露。
协议支持
- OpenVPN:支持通过 UDP 或 TCP 使用静态密钥模式(预共享密钥)。它支持 CBC 加密算法(AES, ARIA, Camellia)和各种 HMAC 摘要算法。
- IPsec:包含一个与 strongSwan 协同工作的 IKEv2 控制平面和 ESP 数据平面。由于无根进程无法发送原始 ESP,所有流量都使用预共享密钥通过 UDP 封装(NAT-T)。
使用与安装
Erebus 使用 Common Lisp (SBCL) 编写,并作为 Debian 软件包分发给 Debian/Ubuntu 衍生版本。
快速开始配置
一个用于出站 UDP 代理的最小配置定义在 INI 文件中:
[erebus]
client-ip = 10.8.0.2
[openvpn-server]
proto = udp
host = vpn.example.com
port = 1194
secret = /etc/erebus/static.key
cipher = AES-256-CBC
auth = SHA256
[proxy-out]
address = 127.0.0.1
port = 11023
要使用该代理,用户可以通过命令行路由流量:
http_proxy=http://127.0.0.1:11023 curl http://10.8.0.1/
性能与局限性
Erebus 是一个处于早期阶段的实验性项目,其优先级是正确性和清晰度而非性能。
适用场景
| 理想场景 | 不理想场景 |
|---|---|
| 在非特权容器中的内部 HTTP 服务 | 系统级 VPN 路由 |
| 需要私有端点的 CI 任务 | 大规模数据传输 |
| 沙箱或多租户宿主机 | TLS 模式 OpenVPN (证书) |
| 将单个本地端口暴露给 VPN 对端 | HTTPS CONNECT 隧道或 SOCKS |
性能权衡
由于实现方式是逐个发送数据块并等待确认后再发送下一个,因此大文件下载速度明显慢于标准代理。这种设计选择确保了代码的简洁性和互操作性。