Skip to content
Merged

Ikev2 #195

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .codex/skills/vnt-operations/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
name: vnt-operations
description: "Operate VNT 2 clients and self-hosted VNTS servers: run packaged programs, author client TOML configuration, call authenticated client or server Web APIs, and deploy VNTS with Linux systemd. Use for VNT runtime, configuration, API automation, troubleshooting, or server deployment tasks; do not use for unrelated Rust development."
---

# VNT Operations

Use the packaged VNT programs and their supported APIs. Treat the checked-in source as the authority when a local build differs from this skill.

## Route the task

- For `vnt2_cli`, `vnt2_ctrl`, `vnt2_web`, the desktop client, or client TOML/CLI parameters, read [references/client-usage.md](references/client-usage.md).
- For the `vnt2_web` or desktop Web-access API, read [references/client-web-api.md](references/client-web-api.md).
- For building, installing, configuring, upgrading, or troubleshooting the self-hosted server in `D:\rust\vnts`, read [references/server-deployment.md](references/server-deployment.md).
- For the VNTS administrative API, read [references/server-web-api.md](references/server-web-api.md).
- For repeatable HTTP calls, use [scripts/vnt_api.py](scripts/vnt_api.py). Run `python scripts/vnt_api.py --help` and the relevant subcommand help before first use.

Read only the references required by the current request. If behavior appears version-dependent, check the current binary's `--help`/`--conf-example` or the source paths named in the relevant reference before acting.

## Acquire API access

Client and server authentication are separate and their tokens are not interchangeable.

For a client Web API task, if access data is missing, ask for either:

- the complete access URL printed by `vnt2_web`, such as `http://host:19099/?token=...`; or
- the API base URL and Web access token separately.

Parse the `token` query parameter, remove it from subsequent request URLs, and send it only as `Authorization: Bearer <token>`. Probe `/api/version` and `/api/runtime` before relying on the rest of the API.

For a VNTS administrative API task, if access data is missing, ask for the management base URL, username, and password. Log in at `/api/login`, then use the returned JWT as the Bearer token. A client Web token does not authenticate to VNTS.

Never echo secrets, include them in summaries, commit them, or persist them in the skill/repository. Prefer the helper's stdin or environment-variable inputs over command-line secret arguments. Redact credentials from errors. On `401`, refresh or request credentials once; if the retry also fails, stop and report the authentication failure.

## Respect operation scope

Read-only inspection may proceed when it is relevant. Start, stop, restart, save, or update only when the user's request authorizes that mutation. Before a delete that was not already explicit, identify the exact instance, configuration, network, device, or peer server and obtain confirmation.

After a mutation, read back the affected resource or status. For asynchronous client startup, poll `/api/start/status` until `Running` or `Stopped`, report the terminal state, and include useful logs without credentials.

For remote deployment, establish the target host, architecture, SSH access method, public name/address, and intended open ports before changing the host. Do not assume access to a production server merely because the local `D:\rust\vnts` source is available.
6 changes: 6 additions & 0 deletions .codex/skills/vnt-operations/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
interface:
display_name: "VNT Operations"
short_description: "运行、配置和通过 API 控制 VNT 客户端,并部署 VNTS 服务端"
default_prompt: "Use $vnt-operations to configure and operate this VNT client or self-hosted VNTS server."
policy:
allow_implicit_invocation: true
147 changes: 147 additions & 0 deletions .codex/skills/vnt-operations/references/client-usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# VNT 客户端程序与配置

## 源码依据与版本核对

当前客户端源码位于 `D:\rust\vnt`。关键来源:

- `README.md`:用户入口和安全说明。
- `Cargo.toml`:程序名称与 feature。
- `src/args_config.rs`:CLI 参数、TOML 字段、默认值和覆盖规则。
- `src/main_cli.rs`、`src/main_ctrl.rs`、`src/main_web.rs`:三个程序的运行行为。
- `.github/workflows/rust.yml`:发行包的实际内容。

发行 zip 包含同一目标平台的 `vnt2_cli`、`vnt2_ctrl`、`vnt2_web`(Windows 带 `.exe`)。桌面安装包是独立的 Tauri 客户端。命令示例在 Windows 上为程序名补 `.exe`;Unix 首次解压后执行 `chmod +x vnt2_*`。

在给出最终命令前优先运行:

```text
vnt2_cli --version
vnt2_cli --help
vnt2_web --help
vnt2_ctrl --help
```

`vnt2_cli --conf-example` 会在当前工作目录写入 `example_config.toml`,仅在用户允许创建该文件时运行。

## 选择程序

