mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-12-15 23:25:48 -07:00
Additional Fixes for Reverse Shell UI
This commit is contained in:
@@ -179,5 +179,8 @@ class PowershellChannel:
|
|||||||
pass
|
pass
|
||||||
# Include exit code in the close reason for debugging.
|
# Include exit code in the close reason for debugging.
|
||||||
exit_suffix = f" (exit={self._exit_code})" if self._exit_code is not None else ""
|
exit_suffix = f" (exit={self._exit_code})" if self._exit_code is not None else ""
|
||||||
await self._send_close(code, (reason or "powershell_exit") + exit_suffix)
|
close_reason = (reason or "powershell_exit") + exit_suffix
|
||||||
self.role._log(f"reverse_tunnel ps channel stopped channel={self.channel_id} reason={reason or 'exit'}")
|
await self._send_close(code, close_reason)
|
||||||
|
self.role._log(
|
||||||
|
f"reverse_tunnel ps channel stopped channel={self.channel_id} reason={close_reason}"
|
||||||
|
)
|
||||||
|
|||||||
@@ -521,6 +521,14 @@ class Role:
|
|||||||
self._log(f"reverse_tunnel connection failed tunnel_id={tunnel.tunnel_id}: {exc}", error=True)
|
self._log(f"reverse_tunnel connection failed tunnel_id={tunnel.tunnel_id}: {exc}", error=True)
|
||||||
await self._emit_status({"tunnel_id": tunnel.tunnel_id, "agent_id": self.ctx.agent_id, "status": "error", "reason": "connect_failed"})
|
await self._emit_status({"tunnel_id": tunnel.tunnel_id, "agent_id": self.ctx.agent_id, "status": "error", "reason": "connect_failed"})
|
||||||
finally:
|
finally:
|
||||||
|
try:
|
||||||
|
ws = tunnel.websocket
|
||||||
|
self._log(
|
||||||
|
f"reverse_tunnel ws closing tunnel_id={tunnel.tunnel_id} "
|
||||||
|
f"code={getattr(ws, 'close_code', None)} reason={getattr(ws, 'close_reason', None)}"
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
await self._shutdown_tunnel(tunnel)
|
await self._shutdown_tunnel(tunnel)
|
||||||
|
|
||||||
async def _pump_sender(self, tunnel: ActiveTunnel) -> None:
|
async def _pump_sender(self, tunnel: ActiveTunnel) -> None:
|
||||||
@@ -562,6 +570,7 @@ class Role:
|
|||||||
f"reverse_tunnel websocket closed tunnel_id={tunnel.tunnel_id} "
|
f"reverse_tunnel websocket closed tunnel_id={tunnel.tunnel_id} "
|
||||||
f"code={ws.close_code} reason={ws.close_reason}"
|
f"code={ws.close_code} reason={ws.close_reason}"
|
||||||
)
|
)
|
||||||
|
tunnel.stop_reason = ws.close_reason or "ws_closed"
|
||||||
break
|
break
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -241,8 +241,13 @@ export default function ReverseTunnelPowershell({ device }) {
|
|||||||
setPolling(true);
|
setPolling(true);
|
||||||
pollTimerRef.current = setTimeout(async () => {
|
pollTimerRef.current = setTimeout(async () => {
|
||||||
const resp = await emitAsync(socket, "ps_poll", {});
|
const resp = await emitAsync(socket, "ps_poll", {});
|
||||||
if (resp?.error) {
|
if (resp?.error) {
|
||||||
// Suppress warming/errors in UI; rely on session chips.
|
stopPolling();
|
||||||
|
disconnectSocket();
|
||||||
|
setPsStatus({});
|
||||||
|
setTunnel(null);
|
||||||
|
setSessionState("error");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (Array.isArray(resp?.output) && resp.output.length) {
|
if (Array.isArray(resp?.output) && resp.output.length) {
|
||||||
appendOutput(resp.output.join(""));
|
appendOutput(resp.output.join(""));
|
||||||
@@ -251,8 +256,7 @@ export default function ReverseTunnelPowershell({ device }) {
|
|||||||
setPsStatus(resp.status);
|
setPsStatus(resp.status);
|
||||||
if (resp.status.closed) {
|
if (resp.status.closed) {
|
||||||
setSessionState("closed");
|
setSessionState("closed");
|
||||||
setStatusSeverity("warning");
|
setTunnel(null);
|
||||||
setStatusMessage(resp.status.close_reason || "Session closed");
|
|
||||||
stopPolling();
|
stopPolling();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -263,7 +267,7 @@ export default function ReverseTunnelPowershell({ device }) {
|
|||||||
pollLoop(socket, tunnelId);
|
pollLoop(socket, tunnelId);
|
||||||
}, 520);
|
}, 520);
|
||||||
},
|
},
|
||||||
[appendOutput, emitAsync, stopPolling]
|
[appendOutput, emitAsync, stopPolling, disconnectSocket]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDisconnect = useCallback(() => {
|
const handleDisconnect = useCallback(() => {
|
||||||
@@ -280,9 +284,8 @@ export default function ReverseTunnelPowershell({ device }) {
|
|||||||
}
|
}
|
||||||
stopPolling();
|
stopPolling();
|
||||||
disconnectSocket();
|
disconnectSocket();
|
||||||
|
setTunnel(null);
|
||||||
setSessionState("closed");
|
setSessionState("closed");
|
||||||
setStatusSeverity("info");
|
|
||||||
setStatusMessage("Session closed by operator.");
|
|
||||||
}, [disconnectSocket, stopPolling, tunnel?.tunnel_id]);
|
}, [disconnectSocket, stopPolling, tunnel?.tunnel_id]);
|
||||||
|
|
||||||
const handleResize = useCallback(() => {
|
const handleResize = useCallback(() => {
|
||||||
@@ -328,6 +331,8 @@ export default function ReverseTunnelPowershell({ device }) {
|
|||||||
socket.on("connect_error", () => {
|
socket.on("connect_error", () => {
|
||||||
setStatusSeverity("warning");
|
setStatusSeverity("warning");
|
||||||
setStatusMessage("Tunnel namespace unavailable.");
|
setStatusMessage("Tunnel namespace unavailable.");
|
||||||
|
setTunnel(null);
|
||||||
|
setSessionState("error");
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("disconnect", () => {
|
socket.on("disconnect", () => {
|
||||||
@@ -336,6 +341,7 @@ export default function ReverseTunnelPowershell({ device }) {
|
|||||||
setSessionState("disconnected");
|
setSessionState("disconnected");
|
||||||
setStatusSeverity("warning");
|
setStatusSeverity("warning");
|
||||||
setStatusMessage("Socket disconnected.");
|
setStatusMessage("Socket disconnected.");
|
||||||
|
setTunnel(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user