Files
Maison/RdpBroker/PROTOCOL.md
2026-02-10 12:12:11 +01:00

8.6 KiB

RdpBroker Protocol Specification

Overview

This document describes the protocol between web-gateway and RdpBroker for user authentication and target management.

Connection Flow

Web-Gateway                    RdpBroker                    Samba AD / Target RDP Servers
    |                              |                              |
    |--AUTH\n{user}\n{pass}\n----->|                              |
    |                              |---LDAP Auth----------------->|
    |                              |<----Auth Result--------------|
    |                              |                              |
    |<---{type:targets,targets:[]}|                              |
    |  OR                          |                              |
    |<---{type:auth_failed}--------|                              |
    |                              |                              |
    |--SELECT\n{target_name}\n---->|                              |
    |                              |---Connect to Target--------->|
    |<---{type:rdp_ready}----------|<-----------------------------|
    |                              |                              |
    |<====== RDP Binary Data ======|<===== RDP Session ==========|

Protocol Messages

Phase 1: Authentication

Request Format (Web-Gateway → RdpBroker)

AUTH\n
username\n
password\n

Example:

AUTH
user@example.com
SecurePassword123

Success Response (RdpBroker → Web-Gateway)

JSON Format:

{
  "type": "auth_success",
  "targets": [
    {
      "name": "Windows Server 2022",
      "host": "ws2022.example.com",
      "port": 3389,
      "description": "Production Windows Server"
    },
    {
      "name": "Development Server",
      "host": "dev.example.com",
      "port": 3389,
      "description": "Development environment"
    }
  ]
}

Notes:

  • The message must end with \n\n (double newline) to signal end of JSON message
  • Targets list is personalized based on user permissions/groups in Samba AD
  • Empty array means user is authenticated but has no authorized targets

Failure Response (RdpBroker → Web-Gateway)

JSON Format:

{
  "type": "auth_failed",
  "message": "Invalid credentials"
}

Followed by connection close.

Possible error messages:

  • "Invalid credentials"
  • "User account disabled"
  • "LDAP connection failed"
  • "User not authorized for any targets"

Phase 2: Target Selection

Request Format (Web-Gateway → RdpBroker)

SELECT\n
target_name\n

Example:

SELECT
Windows Server 2022

Notes:

  • Target name must match exactly one of the names from the targets list
  • Connection should be rejected if target name is invalid or not in user's authorized list

Success Response (RdpBroker → Web-Gateway)

JSON Format:

{
  "type": "rdp_ready"
}

Followed by \n\n, then RDP binary data stream begins.

After this message, the connection transitions to raw RDP protocol forwarding mode.

Failure Response (RdpBroker → Web-Gateway)

JSON Format:

{
  "type": "error",
  "message": "Target not available"
}

Followed by connection close.

Possible error messages:

  • "Target not found"
  • "Target not authorized for user"
  • "Failed to connect to target server"
  • "Target server unreachable"

Phase 3: RDP Session

After rdp_ready message, all subsequent data is raw RDP protocol:

  • Web-Gateway forwards mouse/keyboard events as RDP protocol data
  • RdpBroker forwards screen updates as RDP protocol data
  • Connection is bidirectional binary stream

Implementation Guidelines for RdpBroker

1. Accept Connection

Listen on port 3389 (configurable via RDP_LISTEN_PORT)

2. Read Authentication Message

char buffer[4096];
int bytes = read(client_fd, buffer, sizeof(buffer));

// Parse "AUTH\n{username}\n{password}\n"
char *lines[3];
int line_count = 0;
char *token = strtok(buffer, "\n");
while (token != NULL && line_count < 3) {
    lines[line_count++] = token;
    token = strtok(NULL, "\n");
}

if (strcmp(lines[0], "AUTH") != 0) {
    send_error(client_fd, "Invalid protocol");
    close(client_fd);
    return;
}

char *username = lines[1];
char *password = lines[2];

3. Authenticate with Samba AD

int auth_result = authenticate_user(username, password, 
                                   config->samba_server,
                                   config->samba_port,
                                   config->base_dn);

4. Get User's Authorized Targets