| 程序 | 用途 | 关键行为 |
| --- | --- | --- |
| VNT 桌面客户端 | Windows 普通用户 | 图形界面;可按需启用进程内 Web 访问。 |
| `vnt2_web` | 浏览器管理、NAS、无桌面主机、多实例 | 默认监听 `127.0.0.1:19099`;配置存于工作目录的 `vnt_config/`;通过 Bearer token 保护 API。 |
| `vnt2_cli` | 单实例、服务化、脚本化 | 直接传 CLI 参数或用 `--conf` 读取 TOML;TUN/TAP 通常需要管理员/root。 |
| `vnt2_ctrl` | 查询后台 `vnt2_cli` | 支持 `info`、`ips`、`clients`/`list`、`route`,用 `--port` 连接非默认控制端口。 |

最小客户端示例:

```text
vnt2_cli --network-code my-network --server quic://vpn.example.com:29872 --password "shared-network-password"
```

兼容参数 `-k` 也可设置网络编号;新命令优先写清晰的 `--network-code`。同一虚拟网络中的客户端必须使用相同的服务端、网络编号和网络密码。

Web 管理示例:

```text
vnt2_web --addr 127.0.0.1:19099 --token "at-least-16-characters"
```

也可通过 `VNT_WEB_TOKEN` 提供 token。未指定时程序生成随机 token,并在日志中输出带 `?token=` 的访问链接。只有明确需要远程访问时才监听非回环地址;远程访问应配合防火墙或 HTTPS 反向代理。

控制后台 CLI:

```text
vnt2_ctrl info
vnt2_ctrl clients
vnt2_ctrl route
vnt2_ctrl --port 11234 info
```

`ctrl_port = 0` 会禁用控制服务。

## CLI 与配置文件合并

`vnt2_cli --conf path/to/client.toml` 可与 CLI 参数同时使用:

- `Option` 类型参数由显式 CLI 值覆盖文件值。
- 可重复的列表参数在 CLI 非空时覆盖文件列表,否则使用文件列表。
- 布尔开关通常为 CLI `true` 与文件值做启用合并;CLI 不提供通用的“反向关闭文件中 true”能力。
- `network_code` 必填;`server` 在正常组网中也应设置。
- 已删除 `no_tun`;必须迁移到 `device_mode = "no"`、`"tun"` 或 `"tap"`。

不要仅凭本文猜测边界值;使用当前二进制的 `--help` 和源码中的 `FileConfig`/`Args` 核对。

## 推荐 TOML 基线

```toml
config_name = "office-node"
network_code = "my-network"
server = ["quic://vpn.example.com:29872"]

# 同一虚拟网络必须一致;开启后节点间使用端到端加密。
password = "replace-with-a-strong-shared-password"

device_mode = "tun"
device_name = "office-node"

# 自签名服务端建议使用启动日志给出的 SHA-256 指纹。
cert_mode = "finger:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"

no_punch = false
no_broadcast = false
rtx = false
compress = false
fec = false
auto_sync_subnet = false
no_nat = false
allow_mapping = false
allow_ikev2 = false
```

不要把示例秘密原样投入生产。`config_name` 是 Web 配置格式支持的展示名;CLI 的 `FileConfig` 会忽略未知字段失败与否应按当前版本验证,给纯 CLI 配置时可省略它。

## 参数速查

### 服务端与直连

- `server = ["quic://host:29872", "tcp://host:29872", "wss://host:29872"]` 可配置多个服务端以容灾。
- `dynamic://domain` 从 DNS TXT 解析;`dynamic://https://...` 接口返回按换行分隔的服务端地址。
- `peer_address` 可重复,接受 `ip:port`、`tcp://ip:port`、`udp://ip:port`。无协议时同时尝试 TCP/UDP,端口必须是对端 `tunnel_port`。
- `no_punch = true` 关闭自动打洞,但显式 `peer_address` 仍可直连。
- `turn = ["目标IP或CIDR,中转虚拟IP"]`。中转填写网关虚拟 IP 时强制服务器中继;命中目标不参与 P2P 打洞。
- `punch_model = ["目标IP或CIDR,IPv4Udp,IPv4Tcp"]` 限制打洞方式。模式为 `IPv4Tcp`、`IPv4Udp`、`IPv6Tcp`、`IPv6Udp`;双方使用允许集合的交集。

### 设备与安全

