puzed/wrapguard

GitHub: puzed/wrapguard

WrapGuard 是一个无需特权或内核模块的纯用户空间 WireGuard 代理,通过动态库注入为指定进程提供透明网络隧道。

Stars: 166 | Forks: 8

# WrapGuard - 用户空间 WireGuard 代理 WrapGuard 允许应用程序从用户空间通过网络通过 WireGuard VPN 路由网络流量,无需容器权限或内核模块。 Linux 是目前主要的生产目标。macOS 的构建、打包和回归检查在 CI 中运行,并且 macOS 运行时路径已证明支持 CLI 目标的直接启动 TCP 路由,但仍处于实验阶段,仅限于可以接受注入的目标。 ## 功能 - **纯用户空间**:无需创建 TUN 接口,不需要 NET_ADMIN 权限 - **透明拦截**:在支持的宿主机上使用特定平台的动态库注入 - **双向支持**:在支持的 Linux 构建版本上,传入和传出连接均可工作 - **标准配置**:使用标准 WireGuard 配置文件 ## 安装 ### 预编译二进制文件 从 [发布页面](https://github.com/puzed/wrapguard/releases) 下载 Linux 和 macOS 的预编译二进制文件。 Linux 版本以生产环境为目标。macOS 归档文件已打包并验证了布局一致性以及发布归档冒烟检查,但在运行时启动器工作完成之前,macOS 支持仍应被视为实验性的。 **无需额外依赖** - WrapGuard 是一个单一二进制文件,包含创建 WireGuard 连接所需的一切。您不需要在主机上安装 WireGuard、内核模块或任何其他 VPN 软件。 ### 从源代码构建 ``` make build ``` 这将创建: - `wrapguard` - 主可执行文件 - Linux 上的 `libwrapguard.so` 或 macOS 上的 `libwrapguard.dylib` - 位于二进制文件旁边的注入库 ## 支持矩阵 - Linux `amd64` 和 `arm64`:支持生产使用。 - `amd64` 和 `arm64` 架构上的 macOS 14 Sonoma 和 macOS 15 Sequoia:针对可作为可执行路径启动的目标,提供实验性的直接启动支持。 - 如果您正在尝试简单的 `.app` 包,当 `Contents/MacOS` 包含单个明确候选者时,WrapGuard 可以解析内部可执行文件;尚不支持 `open -a`。 - 通过非 SIP shell 二进制文件进行的直接 CLI 启动受到支持,其实验性质与其他直接 macOS CLI 目标相同。 - `open -a` 以及依赖 Apple 管理的应用启动器的启动目标:不支持。 - Sequoia 之后的 macOS 新版本可能可以工作,但尚未成为文档化 QA 矩阵的一部分。 - 位于 `/usr/bin`、`/bin`、`/System`、`/sbin` 和 `/usr/libexec` 等位置的 macOS SIP 保护二进制文件:启动前被拒绝,不支持。 - 第三方签名的 GUI 应用、强化运行时应用、沙盒助手和浏览器风格的多进程应用可能仍会启动,但不支持,并且在注入下可能不稳定。 - 路由出站 TCP 是目前 macOS 上文档化和测试过的路径。macOS 上 UDP 不被隧道化,WrapGuard 可能会故意抑制可能的 QUIC `UDP/443` 连接尝试,以便浏览器回退到 TCP 路径,而不是通过 UDP 泄露。 - IPv6 在 macOS 上仍不在生产支持声明范围内。 - Windows:不支持。 ## 用法 ``` # 通过 WireGuard 路由传入连接 wrapguard --config=~/wg0.conf -- node -e 'http.createServer((_, res) => res.end("hello")).listen(8080)' # 通过 WireGuard 路由传出连接 wrapguard --config=~/wg1.conf -- curl http://10.0.0.3:8080 # 使用 exit node(通过特定 peer 路由所有流量) wrapguard --config=~/wg0.conf --exit-node=10.150.0.3 -- curl https://icanhazip.com # 通过不同的 peer 路由特定子网 wrapguard --config=~/wg0.conf \ --route=192.168.0.0/16:10.150.0.3 \ --route=172.16.0.0/12:10.150.0.4 \ -- curl https://internal.corp.com # 带 debug 日志输出到控制台 wrapguard --config=~/wg0.conf --log-level=debug -- curl https://icanhazip.com # 带日志记录到文件 wrapguard --config=~/wg0.conf --log-level=info --log-file=/tmp/wrapguard.log -- curl https://icanhazip.com ``` ## macOS 指南 - 使用 WrapGuard 直接启动目标可执行文件。 - 对于 `Contents/MacOS` 中包含单个明确可执行文件的简单 `.app` 包,您也可以传递包路径,WrapGuard 将为您解析内部可执行文件。 - 如果包在 `Contents/MacOS` 中包含多个可执行候选者,WrapGuard 将拒绝启动并要求您显式启动内部可执行文件。 - 如果您想要在 macOS 上使用 WrapGuard 下的 shell 会话,请使用由 WrapGuard 直接启动的非 SIP shell 二进制文件。`/bin` 中受 Apple 保护的 shell 不是受支持的注入目标。 - `open -a AppName` 不等同于直接启动内部可执行文件,也不是受支持的封装路径。 - 位于 `/usr/bin`、`/bin`、`/System`、`/sbin` 和 `/usr/libexec` 等 Apple 受保护位置的二进制文件受 SIP 阻止,不予支持。 - 即使 TCP 拦截有效,Firefox/LibreWolf 类等多进程浏览器等浏览器风格 GUI 应用仍处于实验阶段。Helper、GPU、合成器和沙盒子进程在 DYLD 注入下可能会变得不稳定。 - 对于可重复的实验性浏览器检查,请使用 [docs/macos-browser-validation.md](docs/macos-browser-validation.md) 中的文档化工具,而不是临时启动命令。 - 如果浏览器风格的应用在软刷新与硬刷新时显示不同的结果,请将其视为应用可能正在使用缓存、service worker 或替代传输路径的迹象,而不是假设隧道路径本身已损坏。 - 路由出站 TCP 是目前 macOS 上文档化和测试过的路径。封装 UDP 和封装 IPv6 流量在 macOS 上尚未达到生产就绪状态,更广泛的非阻塞/浏览器套接字兼容性仍在积极验证中。 - DNS 查找仍由主机网络栈解析。WrapGuard 目前通过隧道路由解析后的 IP 字面量 TCP 目标,但不拦截解析器 API 或隧道化 DNS 本身。 - Localhost 和环回流量被有意保留在主机栈上,不通过注入的 SOCKS 路径路由。 ### 实验性 GUI 行为 macOS 实验性 GUI 启动的当前预期行为: - 通过 WrapGuard 直接启动真实可执行文件路径 - 对于 `.app` 包,仅当存在单个明确可执行候选者时,WrapGuard 才可能自动解析 `Contents/MacOS/...` - 如果浏览器或 GUI 应用需要已运行的应用实例、`open -a`、应用启动器服务或切换到另一个未封装的会话,则该路径不在受支持模型范围内 - 最可靠的验证流程是全新配置文件加上直接内部可执行文件启动 - 如果应用保持在直接启动的进程树中并接受 DYLD 注入,则路由出站 TCP 可以工作 macOS 上当前不受支持或有风险的应用类别: - Apple 保护或 SIP 保护的二进制文件 - 拒绝注入库的强化运行时应用 - 立即切换到另一个已运行进程或守护进程的应用启动器 - 其关键助手进程无法容忍 DYLD 注入的应用 - 网络或合成器助手在插入下崩溃的沙盒 GUI 应用 ### 当前浏览器传输决策 macOS 上当前的实验性浏览器立场是: - 路由 TCP 是受支持的浏览器传输路径 - macOS 上目前不支持 UDP 和原生 QUIC 隧道 - WrapGuard 可能会抑制可能的浏览器 QUIC / `HTTP/3` `UDP/443` 流量,以便浏览器回退到经过验证的 TCP 路径 - 因此,浏览器支持应被视为实验性的直接启动 TCP 支持,而不是完整的浏览器传输等效性 ### macOS 故障排除 - 运行 `wrapguard --doctor [target]` 以在尝试真正启动之前检查本地运行时布局、选定的注入模式和 macOS 预检限制。 - 如果传递目标,`--doctor` 还会在 WrapGuard 启动隧道栈之前验证该启动目标。如果省略目标,它仅检查本地运行时产物。 - `--doctor` 接受可解析的 `.app` 包,打印它选择的内部可执行文件,并在启动前拒绝 macOS 上受 SIP 保护的启动路径。 - 运行 `wrapguard --config= --self-test` 以验证 WrapGuard 能否启动其 IPC/SOCKS 栈、注入库并观察被拦截的出站 `connect()`。 - 如果子进程启动但 WrapGuard 报告拦截器从未宣布就绪,请确认目标不受 SIP 保护,并且 `libwrapguard.dylib` 位于 `wrapguard` 旁边。 - 如果流量未更改,请使用 `--log-level=debug` 重新运行,并检查显示 `DYLD_INSERT_LIBRARIES`、解析的 dylib 路径和拦截器加载消息的启动行。 - 如果基于主机名的连接仍通过主机而不是 VPN 解析,这在目前是预期的。WrapGuard 仅通过 SOCKS 和 WireGuard 用户空间 netstack 路由生成的 IP 字面量 TCP 目标。 - 如果您看到拦截器加载并且出站 `connect()` 调用被拦截,但请求仍以主机 IP 退出,请将其视为隧道路径故障。路由出站 TCP 现在会通过 WireGuard 用户空间 netstack 失败,而不是静默回退到直接主机连接,因此这指向对等可达性、出口节点路由或上游 WireGuard 配置问题,而不是 dylib 注入问题。 - 如果您正在验证类浏览器应用,并且它在软刷新后仍报告主机 IP,请将其与硬刷新和直接 CLI 探测(如 `curl`)进行比较;浏览器缓存、service worker、QUIC/HTTP3 或助手进程不稳定性都可能改变观察到的路径。 - 如果代码签名或强化运行时阻止注入,请暂时使用未签名或开发者控制的二进制文件。公证和强化运行时兼容性不在当前实验性支持声明范围内。 - 如果浏览器或 GUI 应用加载、拦截了一些流量,然后崩溃,请将其视为助手进程兼容性问题,而不是隧道路径损坏的证明。 ## 路由 WrapGuard 支持基于策略的路由,以通过特定的 WireGuard 对等节点引导流量。 ### 出口节点 使用 `--exit-node` 选项通过特定对等节点路由所有流量(如传统 VPN): ``` wrapguard --config=~/wg0.conf --exit-node=10.150.0.3 -- curl https://example.com ``` ### 基于策略的路由 使用 `--route` 选项通过不同对等节点路由特定子网: ``` # 通过一个 peer 路由企业流量,通过另一个 peer 路由互联网 wrapguard --config=~/wg0.conf \ --route=192.168.0.0/16:10.150.0.3 \ --route=0.0.0.0/0:10.150.0.4 \ -- ssh internal.corp.com ``` ### 配置文件路由 您还可以在 WireGuard 配置文件中定义路由: ``` [Peer] PublicKey = ... AllowedIPs = 10.150.0.0/24 # 通过此 peer 路由所有流量 Route = 0.0.0.0/0 # 或者路由特定子网 Route = 192.168.0.0/16 Route = 172.16.0.0/12:tcp:443 ``` ## 日志 WrapGuard 提供具有可配置级别和输出目标的结构化 JSON 日志。 ### 日志选项 - `--log-level=` - 设置日志级别。默认值:info - `--log-file=` - 将日志写入文件而不是终端 ### 日志级别 - `error` - 仅严重错误 - `warn` - 警告和错误 - `info` - 一般信息、警告和错误(默认) - `debug` - 详细调试信息 ### 日志格式 所有日志都以带时间戳的结构化 JSON 格式输出: ``` {"timestamp":"2025-05-26T10:00:00Z","level":"info","message":"WrapGuard v1.0.0-dev initialized"} {"timestamp":"2025-05-26T10:00:00Z","level":"info","message":"Config: example-wg0.conf"} {"timestamp":"2025-05-26T10:00:00Z","level":"info","message":"Interface: 10.2.0.2/32"} {"timestamp":"2025-05-26T10:00:00Z","level":"info","message":"Peer endpoint: 192.168.1.8:51820"} {"timestamp":"2025-05-26T10:00:00Z","level":"info","message":"Launching: curl https://icanhazip.com"} ``` 指定 `--log-file` 时,所有日志将写入文件,终端中不会显示任何内容。 ## 配置 WrapGuard 使用标准 WireGuard 配置文件: ``` [Interface] PrivateKey = Address = 10.0.0.2/24 [Peer] PublicKey = Endpoint = server.example.com:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25 ``` ## 工作原理 1. **主进程**:解析配置,初始化 WireGuard 用户空间实现 2. **注入库**:使用宿主机特定的动态加载路径拦截网络系统调用 3. **虚拟网络栈**:在被拦截的连接和 WireGuard 隧道之间路由数据包 4. **用户空间 TUN/Netstack**:无需内核接口,数据包完全由 WireGuard 用户空间 netstack 在内存中处理 ## 限制 - 仅限 Linux 和 macOS(不支持 Windows) - macOS 运行时支持是实验性的,不应假设适用于 SIP 保护二进制文件、强化运行时应用、`open -a` 启动器路径或无法接受注入库的启动目标 - 路由 TCP 是目前主要的文档化路径 - 封装 UDP 和封装 IPv6 在 macOS 上尚未作为受支持项记录在案 - 由于用户空间数据包处理而产生的性能开销 ## 开发 ### 运行测试 WrapGuard 包含针对所有核心功能的全面单元测试: ``` # 运行所有测试 go test -v ./... # 运行测试并生成覆盖率 go test -cover ./... ``` ### 构建 ``` # 构建主要 binary make build # 端到端验证本地 macOS package 布局 make smoke-macos # 使用全新 profile 启动实验性 macOS browser target make smoke-macos-browser \ WG_CONFIG=../NL-US-PA-16.conf \ BROWSER_APP="/Applications/LibreWolf.app/Contents/MacOS/librewolf" # 带 debug 信息构建 make debug # 清理 build artifacts make clean ``` ## 演示 WrapGuard 包含一个全面的基于 Docker 的演示,展示了 Node.js 应用程序通过 WireGuard 隧道通信,无需 root 权限或内核模块。 演示包括: - 一个 WireGuard 服务器容器 - 两个使用 WrapGuard 封装的 Node.js HTTP 服务器 - 通过 WireGuard 隧道的跨服务器通信 ### 运行演示 ``` cd demo ./setup.sh docker compose up --build ``` ## 测试 ``` # 测试传出连接 wrapguard --config=example-wg0.conf -- curl https://example.com # 测试传入连接 wrapguard --config=example-wg0.conf -- python3 -m http.server 8080 ```
标签:EVTX分析, Go, IP 地址批量处理, Ruby工具, SOCKS, VPN, Web截图, WireGuard, 代理工具, 动态库注入, 基础设施, 容器安全, 无特权运行, 日志审计, 流量劫持, 用户态网络, 系统编程, 网络安全, 网络拦截, 网络隧道, 透明代理, 隐私保护