rdp_target_t *user_targets[MAX_TARGETS];
int target_count = get_user_targets(username, config, user_targets);

Recommended approach:

  • Query user's groups from LDAP
  • Filter targets based on group membership or user attributes
  • Return only targets the user is authorized to access

Example YAML configuration:

targets:
  - name: "Windows Server 2022"
    host: "ws2022.example.com"
    port: 3389
    description: "Production Windows Server"
    authorized_groups:
      - "Domain Admins"
      - "Server Operators"
  
  - name: "Development Server"
    host: "dev.example.com"
    port: 3389
    description: "Development environment"
    authorized_groups:
      - "Developers"
      - "Domain Admins"

5. Send Targets List

char json_response[8192];
snprintf(json_response, sizeof(json_response),
    "{\"type\":\"auth_success\",\"targets\":[");

for (int i = 0; i < target_count; i++) {
    char target_json[512];
    snprintf(target_json, sizeof(target_json),
        "%s{\"name\":\"%s\",\"host\":\"%s\",\"port\":%d,\"description\":\"%s\"}",
        (i > 0 ? "," : ""),
        user_targets[i]->name,
        user_targets[i]->host,
        user_targets[i]->port,
        user_targets[i]->description);
    strcat(json_response, target_json);
}

strcat(json_response, "]}\n\n");
write(client_fd, json_response, strlen(json_response));

6. Read Target Selection

bytes = read(client_fd, buffer, sizeof(buffer));

// Parse "SELECT\n{target_name}\n"
if (strncmp(buffer, "SELECT\n", 7) != 0) {
    send_error(client_fd, "Invalid protocol");
    close(client_fd);
    return;
}

char *target_name = buffer + 7;
char *newline = strchr(target_name, '\n');
if (newline) *newline = '\0';

// Verify target is in user's authorized list
rdp_target_t *selected_target = find_target_in_list(target_name, 
                                                     user_targets, 
                                                     target_count);
if (!selected_target) {
    send_error(client_fd, "Target not authorized");
    close(client_fd);
    return;
}

7. Connect to Target and Start Forwarding

int target_fd = connect_to_rdp_target(selected_target->host, 
                                      selected_target->port);

// Send ready message
char *ready_msg = "{\"type\":\"rdp_ready\"}\n\n";
write(client_fd, ready_msg, strlen(ready_msg));

// Start bidirectional forwarding
forward_rdp_connection(client_fd, target_fd);

Security Considerations

  1. Always validate target selection - User must be authorized for selected target
  2. Close on protocol errors - Invalid messages should immediately close connection
  3. Timeout authentication - Implement timeout for AUTH phase (e.g., 30 seconds)
  4. Rate limiting - Prevent brute force attacks on authentication
  5. Logging - Log all authentication attempts and target selections
  6. TLS/SSL - Consider wrapping connection in TLS for production

Testing

Test Authentication Success

(echo -e "AUTH\nuser@example.com\nPassword123\n"; sleep 1) | nc rdpbroker 3389

Expected response:

{"type":"auth_success","targets":[...]}

Test Authentication Failure

(echo -e "AUTH\nuser@example.com\nWrongPassword\n"; sleep 1) | nc rdpbroker 3389

Expected response:

{"type":"auth_failed","message":"Invalid credentials"}

Test Target Selection

(echo -e "AUTH\nuser@example.com\nPassword123\n"; sleep 1; echo -e "SELECT\nWindows Server 2022\n"; sleep 1) | nc rdpbroker 3389

Expected response:

{"type":"auth_success","targets":[...]}

{"type":"rdp_ready"}

[RDP binary data follows]

Migration Notes

Existing RdpBroker implementations that present login/menu screens via RDP protocol will need to be refactored to:

  1. Accept the new text-based protocol on initial connection
  2. Parse AUTH and SELECT commands
  3. Return JSON responses instead of RDP login screens
  4. Only start RDP forwarding after receiving SELECT command

The advantage is that authentication and target selection now happen via structured protocol before RDP session starts, allowing:

  • Better error handling in web UI
  • User-specific target lists
  • Cleaner separation of concerns
  • Easier debugging and monitoring