Files
stun-nav/README.md
2026-07-12 17:13:38 +08:00

8.6 KiB
Raw Permalink Blame History

STUN Nav

一个给 Lucky STUN 使用的个人导航页。

Lucky 的 STUN 外网地址变化后,通过 webhook 把最新地址推送到这个项目;导航页和后台会读取保存的最新地址,点击卡片即可跳转到当前可用入口。

项目支持两种部署方式:

  • 本地 / 家中服务器部署:server.mjs + data/links.json
  • EdgeOne Pages 部署:静态页面 + Edge Functions + KV

功能

  • 自动接收 Lucky webhook,更新导航地址
  • 首页按分组展示服务卡片
  • 后台 /admin 手动新增、编辑、删除导航
  • 后台修改页面标题、顶部标识、首页标题、首页副标题
  • 支持 GET、POST JSON、表单等多种 webhook 方式
  • 支持 EdgeOne Pages 无服务器部署

项目结构

.
├── public/                         # 前端页面
│   ├── index.html                  # 首页
│   ├── admin.html                  # 后台
│   ├── app.js
│   ├── admin.js
│   └── styles.css
├── server.mjs                      # 本地 Node 服务
├── data/links.json                 # 本地数据文件,已被 .gitignore 忽略
├── edge-functions/api/[[default]].js # EdgeOne API
├── edgeone.json                    # EdgeOne Pages 配置
├── EDGEONE.md                      # EdgeOne 部署说明
└── package.json

本地部署

适合部署在家中服务器、NAS、VPS、Docker 容器等环境。

1. 安装 Node.js

需要 Node.js 18 或更高版本。

检查版本:

node -v

2. 启动服务

WEBHOOK_TOKEN=换成你自己的随机密钥 PORT=8080 npm start

参数说明:

参数 说明
WEBHOOK_TOKEN 管理和 webhook 密钥,必须设置成随机字符串
PORT 服务端口,默认 8080

启动后访问:

http://服务器IP:8080/
http://服务器IP:8080/admin

3. 本地数据保存位置

本地版本数据保存在:

data/links.json

这个文件包含导航信息和页面设置,默认不会提交到 GitHub。

4. 反向代理建议

如果你用 Nginx、Caddy、Lucky Web 服务等反向代理,建议:

  • 使用 HTTPS
  • 不要把后台裸露给陌生人
  • WEBHOOK_TOKEN 使用足够长的随机字符串

EdgeOne Pages 部署

适合让导航页本身拥有稳定公网入口,例如:

https://dh.example.com/
https://dh.example.com/admin

1. 导入仓库

在 EdgeOne Pages / Makers 中创建项目,导入本仓库。

项目已经包含:

edgeone.json
edge-functions/api/[[default]].js

edgeone.json 会把静态输出目录设置为:

public

并把:

/admin

重写到:

/admin.html

2. 创建 KV

创建一个 KV Namespace,并绑定到 Pages 项目。

绑定变量名必须填写:

STUN_NAV_KV

EdgeOne 版本会把所有数据保存到 KV 的这个 key:

stun_nav_store

3. 配置环境变量

在 EdgeOne 项目的环境变量中配置:

WEBHOOK_TOKEN=换成你自己的随机密钥

这个密钥用于:

  • Lucky webhook 更新导航
  • 后台保存页面设置
  • 后台新增、编辑、删除导航

4. 部署后访问

https://你的域名/
https://你的域名/admin

首次打开 /admin,填写 WEBHOOK_TOKEN,之后密钥只会保存在当前浏览器本地。

后台使用

后台地址:

/admin

后台包含:

  • 页面设置:修改浏览器标题、顶部标识、首页标题、首页副标题
  • 新增导航:手动新增一个导航入口
  • 导航列表:查看、编辑、删除已有导航

字段说明:

字段 说明
ID 导航唯一标识,例如 alist、fnnas
名称 首页显示名称
分组 首页卡片分组
地址 点击跳转地址
备注 可选说明

如果编辑时修改了 ID,系统会保存新 ID,并删除旧 ID 对应的记录。

Lucky Webhook 配置

Webhook 接口格式:

/api/webhook/:id

例如:

/api/webhook/alist
/api/webhook/fnnas

其中 alist、fnnas 就是导航项 ID。

方式一:GET URL 参数

这是最简单的方式。

接口地址:

https://你的域名/api/webhook/fnnas?token=你的随机密钥&name=FNNAS&group=NAS&url=http://{STUN_你的STUN规则名_ADDR}

