asciimoth/killswitch
GitHub: asciimoth/killswitch
基于 Linux eBPF 的故障封闭式网络出口过滤守护进程,用于 VPN 断线时阻断未授权流量以防止 IP 泄露。
Stars: 1 | Forks: 0
# killswitch
`killswitch` 是一个 Linux eBPF 网络终结开关。系统守护进程会附加一个
egress 程序到选定的网络接口,维护基于接口的策略,
并且除非当前策略明确允许,否则将丢弃路由到这些接口的流量
(顺便说一下,它与 [pmark](https://github.com/asciimoth/p-mark) 配合得很好)。
该项目包括:
- `killswitch`:系统守护进程,负责接口监控、eBPF 挂载、
策略评估、管理 API 以及可选的本地 SOCKS 代理。
- `killswitch-user`:桌面会话辅助工具,用于通知、托盘控制、
网络检查和强制门户处理。
- `killswitch-cli`:控制 killswitch 守护进程的命令行客户端。
## 功能
- 故障封闭式 IPv4 和 IPv6 egress 过滤。
- 按类型、确切名称和正则表达式选择接口。
- 每个接口的有效策略。
- 针对 fwmark、端口、目标主机和主机+端口对的全局允许规则。
- 由接口、地址、Wi-Fi 和网关触发器激活的命名规则集。
- 用于应用程序集成的临时连接独占规则集。
- 用于交互式或受监督工作流的强制规则集激活。
- 可选的本地 SOCKS 代理,其 fwmark 会自动被允许。
- 基于 Unix socket 的管理 API,具有基于对端凭证的授权。
- 桌面通知、托盘集成以及网络登录页面处理。
## 安装说明
### Nix
从 flake 直接构建或运行:
```
nix build github:asciimoth/killswitch#killswitch
nix profile add github:asciimoth/killswitch#killswitch
```
你也可以使用系统服务:
```
imports = [ inputs.killswitch.nixosModules.killswitch ];
environment.systemPackages = [
inputs.killswitch.packages.${pkgs.system}.killswitch
];
services.killswitch = {
enable = true;
settings = {
interface_types = [ "device" ];
interface_regexps = [ "^(en|wl|ww)" ];
allow_all = false;
enable_v4 = true;
enable_v6 = true;
# allowed_ports = [ "udp/53" "tcp/53" ];
socks_proxy = {
enabled = true;
port = 1080;
fwmark = "0xeb9f0001";
dns_server = "8.8.8.8";
protected = {
usernames = [ "root" "myuser" ];
};
};
};
};
```
### 基于 Deb 和 rpm 的系统
软件包已发布到[我的 deb/rpm 仓库](https://repo.moth.contact):
通过脚本(或手动)为你的系统进行设置:
```
curl https://repo.moth.contact/setup.sh | bash
```
然后使用你的系统软件包管理器进行安装:
```
sudo apt install killswitch
# 或
sudo dnf install killswitch
# 或
sudo yum install killswitch
```
### GitHub Releases
发布归档和软件包工件发布在
[GitHub 发布页面](https://github.com/asciimoth/killswitch/releases)上。
### Arch
已提供 [AUR](https://aur.archlinux.org/packages/killswitch-bin)
## 守护进程设置
默认情况下,守护进程会读取 `/etc/killswitch/killswitch.json`。配置是一个
单一的 JSON 对象;未知字段会被拒绝。
示例:
```
{
"interface_types": ["device"],
"interface_names": ["eth0", "wlan0"],
"interface_regexps": ["^(en|wl|ww)"],
"ignored_interface_types": ["bridge"],
"ignored_interface_names": ["docker0"],
"ignored_interface_regexps": ["^(veth|br-)"],
"admin_api": {
"socket_path": "/run/killswitch/admin.sock",
"auth": {
"groupnames": ["killswitch"]
}
},
"socks_proxy": {
"enabled": true,
"port": 1080,
"fwmark": "0xeb9f0001",
"dns_server": "8.8.8.8",
"protected": {
"usernames": ["root", "alice"]
}
},
"rulesets": {
"wireguard-up": {
"disabled": false,
"match": "or",
"trigger": {
"interface_names": ["wg0"],
"ip_addrs": ["10.64.0.2"]
},
"enable_v4": true,
"enable_v6": true,
"allowed_v4_hostports": ["udp/198.51.100.10:51820"]
}
},
"allow_all": false,
"enable_v4": true,
"enable_v6": true,
"allowed_marks": ["0x42"],
"allowed_ports": [],
"allowed_v4_hosts": [],
"allowed_v6_hosts": [],
"allowed_v4_hostports": ["udp/198.51.100.10:51820"],
"allowed_v6_hostports": []
}
```
### 接口过滤
至少需要以下包含选择器之一:
- `interface_types`
- `interface_names`
- `interface_regexps`
匹配的忽略选择器将在包含之后应用:
- `ignored_interface_types`
- `ignored_interface_names`
- `ignored_interface_regexps`
被忽略的接口不由守护进程管理。环回接口 `lo` 始终被忽略。
### 全局策略
顶层策略是每个选定接口的基础策略:
- `allow_all`:在正常数据包解析之前放行所有数据包。这应该作为
临时的恢复或调试设置。
- `enable_v4`:启用 IPv4 流量评估。当为 false 时,除内置引导流量外,
可路由的 IPv4 流量将被丢弃。
- `enable_v6`:启用 IPv6 流量评估。当为 false 时,除内置引导流量外,
可路由的 IPv6 流量将被丢弃。
- `allowed_marks`:允许带有匹配 fwmark 的数据包,例如 `"0x42"` 或
`"100"`。
- `allowed_ports`:允许任何主机上的 TCP 或 UDP 目标端口,例如
`"tcp/443"` 或 `"udp/53"`。
- `allowed_v4_hosts`、`allowed_v6_hosts`:无论端口如何,均允许目标主机。
- `allowed_v4_hostports`、`allowed_v6_hostports`:允许协议、目标
主机和目标端口组成的元组,例如 `"udp/198.51.100.10:51820"` 或
`"tcp/[2001:db8::10]:443"`。
对于固定端点,建议使用主机+端口规则。`allowed_ports` 通常过于
宽泛,因为它允许在每台主机上使用该目标端口。
eBPF 程序会将 ARP、DHCPv4、DHCPv6 和 ICMPv6 邻居发现
引导流量与这些允许规则分开处理。
### 规则集
`rulesets` 是一个以规则集名称为键的对象。一个规则集包含:
- `disabled`:在不删除规则集的情况下忽略它。
- `match`:`"or"` 或 `"and"`。如果任何触发谓词匹配,`"or"` 就会激活。
`"and"` 要求每个配置的触发器组都匹配。API 也将其公开为 `match_all`。
- `trigger`:激活谓词。
- 使用与全局策略相同名称的策略字段。
支持的触发器字段:
- `interface_types`
- `interface_names`
- `interface_regexps`
- `ip_addrs`
- `ssids`
- `bssids`
- `gateway_macs`
规则集在每个接口上独立激活。对于每个选定的接口,
守护进程会从全局策略开始,并合并触发器匹配该接口的每个已启用的命名规则集。
被禁用的规则集将被忽略。
### SOCKS 代理
守护进程可以在 `127.0.0.1` 上运行本地 SOCKS 代理。它由
`socks_proxy` 配置块控制,也可以通过
`killswitch-cli` 启动或停止。
- `enabled`:随守护进程启动代理。
- `port`:本地监听端口。默认为 `1080`。
- `fwmark`:应用于出站代理流量的标记。在代理运行时,配置的标记会
自动合并到 `allowed_marks` 中。
- `dns_server`:代理 DNS 处理所使用的可选 DNS 服务器。
- `protected.uids`、`protected.gids`、`protected.usernames`:限制哪些本地
用户可以连接到代理。
基于用户的代理访问是一个便利的边界,而不是绝对安全的保护。监听器会
尽最大努力检查传入本地连接的所有者,并且该检查可能会受到竞争条件的影响。
### 管理 API
管理 API 默认启用。它监听 Unix socket,默认路径为
`/run/killswitch/admin.sock`。
配置字段:
- `admin_api.socket_path`:Unix socket 的绝对路径。
- `admin_api.debug`:启用调试通知注入以测试客户端。
- `admin_api.auth.uids`
- `admin_api.auth.gids`
- `admin_api.auth.usernames`
- `admin_api.auth.groupnames`
如果未配置任何身份验证规则,守护进程将允许 `killswitch`
组的成员。该 API 使用来自 Unix socket 连接的对端凭证。
## 桌面集成
`killswitch-user` 应在用户的图形会话中运行。它连接到
守护进程管理 API,并处理面向用户的通知、托盘状态和
网络检查。
默认情况下,它使用:
```
$XDG_CONFIG_HOME/killswitch/killswitch-user.json
```
或:
```
~/.config/killswitch/killswitch-user.json
```
如果你的会话在桌面栏或 D-Bus 服务就绪之前启动了 `killswitch-user`,
请添加一个启动延迟:
```
killswitch-user --delay 10s
```
示例:
```
{
"socket_path": "/run/killswitch/admin.sock",
"notify_interface_changes": true,
"notify_global_allow_all": true,
"tray_enabled": true,
"network_check": {
"period": "300s",
"url": "http://connectivity-check.ubuntu.com/",
"status": 204,
"header": "online",
"notify": true,
"captive_portal": {
"cmd": [
"chromium",
"--proxy-server={{.ProxyAddr}}",
"--user-data-dir={{.Tmp}}",
"--no-first-run",
"--password-store=basic",
"{{.Portal}}"
]
}
}
}
```
配置字段:
- `socket_path`:管理 API 的 socket 路径。
- `notify_interface_changes`:在受管理的接口发生更改时显示通知。
- `notify_global_allow_all`:在全局 `allow_all`
状态发生更改时显示通知。
- `tray_enabled`:启用系统托盘 UI。
- `network_check`:在设置了 `url` 时启用定期连接检查。
网络检查字段:
- `period`:间隔,例如 `"300s"`。
- `url`:要检查的 HTTP 端点。
- `status`:预期的 HTTP 状态码。
- `text`:可选的预期响应文本。
- `header`:可选的预期响应头。
- `timeout`:可选的请求超时。
- `notify`:为网络检查状态更改显示通知。
- `captive_portal`:在网络似乎需要登录时启动的命令。
强制门户命令支持模板值,例如 `{{.Portal}}`、
`{{.ProxyAddr}}` 和 `{{.Tmp}}`。建议在强制门户流程中使用 Chromium,
因为它可以通过命令行参数接受 SOCKS 代理 URL。
## CLI 使用
`killswitch-cli` 与守护进程管理 API 通信。当守护进程 socket 不是默认值时,
每个子命令都接受 `-socket PATH` 或 `-s PATH`。
检查当前守护进程状态:
```
killswitch-cli get-cfg
killswitch-cli get-cfg --watch
killswitch-cli get-cfg --json-out
```
监听通知:
```
killswitch-cli notifications
killswitch-cli notifications --json-out
```
启动或停止守护进程 SOCKS 代理:
```
killswitch-cli socks-proxy start
killswitch-cli socks-proxy stop
```
修改全局策略:
```
killswitch-cli set -target base_policy.enable_v4 true
killswitch-cli set -target base_policy.allow_all false
killswitch-cli add -target base_policy.allowed_v4_hostports udp/198.51.100.10:51820
killswitch-cli remove -target base_policy.allowed_marks 0x42
```
添加、更改或移除命名规则集:
```
killswitch-cli add -target ruleset -ruleset wireguard-up -json '{"trigger":{"interface_names":["wg0"]},"policy":{"enable_v4":true,"allowed_v4_hostports":["udp/198.51.100.10:51820"]}}'
killswitch-cli set -target ruleset.disabled -ruleset wireguard-up true
killswitch-cli remove -target ruleset -ruleset wireguard-up
```
安装临时规则集并使其保持活动状态,直到按下 Ctrl+C、Ctrl+D、Esc 或
服务器断开连接:
```
killswitch-cli tmp-ruleset -interfaces wg0 -json '{"enable_v4":true,"allowed_v4_hostports":["udp/198.51.100.10:51820"]}'
```
在 CLI 连接的生命周期内,强制为选定接口激活命名规则集:
```
killswitch-cli force-ruleset -interfaces wg0 -ruleset wireguard-up
```
临时和强制规则集的作用域仅限于连接。当拥有它们的客户端断开连接时,
它们会自动被移除。
## 应用程序集成
应用程序应将绕过 killswitch 视为用户的明确选择。默认情况下将其
保持禁用状态,只有在用户有意选择加入后才启用。
推荐策略:
- 对于短暂的访问使用拥有的临时规则集。临时规则集与
管理 API 客户端连接绑定,并在应用程序退出、崩溃或断开连接时自动移除。
- 当应用程序与已知地址通信时,首选端点白名单。仅针对所需的
协议、地址和端口添加主机+端口规则。
- 当应用程序能够标记其所有流量时,使用 fwmark 策略。
使用带有 `allowed_marks` 的临时客户端拥有的规则。
## 待办事项
- [ ] killswitch 守护进程启动后是否应进行权限降级?
- [ ] 安全审计
- [ ] killswitch-cli 的 shell 自动补全
- [ ] 流行 VPN 客户端的设置示例
- [ ] Tailscale?
- [ ] Amnesia
- [ ] 允许检查多个 URL 以测试网络连通性
## 许可协议
本仓库采用 GPL 或 MIT 双重许可;请参阅
[LICENSE-GPL](./LICENSE-GPL)
和
[LICENSE-MIT](./LICENSE-MIT)。
注意:Go 绑定嵌入了由 `bpf2go` 生成的预编译 eBPF 对象二进制大对象
(`cmd/killswitch/killswitch_bpf*.o`)。
这些二进制大对象由开源的
[killswitch.c](./cmd/killswitch/killswitch.c) 构建,
该文件为内核验证器声明了 `Dual MIT/GPL`。
你可以使用以下命令重新生成它们:
```
go generate ./...
```
标签:EVTX分析, VPN, 日志审计, 流量过滤, 网络防火墙