- `device_mode = "tun"`:三层虚拟网卡,默认模式。
- `device_mode = "tap"`:二层 Ethernet;Windows 需管理员权限并预装 TAP-Windows `tap0901`。
- `device_mode = "no"`:不创建网卡,只提供流量出口和端口映射,通常不需管理员权限。
- Windows TUN 使用随程序提取的 `wintun.dll`;Linux/macOS 使用系统 TUN/TAP 能力。
- `device_id` 同一服务端和网络内不得冲突;缺省时使用机器标识。`device_name` 缺省取 hostname。
- `tunnel_port` 固定 P2P 端口;同机多实例不能使用同一显式端口。
- `outbound_interface` 绑定服务端通信、打洞及转发流量使用的出口网卡。
- `cert_mode = "skip"` 跳过服务端证书验证(默认但不推荐公网生产);`standard` 使用系统根证书;`finger:<64位hex>` 绑定 SHA-256 指纹。
- `password` 是节点间端到端加密密码,不是 Web token,也不是服务端管理密码。
- `allow_ikev2 = true` 信任服务端注入的 IKEv2 明文 IPv4 流量;仅在确实要与 IKEv2 客户端互通时开启。

### 网络转发与质量

- `input = ["源网段CIDR,目标虚拟IP"]` 将指定网段流量导向出口节点。
- `output = ["真实CIDR"]` 声明本机允许转发的真实网段。
- `subnet_mapping = ["映射CIDR,真实CIDR"]` 做等掩码映射;真实范围必须被 `output` 覆盖。
- `auto_sync_subnet = true` 自动应用在线节点上报的出口子网。
- `no_nat = true` 关闭内置子网 NAT,此时必须另行配置系统转发/NAT。
- `port_mapping = ["tcp://0.0.0.0:81-10.26.0.2-192.168.1.10:80"]` 表示本地监听、目标虚拟节点和最终目标。
- 作为远端端口映射出口的节点必须设置 `allow_mapping = true`。
- `no_broadcast = true` 关闭本机发出的 IPv4 广播和组播转发;ARP、其他二层广播及单播不受影响。
- `rtx` 启用 QUIC 优化通道;`compress` 启用 LZ4;`fec` 用额外带宽换取丢包恢复。根据链路实测启用,不要默认全部开启。
- `mtu` 只在明确诊断到 MTU/分片问题时调整。

## 多实例和验证

Web 端允许多个配置实例,但会拒绝以下冲突:

- 相同服务端范围、相同 `network_code` 且相同 `device_id`;双方都未指定 `device_id` 也可能因机器标识相同而冲突。
- 两个实例显式设置相同 `tunnel_port`。

验证顺序:确认程序版本;确认服务器、网络编号和密码一致;确认实例进入 `Running`;查看分配的虚拟 IP 和节点列表;最后用虚拟 IP `ping` 或真实业务流量验证。ICMP 失败也可能只是主机防火墙阻止 ping。
141 changes: 141 additions & 0 deletions .codex/skills/vnt-operations/references/client-web-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# VNT 客户端 Web API

## 连接与鉴权

本接口由独立 `vnt2_web` 或桌面端启用的 Web 访问提供。独立程序默认地址是 `http://127.0.0.1:19099`。

若用户未提供访问数据,询问完整访问链接(通常包含 `?token=...`),或分别询问 API 根地址和 token。完整链接的查询参数只用于提取 token,API 请求必须改为:

```text
Authorization: Bearer <token>
```

不要继续把 token 放在请求 URL 中。先请求:

```text
GET /api/version
GET /api/runtime
```

`runtime` 当前可能返回 `standalone_web` 或 `desktop_web`。所有业务响应采用:

```json
{"code": 0, "msg": "success", "data": {}}
```

HTTP 2xx 不等于业务成功;只有 `code == 0` 才成功。`401` 表示 Web token 不正确或已变化,只重新获取/重试一次。

通用辅助脚本示例(从 stdin 输入带 token 的完整链接):

```text
python scripts/vnt_api.py client --access-url-stdin GET /api/version
python scripts/vnt_api.py client --access-url-stdin GET /api/instances
```

脚本路径相对于本 skill 目录。若调用环境不方便重复输入,可将链接放入临时进程环境变量并用 `--access-url-env`;不要写入仓库文件。

## 接口目录

