Interactive list
This commit is contained in:
336
PROTOCOL.md
Normal file
336
PROTOCOL.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# 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:**
|
||||
```json
|
||||
{
|
||||
"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:**
|
||||
```json
|
||||
{
|
||||
"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:**
|
||||
```json
|
||||
{
|
||||
"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:**
|
||||
```json
|
||||
{
|
||||
"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
|
||||
```c
|
||||
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
|
||||
```c
|
||||
int auth_result = authenticate_user(username, password,
|
||||
config->samba_server,
|
||||
config->samba_port,
|
||||
config->base_dn);
|
||||
```
|
||||
|
||||
### 4. Get User's Authorized Targets
|
||||
```c
|
||||
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:**
|
||||
```yaml
|
||||
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
|
||||
```c
|
||||
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
|
||||
```c
|
||||
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
|
||||
```c
|
||||
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
|
||||
```bash
|
||||
(echo -e "AUTH\nuser@example.com\nPassword123\n"; sleep 1) | nc rdpbroker 3389
|
||||
```
|
||||
|
||||
Expected response:
|
||||
```json
|
||||
{"type":"auth_success","targets":[...]}
|
||||
```
|
||||
|
||||
### Test Authentication Failure
|
||||
```bash
|
||||
(echo -e "AUTH\nuser@example.com\nWrongPassword\n"; sleep 1) | nc rdpbroker 3389
|
||||
```
|
||||
|
||||
Expected response:
|
||||
```json
|
||||
{"type":"auth_failed","message":"Invalid credentials"}
|
||||
```
|
||||
|
||||
### Test Target Selection
|
||||
```bash
|
||||
(echo -e "AUTH\nuser@example.com\nPassword123\n"; sleep 1; echo -e "SELECT\nWindows Server 2022\n"; sleep 1) | nc rdpbroker 3389
|
||||
```
|
||||
|
||||
Expected response:
|
||||
```json
|
||||
{"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
|
||||
Reference in New Issue
Block a user