请求方法:

GET

请求头:

不用填

方式二:POST JSON

接口地址:

https://你的域名/api/webhook/fnnas?token=你的随机密钥

请求方法:

POST

请求头:

Content-Type: application/json

请求体:

{
  "name": "FNNAS",
  "group": "NAS",
  "url": "http://{STUN_你的STUN规则名_ADDR}",
  "note": "家里 NAS"
}

方式三:拆分 host 和 port

如果你想分别传 IP 和端口:

{
  "name": "FNNAS",
  "group": "NAS",
  "protocol": "http",
  "host": "{STUN_你的STUN规则名_IP}",
  "port": "{STUN_你的STUN规则名_PORT}"
}

最终会拼成:

http://IP:PORT

Lucky STUN 变量说明

Lucky 的 STUN 全局变量不是系统环境变量,而是 Lucky webhook 中可用的占位符。

格式:

{STUN_规则名_ADDR}
{STUN_规则名_IP}
{STUN_规则名_PORT}

这里的 规则名 必须替换成 Lucky 里 STUN 穿透规则列表中的真实规则名。

例如:

STUN 规则名:fnnas
完整地址:{STUN_fnnas_ADDR}
IP:{STUN_fnnas_IP}
端口:{STUN_fnnas_PORT}

如果你的规则名是:

AList-Web

就写:

{STUN_AList-Web_ADDR}

Webhook 字段

字段 说明 示例
id 服务唯一标识,也可写在 /api/webhook/:id fnnas
name 页面显示名称 FNNAS
group 页面分组 NAS
url 完整跳转地址 http://1.2.3.4:12345
addr 地址加端口 1.2.3.4:12345
host / ip 主机或 IP 1.2.3.4
port 端口 12345
protocol / scheme 协议,默认 http https
path 跳转路径 /admin
note 备注 家里 NAS

如果同时提供多个地址字段,优先级是:

url > addr > host/ip + port

API 说明

获取导航列表

curl "https://你的域名/api/services"

返回页面设置和导航列表。

新增或更新导航

curl -X POST "https://你的域名/api/webhook/fnnas?token=你的随机密钥" \
  -H "Content-Type: application/json" \
  --data '{"name":"FNNAS","group":"NAS","url":"http://1.2.3.4:12345"}'

删除导航

curl -X DELETE "https://你的域名/api/services/fnnas?token=你的随机密钥"

修改页面设置

curl -X PUT "https://你的域名/api/settings?token=你的随机密钥" \
  -H "Content-Type: application/json" \
  --data '{"browserTitle":"导航","brand":"HOME","title":"家庭服务","subtitle":"我的服务入口"}'

常见问题

1. 只访问 /api/webhook/fnnas?token=xxx 为什么新增失败?

因为只传了 ID 和 token,没有传导航地址。

至少需要传 url、addr,或者 host + port。

正确示例:

https://你的域名/api/webhook/fnnas?token=xxx&name=FNNAS&url=http://{STUN_fnnas_ADDR}

2. EdgeOne 上返回 KV 相关错误怎么办?

检查 KV 是否已绑定,绑定变量名必须是:

STUN_NAV_KV

3. 后台提示 invalid webhook token 怎么办?

检查后台输入的密钥是否等于部署时设置的:

WEBHOOK_TOKEN

4. Lucky 变量没有替换怎么办?

确认 Lucky webhook 配置位置支持全局变量,并确认 STUN 规则名完全一致。

例如规则名是 fnnas,就写:

{STUN_fnnas_ADDR}

不要写成:

{STUN_你的服务名_ADDR}

除非你的 STUN 规则名真的叫 你的服务名。

5. 页面看起来没有更新怎么办?

浏览器可能缓存了旧资源,可以尝试:

https://你的域名/admin?fresh=1

或者强制刷新浏览器。

项目的静态资源已经加了版本号,并在 edgeone.json 中设置了 Cache-Control: no-cache。

安全建议

  • 不要使用简单密码当 WEBHOOK_TOKEN
  • 不要把 WEBHOOK_TOKEN 发给别人
  • 如果密钥泄露,立即在部署平台更换
  • 后台 /admin 暴露在公网时,建议配合 EdgeOne 访问控制或其他鉴权
  • 本地部署时不要把 data/links.json 提交到公开仓库

开发

本地启动:

npm start

开发模式:

npm run dev

语法检查:

node --check server.mjs
node --check public/app.js
node --check public/admin.js
node --check 'edge-functions/api/[[default]].js'