fix: 管理入口改为「填链接」而非绑定特定隧道方案,并修掉配置接口的密钥泄露
用户反馈:「你不需要帮我处理 tunnel 这部分,也许我不是通过 tunnel 开放内网呢? 你只需要给我一个填写开放的管理端链接的地方。」 之前把「Cloudflare Tunnel」当成既定方案写进了配置与文档,这是替用户做了假设。 现在改为:项目只提供一个填地址的地方,怎么暴露完全由使用者决定。 - 删除 edge/cloudflare/tunnel.yml 与全部 tunnel 相关文档 - 新增 settings.adminUrl:管理界面里填一个地址,公开面板页脚出现「管理」按钮 指向它;留空则完全不显示(默认,避免在公网面板暴露管理面位置) - 只接受 http/https,javascript: 等协议被服务端拒绝(会被渲染成 <a href>) - 设置落在 local.monitors.json(私有层),只有自己的面板会出现该按钮 - 面板启动时额外拉 /api/monitors 合并 settings:原先只读静态 monitors.json (公开层),导致私有层的设置面板看不到;纯静态部署无该接口时沿用公开配置 顺带修掉一个既存漏洞(与本轮改动无关,是引入私有层叠加机制时埋下的): /api/monitors 无鉴权却回吐合并后的完整配置,包含私有层的 UptimeRobot API Key —— 只要配了 key,任何访客 curl /api/monitors 就能拿到。现在两侧(Node 与 Worker) 都对对外响应剥离 uptimeRobot.apiKey,保留 enabled 等非敏感字段供面板读取; 探针内部同步仍用完整配置,剥离只作用于 HTTP 出口。 测试:verify-worker 36→40 项(新增 [E] 配置接口密钥泄露 4 条)、 verify-security 20→25 项(新增 [D2] 密钥泄露 5 条)。全项目 8 套 314 项通过。
This commit is contained in:
@@ -380,6 +380,8 @@ function renderConsole(d) {
|
||||
|
||||
$('probe-scope').value = d.settings?.probeScope ?? 'all';
|
||||
$('data-filter').value = d.settings?.dataFilter ?? 'both';
|
||||
$('admin-url').value = d.settings?.adminUrl ?? '';
|
||||
$('admin-url').dataset.saved = $('admin-url').value;
|
||||
|
||||
// 维护窗口目标下拉
|
||||
const sel = $('mw-id');
|
||||
@@ -545,6 +547,18 @@ $('data-filter').addEventListener('change', async (e) => {
|
||||
else msg($('action-msg'), errText(r.data?.error, r.data?.hint), 'err');
|
||||
});
|
||||
|
||||
$('admin-url').addEventListener('change', async (e) => {
|
||||
const v = e.target.value.trim();
|
||||
const r = await api('/admin-url', { method: 'POST', body: { adminUrl: v } });
|
||||
if (r.ok) {
|
||||
msg($('action-msg'), v ? `面板页脚将显示指向 ${v} 的「管理」入口` : '已清空,面板不再显示管理入口', 'ok');
|
||||
refresh();
|
||||
} else {
|
||||
msg($('action-msg'), errText(r.data?.error, r.data?.hint), 'err');
|
||||
e.target.value = $('admin-url').dataset.saved ?? '';
|
||||
}
|
||||
});
|
||||
|
||||
$('probe-now').addEventListener('click', async () => {
|
||||
const btn = $('probe-now');
|
||||
btn.disabled = true;
|
||||
|
||||
@@ -664,6 +664,25 @@ function localStats() {
|
||||
};
|
||||
}
|
||||
|
||||
// 管理入口:地址写在 settings.adminUrl(可为内网地址、Tailscale 地址、VPS 域名等,
|
||||
// 由使用者自己决定怎么暴露)。默认不配置即不渲染,避免在公网面板上泄露管理面位置。
|
||||
function renderAdminLink() {
|
||||
const el = $('admin-link');
|
||||
if (!el) return;
|
||||
const raw = String(state.config?.settings?.adminUrl ?? '').trim();
|
||||
// 只接受 http/https,避免 javascript: 之类被当作可点击链接注入
|
||||
let url = null;
|
||||
try {
|
||||
const u = new URL(raw);
|
||||
if (u.protocol === 'http:' || u.protocol === 'https:') url = u;
|
||||
} catch { /* 不是合法绝对 URL 则视为未配置 */ }
|
||||
if (!url) { el.hidden = true; return; }
|
||||
el.href = url.href;
|
||||
el.textContent = '管理';
|
||||
el.title = `管理后台:${url.href}\n需绑定 2FA 并通过两步验证才能进入`;
|
||||
el.hidden = false;
|
||||
}
|
||||
|
||||
function renderSummary() {
|
||||
const st = state.status;
|
||||
const stats = localStats();
|
||||
@@ -727,6 +746,7 @@ function renderAll() {
|
||||
renderViewSwitch();
|
||||
renderView();
|
||||
renderEvents();
|
||||
renderAdminLink();
|
||||
}
|
||||
|
||||
function renderError(err) {
|
||||
@@ -938,6 +958,14 @@ async function init() {
|
||||
renderError(err);
|
||||
return;
|
||||
}
|
||||
// 配置以服务端合并后的版本为准(/api/monitors 含 private overlay):
|
||||
// 静态 monitors.json 是不入库的公开层,管理端写入的设置只落在私有层,
|
||||
// 不合并的话面板读不到(例如 adminUrl)。
|
||||
// 纯静态部署没有这个接口,此时沿用已读到的公开配置即可。
|
||||
try {
|
||||
const merged = await fetchJson('api/monitors', 5000);
|
||||
if (merged?.settings) state.config = { ...state.config, settings: { ...state.config.settings, ...merged.settings } };
|
||||
} catch { /* 无边缘接口(静态部署):保留公开配置 */ }
|
||||
document.title = state.config.settings?.title || 'Shiroko Monitor';
|
||||
$('site-title').textContent = state.config.settings?.title || 'Shiroko Monitor';
|
||||
$('site-desc').textContent = state.config.settings?.description || '';
|
||||
|
||||
@@ -333,6 +333,17 @@ body {
|
||||
color: var(--text-2);
|
||||
}
|
||||
.footer .version { margin-left: auto; }
|
||||
/* 管理入口:仅在配置了 settings.adminUrl 时出现;默认隐藏,避免在公网面板上暴露管理面位置 */
|
||||
.admin-link {
|
||||
padding: 1px 9px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 999px;
|
||||
color: var(--text-2);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
transition: color 0.15s, border-color 0.15s;
|
||||
}
|
||||
.admin-link:hover { color: var(--accent); border-color: var(--accent); }
|
||||
.demo-chip { padding: 1px 8px; border-radius: 999px; background: var(--pending-bg); color: var(--pending-text); font-weight: 600; }
|
||||
.warn-chip { padding: 1px 8px; border-radius: 999px; background: var(--down-bg); color: var(--down-text); font-weight: 600; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user