- 域名自有化:全站 ipw.cn 映射到自有域名(站点 nipw.cn;取本机 IP 用 test./4./6.wsmdn.top),
7 篇正文与 6 个 svg 图层名同步替换;纯文本接口的示例代码相应重写。
- 新增 4 篇 API 文档(api/ip/{locate,myip,query}.md、api/whois/query.md):按自有接口实测
重写,给出可直接执行的公开实例(节点直连 + middleware-1 转发),另设 1.2 节引导到拨测
控制台 boce.wsmdn.top 取用已部署的节点与中间件。
- 新增 4 篇文档:tls / dns_dig / code_getip / check_userip_ipv4_ipv6,正文首行徽标一律标
「转载」(本站为转载方)。
- 补齐 9 张原始配图,置于 public/doc/ 下同名覆盖(wayback 仅存 1 张,实际取自 arquivo.pt)。
- 修正 Serverless 部署支持范围的表述,与仓库内实际实现对齐;/info 拆分后正文同步。
15 KiB
后端节点部署
后端节点提供全部检测 API(IP 归属地 / ASN / SSL / DNS / DNSSEC / Whois / TCPing / 测速 / 截图等),可在任意地区部署,组成去中心化测试网络。
方案一:EdgeOne
腾讯云 EdgeOne 支持 Go 边缘函数,点击下方按钮通过 EdgeOne Makers 一键部署 serverless/edgeone/ 版本(无需本地构建):
也可以使用 EdgeOne CLI 手动部署:
cd serverless/edgeone
npx edgeone pages deploy -n ipw-cn -t $EDGEONE_API_TOKEN
serverless/edgeone/ 版本的配置来源为 环境变量 + 远端配置(REMOTE_CONFIG_URL)。
数据上报(可选)
serverless/edgeone/ 版本没有 WS 客户端(边缘函数不维持长连接),因此上报只走 HTTP 一条路:按周期把统计与拨测明细 POST <report-url>/report 到收集中心。下列键同样支持环境变量与远端配置两种来源(远端配置优先):
| 配置键 | 环境变量 | 说明 |
|---|---|---|
node-id |
NODE_ID |
上报身份(写入 probe_results.origin);留空回退 hostname |
report-url |
REPORT_URL |
收集中心基址;留空则不上报 |
report-token |
REPORT_TOKEN |
/report 鉴权,请求头 Authorization: Bearer <token>;收集中心未配 token 时可留空 |
report-interval-seconds |
REPORT_INTERVAL_SECONDS |
上报间隔秒,缺省 15 |
记账口径与主节点完全一致(节点是唯一记录者、stats 为增量累加、上报 at-most-once),报文格式见 节点 API 与协议 的「数据上报协议」一节。
Note
上报依赖进程存活期内的内存计数。若所用平台会把实例缩容到零,缓冲区会随实例回收丢失——上报只在实例存活期内累积。长驻部署(Docker / 二进制)不受此限。
方案二:Vercel
点击下方按钮一键导入仓库(部署目标为 serverless/edgeone/cloud-functions 目录,即 Go 边缘函数版本):
Important
Serverless 节点均为 IPv4-only(EdgeOne、Vercel 等平台的出站网络只提供 IPv4)。部署后需要:
- 给节点配置
SINGLE_STACK=ipv4(声明节点为 IPv4 单栈),跳过 IPv6 相关测试,避免无意义的错误日志与超时- 在前端配置
config/index.ts中,该节点只能填入APIBaseURL.IPv4(拨测节点池的 IPv4 栈),不要放进DualStack/IPv6栈
方案三:Docker
src/ 目录提供 Dockerfile(多阶段构建,产物基于 Alpine,支持多架构):
cd src
docker build -t lemon-ipw .
docker run -d --restart unless-stopped -p 8080:8080 \
-v $(pwd)/setting.json:/home/appuser/setting.json \
lemon-ipw
--restart unless-stopped:主进程意外退出时 Docker 自动拉起容器;手动docker stop不会触发重启。
配置通过挂载 setting.json 提供(注意挂载到容器工作目录 /home/appuser),也可用环境变量覆盖(PORTS / CORS / TRUSTED_PROXIES / ACCESS_TOKEN 等)。
Tip
容器内 OTA 替换二进制意义有限(重建容器即回滚到镜像版本),如需彻底关闭可设
NODE_OTA=false;镜像不含 IP 库数据,首次启动若ipdb未关闭会现场拉取约 450MB 到容器可写层,轻量部署建议直接IPDB=false。
多架构:Dockerfile 已适配 buildx——构建阶段固定在构建机原生平台交叉编译(TARGETOS/TARGETARCH),目标架构无需 QEMU 模拟。本机为其他架构构建:
cd src
docker buildx build --platform linux/arm64 -t lemon-ipw:arm64 --load .
打 v* 版本标签发版时,CI(.github/workflows/docker.yml)会自动构建 linux/amd64 / linux/arm64 / linux/arm/v7 三架构镜像(amd64 在 x64 实例上原生构建,arm64/armv7 在 GitHub 原生 ARM 实例 ubuntu-24.04-arm 上交叉构建,全程无 QEMU),推送 GHCR 与 Docker Hub:
- GHCR:
ghcr.io/<owner>/<repo>/lemon-ipw(自动) - Docker Hub:
docker.io/<namespace>/lemon-ipw(workflow 中暂未启用——.github/workflows/docker.yml已预留注释,取消注释并配置DOCKERHUB_USERNAME/DOCKERHUB_TOKENSecrets 即可开启)
均带 版本 与 major.minor 标签。部署直接:
docker run -d -p 8080:8080 \
-v $(pwd)/setting.json:/home/appuser/setting.json \
ghcr.io/nomdn/ipw-cn/lemon-ipw:v1.2.3
Docker 会按宿主机架构自动拉取 manifest 中对应的镜像变体。
方案四:二进制
# 编译(Go 后端在 src/ 目录)
cd src && go build -o lemonipw .
# 运行(与 setting.json 同目录)
./lemonipw
首次启动自动下载 IP 数据库(约 450MB),之后每 24 小时自动更新一次。需要守护运行时,可参考下方「方案五」生成的 systemd 服务,或手动创建 service 文件(ExecStart 指向二进制,WorkingDirectory 指向 setting.json 所在目录)。
方案五:一键安装(install.sh)
仓库根目录提供 install.sh 一键安装脚本:自动检测架构 → 下载最新 release 二进制 → 交互式输入配置(无需准备 setting.json,配置以环境变量注入)→ 生成 systemd 服务并守护进程。
# 先下载脚本到本地(勿用 curl | bash 管道执行,避免下载中断导致语法解析错误)
git clone https://github.com/nomdn/ipw-cn && cd ipw-cn # 或
curl -fsSL https://raw.githubusercontent.com/nomdn/ipw-cn/main/install.sh -o install.sh
sudo bash install.sh
交互式配置项(直接回车使用默认值):
| 配置项 | 默认值 | 说明 |
|---|---|---|
| 安装目录 | /opt/lemon-ipw |
二进制与工作目录 |
| 监听端口 | 8080 |
PORTS |
| 单栈模式 | 双栈 | SINGLE_STACK,ipv4 / ipv6 / 留空 |
| access-token | 留空 | 留空 = 不启用鉴权 |
| DNS 服务器 | 留空 | 主从逗号分隔(119.28.28.28:53,223.5.5.5:53);留空 = 启动时自动探测系统 DNS |
| DNSSEC 专用 DNS | 留空 | 留空 = 沿用 dns-server;都留空 = 自动探测系统 DNS |
| IP 数据库 | Y |
IPDB,首次启动下载约 450MB |
| CORS | 留空 | 逗号分隔允许来源 |
| 远端配置地址 | 留空 | REMOTE_CONFIG_URL |
| WS 通道接入 | N |
选 y 后继续输入 WS_URL / NODE_ID / NODE_KEY |
| 其他环境变量 | 无 | 每行一个 K=V,空行结束。如需可信代理在此输入 TRUSTED_PROXIES=<IP/CIDR 逗号分隔>(配置后归属地接口只信任这些代理转发的 X-Forwarded-For,防伪造) |
WS 接入特殊规则:
WS_URL留空时自动使用默认值wss://middleware-1.api-ipw.wsmdn.top/ws;填写自己的中间件地址时须为完整路径(含wss://前缀与/ws路径,如wss://host:8092/ws),逗号分隔多个则同时连接全部(多活)NODE_ID强制自动生成 UUID(无需输入,如4580ea9d-2a16-4b8e-8090-5f2e7f0a2229),适合作为节点唯一标识NODE_KEY必填:不加 key 禁止启用 WS(中间件ws-keys必须包含该节点,否则注册被拒 401);安装完成后脚本会提示把"<NODE_ID>": "<NODE_KEY>"加入中间件 setting.json 的ws-keys
安装完成后自动生成并启动 systemd 服务(lemon-ipw.service),配置以 Environment="K=V" 注入,无需 setting.json。常用管理命令:
systemctl status lemon-ipw # 状态
journalctl -u lemon-ipw -f # 日志
sudo systemctl restart lemon-ipw # 重启(改配置后)
修改配置:sudo systemctl edit --full lemon-ipw 编辑环境变量,保存后 sudo systemctl daemon-reload && sudo systemctl restart lemon-ipw 生效。
Warning
版本兼容提醒:v1.1.0 及更早的 release 二进制读的是旧环境变量名
IPW_WS_URL/IPW_NODE_ID/IPW_NODE_KEY(8-20 及之前构建)。install.sh 生成的 service 用的是新名WS_URL/NODE_ID/NODE_KEY——旧二进制 + 新 service 会因读不到配置而完全不启用 WS(启动日志无任何 ws 输出)。升级到包含改名后的新 release 即可;急用可临时把 service 环境变量改回IPW_前缀。
配置
后端配置见 配置文件:setting.json 或环境变量,支持远端配置(REMOTE_CONFIG_URL,优先级:远端 > 环境变量 > setting.json)。
WS 通道接入(可选)
后端节点可作为 WS 客户端接入 独立中间件 的 WS 通道,拨测请求经 WebSocket 转发,节点本地执行探针后回传。不配置则完全走原 HTTP 接口。
配置三个环境变量(或 setting.json 的 ws-url / node-id / node-key,env 优先;也支持远端配置覆盖,除非列入 remote-ignore-config):
WS_URL=ws://<中间件IP>:8092/ws \
NODE_ID=<节点id,与中间件 api-base-url / ip-location-api 池的节点 id 一致> \
NODE_KEY=<注册key,与中间件 ws-keys[节点id] 一致;节点未配置 key 可留空> \
./lemonipw
WS_URL支持逗号分隔多个中间件(ws://中间件1:8092/ws,ws://中间件2:8092/ws),同时连接全部(多活):每个地址独立注册并保持连接,任一断开只重连自己,不影响其他中间件;注意多个地址指向同一中间件实例时,同nodeId后注册的连接会顶掉先前的- 双向心跳:节点每 10s 发 ping,中间件回 pong;心跳发送连续失败 3 次判定中间件不可用,断开后 3s 重试(注册被拒 30s 重试)
- 收到
probe后节点直调探针函数(带缓存)并回probe_result,结果与 HTTP 通道一致 - 节点注册带
NODE_KEY:中间件ws-keys里配了 key 就必须传对,否则返回 401 并断开;未配置 key 的节点开放注册
注意:NODE_ID 必须与中间件 APIBaseURL / IPLocationAPI 池中的节点 id 一致,且该节点需配置 "ws": true 才会走 WS 通道。未连接中间件时,ws:true 节点的拨测会返回 502。
运行时配置管理(可选)
节点暴露 /v1/config,供收集中心读写该节点当前生效的配置(内存值),是「控制台改配置不用登机器」的基础:
| 动作 | HTTP | WS | 说明 |
|---|---|---|---|
| 读取 | GET /v1/config |
config + action=get |
返回生效配置快照 + secretKeys + restartRequiredKeys |
| 修改 | PATCH /v1/config(?persist=1 写回本地文件) |
config + action=patch |
只应用传入的键,其余不动 |
| 刷新远端 | POST /v1/config/refresh |
config + action=refresh |
重新拉 remote-config-url 并应用 |
三条重要约定:
- 凭据类键不回显明文:
access-token/node-key/report-token在快照中为***。调用方下发配置时必须剔除这些键,否则会把真值覆盖成三个星号。收集中心控制台已自动剔除。 - 节点不自行重启:
port/cors/ipdb/report-interval-seconds/trusted-proxies/node-id/node-key/access-token这些启动期固定的键,改动后在应答的restartRequired中如实列出,但不会自动重启进程——重启会中断在途服务,时机由运维 / 编排层掌握。ws-url是例外:热生效,控制器按新地址多退少补。 - 只 PATCH 内存的改动会被重启顶掉:节点侧优先级是 远端 > 环境变量 >
setting.json,长期生效需写回托管配置或本地文件,详见 配置文件 的「运行时配置管理」一节。
Note
HTTP 管理面需要凭据:节点未配置
access-token时,/v1/config与/v1/ota整组返回403(此时业务接口也无鉴权,开放配置读写等于公网可改配置)。WS 通道不受此限制——节点是 WS 客户端,指令只来自已通过中间件ws-keys校验的连接。
OTA 升级(收集中心下发,可选)
节点支持由收集中心下发一次性升级任务:下载新二进制 → 校验 → 预检 → 原子替换 → 重启,全程无需登录节点主机。
触发方式:收集中心经 WS ota 消息下发(HTTP 回退 POST /v1/ota)。请求体三选一指定下载源:
| 字段 | 说明 |
|---|---|
version |
按版本号下发。节点按自身平台拼资产名 lemonipw-{goos}-{goarch}[.exe],到资产基址 {assetBase}/{tag}/ 下取;assetBase 缺省为 GitHub Releases,自建镜像源可覆盖 |
url |
直发下载地址(完全自定义) |
sha256 |
可选,提供即强校验(hex64,兼容 sha256: 前缀) |
执行流程:下载到与目标同分区的临时文件(保证 rename 原子)→ 体积下限 1MB(防错误页)→ sha256 校验 → 预检(试运行新二进制 -v,确认架构匹配、可执行,在停机前拦下损坏文件)→ 当前二进制改名 .old → 新文件就位 → 重启。任一步失败都会回滚 .old。
进度回传:经 WS ota_result 依次回报 accepted → downloading → verifying → installing → restarting,失败时带 error。重启后连接必然断开,最终结果由收集中心以重连注册上报的新版本号判定(15 分钟未观测到新版本即判超时失败)。
并发与开关:
- 同一时刻只允许一个 OTA 任务,重复下发直接拒绝。
node-ota: false(envNODE_OTA)可完全禁用:节点拒绝一切 OTA 指令并回传原因。只读文件系统 / 编排托管(Docker Swarm、K8s 等自行管理镜像)的部署建议关闭。- 部署方式受限导致替换失败(如容器只读层)时,升级会失败并回滚,此时仍按传统方式人工升级。
手动更新(OTA 不可用时):
# Docker:拉取新镜像后重建容器
docker pull lemon-ipw && docker stop lemon-ipw && docker run ... lemon-ipw
# systemd:替换二进制后重启服务
systemctl restart lemon-ipw
版本与能力上报
节点无论是否接入 WS,都会上报自身版本与支持的管理能力:
- 版本号来自构建时注入的
VERSION,随 WSregister报文上报(字段version);纯 HTTP 主节点(无 WS 连接)由收集中心探活后再请求GET /info取回(GET /只返回{"status":"ok"})。边缘函数版本不提供/info。 - 能力清单(
capabilities)取值为probe/report/config/ota,用于让收集中心在下发管理指令前判断该节点能否理解——老版本节点的消息循环没有对应分支,收到管理消息会静默忽略,只能靠超时暴露。 - 收集中心「节点状态」页展示每个节点的版本号,并据此判断哪些节点需要升级;节点升级部署后重新注册即为新版本。
能力清单的取值与三态判定规则见 节点 API 与协议参考 的「能力清单」一节。