Linux eBPF
在 Linux 上,增强模式把 eBPF 程序挂到 cgroup v2 的 socket hook 上。任何程序发起连接时,内核已经知道 它属于哪个进程、要去哪里,Specola 据此按你的规则路由。不创建 TUN 设备,也不修改路由表。
系统要求
- Linux 5.17 或更新;
- cgroup v2 挂载在
/sys/fs/cgroup; - 内核 BTF(
/sys/kernel/btf/vmlinux); - root 权限,用于加载和挂载 BPF 程序。
检查:
bash
uname -r # 5.17 或更新
stat -fc %T /sys/fs/cgroup # cgroup2fs
test -r /sys/kernel/btf/vmlinux && echo BTF ok当前的 Arch Linux(包括 Omarchy)、Fedora、Ubuntu 24.04+ 和 Debian 12+ 内核都满足这三项。在容器内, 即使是 root 通常也无法加载 BPF 或挂载 cgroup 程序。
配置
toml
[general]
route-mode = "rule"
port = 7890
protocols = "mixed"
[[proxy]]
name = "office"
type = "http"
server = "proxy.example.com"
port = 8080
[rule]
list = [
"PROCESS-NAME,git-remote-http,office",
"PROCESS-NAME,cargo,office",
"DOMAIN-SUFFIX,corp.example.com,office",
"IP-CIDR,10.0.0.0/8,DIRECT,no-resolve",
"FINAL,DIRECT",
]
[dns.tun]
mode = "fake-ip"
[enhanced-mode]
enable = true
type = "ebpf"
ip-version = "ipv4"
[enhanced-mode.ebpf]
process-routing = true本地端口必须保持开启(port > 0):被重定向的连接通过它交给 Core。[dns.tun] 决定 Core 如何应答 被接管进程的 DNS 查询;默认就是 Fake-IP,所以这个表可以省略。
字段
| 字段 | 默认值 | 说明 |
|---|---|---|
[enhanced-mode] ip-version | "ipv4" | eBPF 后端接管 IPv4,IPv6 流量会绕过 |
[enhanced-mode.ebpf] process-routing | false | 为连接关联进程;规则中使用 PROCESS-* 时设为 true |
[enhanced-mode.ebpf] unmatched-traffic | "direct" | 为兼容旧配置保留;未命中的流量现在总是按 FINAL 处理 |
运行
先以普通用户校验,再用 root 启动:
bash
specola-core -t --config my.toml
sudo specola-core --config my.toml启动成功时日志包含:
text
Linux IPv4 process proxy started with cgroup eBPF socket redirection (IPv6 bypassed)用 Ctrl+C 或 SIGTERM 停止,Core 会卸载它挂载的程序。使用 sudo 时,--config 中只写文件名 仍会在你自己的 ~/.config/specola/profiles/ 中查找。
长期运行请使用 systemd 服务,完整的 unit 文件见《在 Omarchy 上使用 Specola》。
一条连接如何被决定
每一条新的 TCP 连接或 UDP 发送,在内核中按以下顺序处理:
- Core 自己和 Specola UI 的 socket 始终放行;
- 发往 53 端口的 DNS 查询交给 Core 的 DNS 模块;
- 回环、本机地址、私有和链路本地网段、组播和广播直接放行;
- 其余连接与 Core 在 BPF map 中维护的候选列表比对:规则中的进程名、IP 规则的网段、DNS 为带域名 规则的域名返回的地址,以及当前的
FINAL; - 不是候选的连接在内核中按
FINAL处理。FINAL,DIRECT时它保留原始 socket,从不进入 Core; - 候选连接被重定向到 Core 的本地端口,Core 按顺序执行完整规则列表,决定直连、拒绝,或经由所选的 代理或代理组连接。
这对规则意味着:
- 精确的
PROCESS-NAME可以在内核中预先检查;PROCESS-PATH、通配符和正则不行,会让更多连接绕经 Core。 - 如果
FINAL是代理或代理组,所有非本地连接都会经过 Core。 - 修改规则只影响新连接,已建立的连接保持原有决定。
- 自己走加密 DNS 的应用不会让 Core 看到域名,请用进程或 IP 规则匹配。
验证
bash
curl -sI https://example.com # 会出现在 Specola 连接日志中
sudo bpftool cgroup tree /sys/fs/cgroup # 列出已挂载的程序Core 停止后,这些程序会从 bpftool cgroup tree 中消失。
想在不改动真实程序的情况下测试进程规则,可以把一个可执行文件复制成规则期望的名字:
bash
cp /usr/bin/curl /tmp/cargo && /tmp/cargo -sI https://example.com # 命中 PROCESS-NAME,cargo排错
| 现象 | 原因与处理 |
|---|---|
enhanced-mode.type=tun is not supported on Linux | 改用 type = "ebpf" |
cgroup v2 is not mounted at /sys/fs/cgroup | 系统使用 cgroup v1 或非标准挂载点;启用统一 cgroup 层级 |
Operation not permitted | 没有以 root 运行,或容器、LSM 禁止了 BPF |
| 进程规则始终不命中 | 内核中的名字不同;用 cat /proc/<pid>/comm 查看(最多 15 个字符) |
| 域名规则始终不命中 | 应用使用自己的 DNS(DoH);改用进程或 IP 规则 |
| IPv6 网站绕过了 Specola | 正常现象,后端只接管 IPv4。保持 [dns].ipv6 = false,让被接管的程序拿到 IPv4 应答 |
| 所有流量都经过 Core | FINAL 是代理,或路径/通配符规则让大部分连接成为候选 |