| 方法 | 路径 | 用途 | 输入 |
| --- | --- | --- | --- |
| GET | `/api/version` | 程序版本 | 无 |
| GET | `/api/runtime` | 运行形态 | 无 |
| GET | `/api/instances` | 所有实例 | 无 |
| GET | `/api/start/status?file_name=...` | 启动状态和日志 | 配置文件名 |
| GET | `/api/info?file_name=...` | 实例综合状态 | 配置文件名 |
| GET | `/api/peers?file_name=...` | 节点列表 | 配置文件名 |
| GET | `/api/routes?file_name=...` | 路由列表 | 配置文件名 |
| POST | `/api/start` | 启动实例 | `{"file_name":"x.toml"}` |
| POST | `/api/stop` | 停止实例/中止启动 | `{"file_name":"x.toml"}` |
| POST | `/api/restart` | 停止后重新启动 | `{"file_name":"x.toml"}` |
| DELETE | `/api/instance?file_name=...` | 移除已停止实例卡片 | 配置文件名 |
| GET | `/api/config/list` | 配置摘要列表 | 无 |
| GET | `/api/config?file_name=...` | 读取 TOML 原文 | 配置文件名 |
| POST | `/api/config` | 新建或覆盖配置 | `{"file_name":"x.toml","config":"..."}` |
| DELETE | `/api/config?file_name=...` | 删除未占用的配置文件 | 配置文件名 |

查询参数必须进行 URL 编码。文件名不能为空,不能包含 `..`、`/` 或 `\\`。保存配置时无扩展名会补 `.toml`,其他扩展名会被拒绝;省略或传空 `file_name` 时服务端生成时间戳文件名。

## 典型工作流

### 查看状态

1. `GET /api/instances`,取得准确 `file_name` 和 `status`。
2. 针对实例读取 `/api/info`、`/api/peers` 或 `/api/routes`。
3. 不要把展示名 `config_name` 当作 `file_name`。

实例摘要:

```json
{
"file_name": "office.toml",
"config_name": "Office",
"status": "Running"
}
```

状态值由当前版本序列化,主要关注 `Starting`、`Running`、`Stopped`。

### 保存配置

先读取当前配置并保留用户未要求改变的字段。请求体中的 `config` 是 TOML 字符串,不是嵌套 JSON 对象:

```json
{
"file_name": "office.toml",
"config": "config_name = \"Office\"\nnetwork_code = \"team-a\"\nserver = [\"quic://vpn.example.com:29872\"]\ndevice_mode = \"tun\"\n"
}
```

服务端会解析 TOML 并拒绝旧的 `no_tun = true`。写入成功后再 `GET /api/config` 比对。覆盖正在运行实例的配置不会自动重启;由用户决定是否调用 restart。

脚本示例:

```text
python scripts/vnt_api.py client --access-url-stdin POST /api/config --json-file office-request.json
```

`office-request.json` 只能是用户允许的临时文件,且不得放入秘密 token。若无需落盘,可使用 `--json`。

### 启动与轮询

调用:

```json
{"file_name":"office.toml"}
```

发送到 `/api/start` 后,每 0.5–2 秒请求 `/api/start/status?file_name=office.toml`,但避免无限轮询。响应 data:

```json
{
"status": "Starting",
"logs": ["..."]
}
```

到 `Running` 即成功;到 `Stopped` 即失败或已停止,报告相关日志。设置合理总超时;服务端不可达时启动任务可能持续重试,用户要求取消时调用 `/api/stop`。

### 停止、重启和清理

- `POST /api/stop` 会中止尚在注册重试中的启动任务,并停止运行实例。
- `POST /api/restart` 最多等待约 5 秒停止,再尝试启动;之后仍需轮询状态。
- `DELETE /api/instance` 只移除 `Stopped` 实例的内存条目,不删除 TOML。
- `DELETE /api/config` 删除 TOML,若配置仍被实例占用会失败。

先停止、确认 `Stopped`、必要时移除实例条目,最后才删除配置文件。删除不是“修复卡片”的首选;启动失败残留应优先用 `/api/instance` 清理。

## 返回数据要点

`/api/info` 包含虚拟 IP、前缀、网关、设备 ID、服务器状态、NAT、公网地址、在线/离线/直连数量,以及 FEC、压缩、加密、RTX 和配置是否变化等信息。

`/api/peers` 返回各虚拟节点的设备信息、在线状态、连接路径和流量信息。`/api/routes` 按目标虚拟 IP 返回一个或多个路由,每条路由包含地址、协议、metric、RTT 和丢包率。以实际响应为准,不要依赖未使用字段的固定顺序。

## 错误处理

- HTTP `401`:token 无效;重新询问/刷新一次。
- `code != 0`:展示已脱敏的 `msg`,不要继续执行依赖该步骤的写操作。
- `Config file not found`:重新读取配置列表,确认 `file_name`。
- `实例不存在`:重新读取实例列表,不要假设配置也不存在。
- `此配置已被使用,不能删除`:先停止并确认状态,不要强制绕过。
- 网络超时:先做一次只读健康探测;不要循环重放 POST/DELETE。
Loading