Fix RDP WebSocket auth and tunnel UUID protocol
- RdpTab: remove token from base URL; pass via client.connect(data) because WebSocketTunnel always appends "?"+data to the URL, corrupting a pre-built ?token=JWT into ?token=JWT?<data> - rdp.ts: send UUID as Guacamole internal instruction "0.,36.<uuid>;" (opcode="" = INTERNAL_DATA_OPCODE) instead of a plain string, matching the WebSocketTunnel 1.5.0+ protocol expectation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -166,10 +166,11 @@ export async function rdpWebsocket(fastify: FastifyInstance) {
|
||||
throw new Error(`guacd handshake failed: expected 'ready', got '${readyInstruction[0]}'`);
|
||||
}
|
||||
|
||||
// 5. Send the guacd connection UUID as the first WebSocket message.
|
||||
// Guacamole.WebSocketTunnel expects this as its tunnel-UUID handshake.
|
||||
// 5. Send the tunnel UUID as a Guacamole internal instruction.
|
||||
// WebSocketTunnel (1.5.0+) expects opcode "" (empty string) with the
|
||||
// UUID as the single argument: "0.,36.<uuid>;"
|
||||
const guacdUUID = readyInstruction[1] ?? randomUUID();
|
||||
socket.send(guacdUUID);
|
||||
socket.send(buildInstruction('', guacdUUID));
|
||||
|
||||
// 6. Flush any buffered bytes that arrived after 'ready'
|
||||
if (tcpBuf.value.length > 0 && socket.readyState === WebSocket.OPEN) {
|
||||
|
||||
@@ -10,10 +10,12 @@ interface Props {
|
||||
|
||||
type Status = 'connecting' | 'connected' | 'disconnected' | 'error';
|
||||
|
||||
function getWsUrl(connectionId: string, token: string): string {
|
||||
// NOTE: Do NOT include query params here. Guacamole.WebSocketTunnel always
|
||||
// appends "?" + connectData to the URL, so auth params must go via connect().
|
||||
function getWsUrl(connectionId: string): string {
|
||||
const proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const host = window.location.host;
|
||||
return `${proto}//${host}/ws/rdp/${connectionId}?token=${encodeURIComponent(token)}`;
|
||||
return `${proto}//${host}/ws/rdp/${connectionId}`;
|
||||
}
|
||||
|
||||
export const RdpTab: React.FC<Props> = ({ session }) => {
|
||||
@@ -29,7 +31,7 @@ export const RdpTab: React.FC<Props> = ({ session }) => {
|
||||
setStatus('connecting');
|
||||
setErrorMsg('');
|
||||
|
||||
const url = getWsUrl(session.connection.id, token);
|
||||
const url = getWsUrl(session.connection.id);
|
||||
const tunnel = new Guacamole.WebSocketTunnel(url);
|
||||
const client = new Guacamole.Client(tunnel);
|
||||
|
||||
@@ -80,8 +82,9 @@ export const RdpTab: React.FC<Props> = ({ session }) => {
|
||||
setErrorMsg(`Client error: ${error.message ?? 'unknown'}`);
|
||||
};
|
||||
|
||||
// Connect
|
||||
client.connect();
|
||||
// Connect — pass token as query param via connect(data).
|
||||
// WebSocketTunnel appends "?" + data to the base URL, so auth goes here.
|
||||
client.connect(`token=${encodeURIComponent(token)}`);
|
||||
|
||||
return () => {
|
||||
keyboard.onkeydown = null;
|
||||
|
||||
Reference in New Issue
Block a user