# STUN 导航页 一个给 Lucky STUN 使用的个人导航页。Lucky 的 STUN 地址变化后,通过 webhook 把最新地址推到这里;浏览器打开导航页时,按钮会跳转到最新地址。 ## 启动 ```bash WEBHOOK_TOKEN=换成一串随机密钥 PORT=8080 npm start ``` 然后访问: ```text http://服务器IP:8080 ``` 管理页: ```text http://服务器IP:8080/admin ``` 打开管理页后填写 `WEBHOOK_TOKEN`,即可手动新增、修改、删除导航项,也可以修改浏览器标题、顶部标识、首页标题和副标题。密钥只保存在当前浏览器本地。 ## 部署到 EdgeOne Pages 项目已经包含 EdgeOne Pages 改造版本,见 `EDGEONE.md`。 核心变化: - 静态页面从 `public/` 部署 - `/api/*` 由 `edge-functions/api/[[default]].js` 提供 - 数据保存到 EdgeOne KV,绑定变量名需要设置为 `STUN_NAV_KV` - 管理密钥使用环境变量 `WEBHOOK_TOKEN` ## Lucky Webhook 配置 推荐让 Lucky 发送 JSON: ```text URL: http://你的导航页地址:8080/api/webhook/alist?token=换成一串随机密钥 Method: POST Content-Type: application/json Body: { "name": "AList", "group": "文件", "url": "http://{STUN_你的STUN规则名_ADDR}", "note": "家中文件服务" } ``` 也可以不用 JSON,直接用 URL 参数: ```text http://你的导航页地址:8080/api/webhook/alist?token=换成一串随机密钥&name=AList&group=文件&url=http://{STUN_你的STUN规则名_ADDR} ``` Lucky 的全局变量需要把 `规则名` 替换成 STUN 穿透规则列表里的真实规则名,不是导航页服务名,也不是环境变量。例如你的 STUN 规则名叫 `alist-web`,就写 `{STUN_alist-web_ADDR}`。 ```text {STUN_规则名_ADDR} {STUN_规则名_IP} {STUN_规则名_PORT} ``` ## Webhook 支持的字段 | 字段 | 说明 | | --- | --- | | `id` | 服务唯一标识;也可以写在 `/api/webhook/:id` 里 | | `name` | 页面显示名称 | | `group` | 页面分组 | | `url` | 完整跳转地址,例如 `http://1.2.3.4:12345` | | `addr` | 地址加端口,例如 `1.2.3.4:12345` | | `host` / `ip` + `port` | 分开发送主机和端口 | | `protocol` / `scheme` | `http` 或 `https`,默认 `http` | | `path` | 跳转路径,例如 `/admin` | | `note` | 备注 | 收到的数据会保存在 `data/links.json`。 ## 删除导航 删除某个导航项时,用它的 `id` 调用删除接口。`id` 默认来自 `/api/webhook/:id` 里的那一段,例如 `/api/webhook/alist` 创建的导航,删除时就是: ```bash curl -X DELETE "http://你的导航页地址:8080/api/services/alist?token=换成一串随机密钥" ``` 删除刚才测试的百度示例: ```bash curl -X DELETE "http://你的导航页地址:8080/api/services/baidu?token=换成一串随机密钥" ``` 如果不想调用接口,也可以停掉服务后直接编辑 `data/links.json`,删除对应对象,再重新启动服务。 ## 安全建议 - 一定要设置 `WEBHOOK_TOKEN`。 - 不建议直接把导航页暴露到公网裸奔,最好放到 HTTPS 反代后面。 - 如果导航页本身也通过 STUN 暴露,至少给入口加访问控制或复杂路径。