v2.5.0: show routed services behind port 443

This commit is contained in:
Виталий Литвинов
2026-04-25 13:25:32 +03:00
parent 5225811b3c
commit 7eaeef8b49
3 changed files with 106 additions and 13 deletions

View File

@@ -136,14 +136,19 @@ const i18n = {
languageSaved: "Language saved",
keyEnabled: "Key enabled",
keyDisabled: "Key disabled",
visualTitle: "Port 443 listeners",
visualText: "Actual TCP/UDP listeners on public port 443: telemt, website, Xray/3x-ui, AmneziaWG or another service.",
visualTitle: "Port 443 map",
visualText: "Shows the public 443 listener and services routed behind it, including the website on local nginx.",
port443Checked: "checked",
port443NoListeners: "No 443 listeners found",
port443Listeners: "listeners",
port443Routes: "routed",
port443Error: "Port check failed",
port443Public: "public",
port443Configured: "telemt: {port}",
port443PublicSection: "Public 443",
port443BehindSection: "Behind 443",
port443NoRoutes: "No routed services detected",
port443Via: "via {value}",
roleMtproxy: "MTProxy",
roleSite: "Website",
roleXray: "Xray / 3x-ui",
@@ -318,14 +323,19 @@ const i18n = {
languageSaved: "Язык сохранён",
keyEnabled: "Ключ включён",
keyDisabled: "Ключ отключён",
visualTitle: "Кто слушает порт 443",
visualText: "Реальные TCP/UDP-процессы на публичном 443: telemt, сайт, Xray/3x-ui, AmneziaWG или другой сервис.",
visualTitle: "Карта порта 443",
visualText: "Показывает публичного слушателя 443 и сервисы, которые живут за ним, включая сайт на локальном nginx.",
port443Checked: "проверено",
port443NoListeners: "Слушателей 443 не найдено",
port443Listeners: "слушателей",
port443Routes: "за 443",
port443Error: "Проверка порта не удалась",
port443Public: "публичный",
port443Configured: "telemt: {port}",
port443PublicSection: "Публичный 443",
port443BehindSection: "За портом 443",
port443NoRoutes: "Маршрутизируемых сервисов не найдено",
port443Via: "через {value}",
roleMtproxy: "MTProxy",
roleSite: "Сайт",
roleXray: "Xray / 3x-ui",
@@ -637,6 +647,7 @@ function roleLabel(role) {
function renderPort443(payload = {}) {
const listeners = Array.isArray(payload.listeners) ? payload.listeners : [];
const routes = Array.isArray(payload.routes) ? payload.routes : [];
const summary = $("#port443Summary");
const list = $("#port443List");
const configuredPort = Number(payload.configured_port) || 443;
@@ -649,14 +660,10 @@ function renderPort443(payload = {}) {
summary.textContent = t("port443NoListeners");
summary.className = "port-status warn";
} else {
summary.textContent = `${listeners.length} ${t("port443Listeners")}`;
summary.textContent = `${listeners.length} ${t("port443Listeners")}${routes.length ? ` · ${routes.length} ${t("port443Routes")}` : ""}`;
summary.className = "port-status ok";
}
if (!listeners.length) {
list.innerHTML = `<div class="port-empty">${escapeHtml(payload.error || t("port443NoListeners"))}</div>`;
return;
}
list.innerHTML = listeners.map((item) => {
const listenerHtml = listeners.length ? listeners.map((item) => {
const title = `${item.proto || ""} ${item.address || ""} · ${item.process || "unknown"}${item.pid ? ` · pid ${item.pid}` : ""}`;
return `<article class="port-listener role-${escapeAttr(item.role || "other")}" title="${escapeAttr(title)}">
<div>
@@ -665,7 +672,24 @@ function renderPort443(payload = {}) {
</div>
<small>${escapeHtml(item.proto || "--")} · ${escapeHtml(item.address || "--")}</small>
</article>`;
}).join("");
}).join("") : `<div class="port-empty">${escapeHtml(payload.error || t("port443NoListeners"))}</div>`;
const routeHtml = routes.length ? routes.map((item) => {
const via = item.via ? t("port443Via").replace("{value}", item.via) : "";
const title = `${item.public || ""}${item.target || ""} · ${item.process || ""}`;
return `<article class="port-listener role-${escapeAttr(item.role || "other")}" title="${escapeAttr(title)}">
<div>
<strong>${escapeHtml(roleLabel(item.role))}</strong>
<span>${escapeHtml(item.process || "unknown")}${item.status ? ` · ${escapeHtml(statusLabel(item.status))}` : ""}</span>
</div>
<small>${escapeHtml(item.public || "--")}${escapeHtml(item.target || "--")}${via ? ` · ${escapeHtml(via)}` : ""}</small>
</article>`;
}).join("") : `<div class="port-empty">${escapeHtml(t("port443NoRoutes"))}</div>`;
list.innerHTML = `
<div class="port-section-label">${escapeHtml(t("port443PublicSection"))}</div>
${listenerHtml}
<div class="port-section-label">${escapeHtml(t("port443BehindSection"))}</div>
${routeHtml}
`;
}
function renderOverview() {

View File

@@ -400,6 +400,14 @@ h2 {
gap: 8px;
}
.port-section-label {
margin-top: 2px;
color: var(--muted);
font-size: 11px;
font-weight: 900;
text-transform: uppercase;
}
.port-listener,
.port-empty {
display: grid;