Files
2025-12-05 16:33:03 +01:00
..
2025-12-05 16:33:03 +01:00
2025-12-05 16:33:03 +01:00
2025-12-03 13:16:35 +01:00
2025-12-04 09:32:45 +01:00
2025-12-03 13:16:35 +01:00
2025-12-04 11:08:55 +01:00
2025-12-04 11:08:55 +01:00
2025-12-05 14:54:08 +01:00
2025-12-04 09:32:45 +01:00
2025-12-03 13:16:35 +01:00
2025-12-05 16:33:03 +01:00
2025-12-04 11:08:55 +01:00
2025-12-05 14:54:08 +01:00

RDP Web Gateway

HTML5 WebSocket-based gateway for accessing RDP connections through a web browser. This service sits in front of RdpBroker and provides a modern web interface for remote desktop access.

Features

  • 🌐 Browser-Based Access - Connect to RDP sessions from any modern web browser
  • 🔒 Secure WebSocket - Real-time bidirectional communication
  • 🎨 Modern UI - Clean, responsive interface
  • 🔑 User-Specific Targets - Each user sees only their authorized RDP servers
  • 📊 Service Health Monitoring - Automatic RdpBroker availability checks
  • 🎯 Dynamic Target Loading - Personalized targets from RdpBroker based on user permissions
  • Low Latency - Optimized for performance
  • ☁️ Kubernetes Native - Console-only logging for cloud environments
  • 🔐 Samba AD Integration - Authentication via RdpBroker with Samba Active Directory

Architecture

User Browser (HTML5/WebSocket)
          ↓
    RDP Web Gateway (Node.js)
          ↓  [WebSocket Protocol]
          ↓  1. AUTH → receives user-specific targets
          ↓  2. SELECT → connects to chosen target
          ↓
      RdpBroker (C)
          ↓  [Samba AD Auth]
          ↓  [Target Authorization]
          ↓  [RDP Forwarding]
          ↓
    Target RDP Servers

Authentication Flow

  1. User Login - User enters credentials in web interface
  2. Health Check - Web-gateway verifies RdpBroker is available
  3. WebSocket Auth - Credentials sent via WebSocket to RdpBroker
  4. LDAP Authentication - RdpBroker authenticates against Samba AD
  5. Target Authorization - RdpBroker determines user's authorized targets based on groups/permissions
  6. Targets Display - User-specific target list sent back to web-gateway
  7. Target Selection - User chooses from their authorized servers
  8. RDP Session - RdpBroker establishes connection to selected target

Prerequisites

  • Node.js 18+
  • RdpBroker service running
  • Modern web browser with WebSocket support

Installation

Local Development

cd web-gateway

# Install dependencies
npm install

# Copy environment file
cp .env.example .env

# Edit configuration
nano .env

# Start development server
npm run dev

Docker Build

docker build -t rdp-web-gateway:latest .

Configuration

Edit .env file:

PORT=8080
RDP_BROKER_HOST=rdpbroker
RDP_BROKER_PORT=3389
NODE_ENV=production

# Optional: Pre-configure RDP targets (JSON array)
# If not set, RdpBroker will provide targets dynamically
RDP_TARGETS=[{"name":"Server1","host":"srv1.example.com","port":3389,"description":"Production Server"}]

Environment Variables

Variable Description Default
PORT Web server listening port 8080
RDP_BROKER_HOST RdpBroker hostname rdpbroker
RDP_BROKER_PORT RdpBroker port 3389
RDP_TARGETS JSON array of pre-configured targets null
NODE_ENV Environment mode development

Usage

Access the Web Interface

  1. Open your browser to http://localhost:8080
  2. Enter your credentials (validated against Samba AD via RdpBroker)
  3. Select a target from the list
  4. Connect and use the remote desktop

API Endpoints

GET /health

Health check endpoint for monitoring the web gateway.

Response:

{
  "status": "healthy",
  "version": "1.0.0",
  "uptime": 12345
}

GET /api/broker-status

Check if RdpBroker service is available.

Response:

{
  "available": true,
  "broker": "rdpbroker:3389",
  "timestamp": "2025-12-04T10:30:00.000Z"
}

GET /api/targets

Fetch available RDP targets.

Success Response (200):

{
  "targets": [
    {
      "name": "Windows Server 2022",
      "host": "ws2022.example.com",
      "port": 3389,
      "description": "Production Windows Server"
    }
  ],
  "timestamp": "2025-12-04T10:30:00.000Z"
}

Service Unavailable (503):

{
  "error": "RdpBroker service is unavailable. Please contact your administrator.",
  "timestamp": "2025-12-04T10:30:00.000Z"
}

WebSocket Protocol

Connect to ws://localhost:8080/ws/rdp

The protocol follows a two-phase approach:

  1. Authentication Phase: User authenticates and receives personalized target list
  2. Connection Phase: User selects target and establishes RDP session

Phase 1: Authentication

Client → Server - Authenticate:

{
  "type": "authenticate",
  "username": "user@domain.com",
  "password": "password123"
}

Server → Client - Authentication Success with Targets:

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

Server → Client - Authentication Failed:

{
  "type": "error",
  "error": "Invalid credentials"
}

Phase 2: Connection

Client → Server - Connect to Target:

{
  "type": "connect",
  "target": {
    "name": "Windows Server 2022",
    "host": "ws2022.example.com",
    "port": 3389
  }
}

Server → Client - RDP Session Ready:

{
  "type": "connected",
  "target": "Windows Server 2022"
}

Client → Server Messages

Mouse event:

{
  "type": "mouse",
  "action": "move|down|up|wheel",
  "x": 100,
  "y": 200,
  "button": 0,
  "deltaY": 0
}

Keyboard event:

{
  "type": "keyboard",
  "action": "down|up",
  "key": "a",
  "code": "KeyA",
  "ctrlKey": false,
  "altKey": false,
  "shiftKey": false
}

Special command:

{
  "type": "special",
  "action": "ctrl-alt-del"
}

Server → Client Messages

Connected:

{
  "type": "connected",
  "target": "Server 01"
}

Resize canvas:

{
  "type": "resize",
  "width": 1920,
  "height": 1080
}

Error:

{
  "type": "error",
  "error": "Error message"
}

Deployment

Kubernetes with Helm

Option 1: LoadBalancer (Default)

# Deploy with LoadBalancer service
helm install rdp-web-gateway ./chart/rdp-web-gateway \
  --namespace rdpbroker \
  --create-namespace \
  --set service.type=LoadBalancer

Option 2: Traefik IngressRoute with Let's Encrypt

Recommended for production with automatic HTTPS

  1. Apply Traefik middlewares (one time):
kubectl apply -f chart/rdp-web-gateway/examples/traefik-middlewares.yaml -n rdpbroker
  1. Deploy with Traefik IngressRoute:
# Edit the host in examples/traefik-letsencrypt.yaml
# Then deploy:
helm install rdp-web-gateway ./chart/rdp-web-gateway \
  --namespace rdpbroker \
  --create-namespace \
  -f chart/rdp-web-gateway/examples/traefik-letsencrypt.yaml

Or directly with values:

helm install rdp-web-gateway ./chart/rdp-web-gateway \
  --namespace rdpbroker \
  --create-namespace \
  --set service.type=ClusterIP \
  --set traefik.enabled=true \
  --set traefik.host=rdp.yourdomain.com \
  --set traefik.tls.enabled=true \
  --set traefik.tls.certResolver=letsencrypt
  1. Verify deployment:
# Check IngressRoute
kubectl get ingressroute -n rdpbroker

# Check certificate (after a few seconds)
kubectl get certificate -n rdpbroker

# Access your gateway
https://rdp.yourdomain.com

Option 3: Standard Ingress (nginx, etc.)

helm install rdp-web-gateway ./chart/rdp-web-gateway \
  --namespace rdpbroker \
  --create-namespace \
  --set service.type=ClusterIP \
  --set ingress.enabled=true \
  --set ingress.className=nginx \
  --set ingress.hosts[0].host=rdp.example.com \
  --set ingress.hosts[0].paths[0].path=/ \
  --set ingress.hosts[0].paths[0].pathType=Prefix

Important Notes for Traefik

WebSocket Support: Traefik automatically handles WebSocket upgrades, no special configuration needed!

Let's Encrypt Certificate Resolver: Ensure your Traefik has a certResolver named letsencrypt configured. Example:

# Traefik values.yaml or static config
certificatesResolvers:
  letsencrypt:
    acme:
      email: admin@yourdomain.com
      storage: /data/acme.json
      httpChallenge:
        entryPoint: web

Middlewares: Apply the recommended middlewares for security:

  • redirect-to-https - Force HTTPS
  • security-headers - Security headers including WebSocket support
  • rate-limit - Prevent abuse
  • compression - Reduce bandwidth

Browser Support

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+
  • Opera 76+

Security Considerations

  • Use HTTPS/WSS in production
  • Credentials are passed directly to RdpBroker (no storage in web-gateway)
  • Implement rate limiting at ingress level
  • Enable CORS restrictions
  • Regular security audits
  • All authentication handled by RdpBroker → Samba ADs
  • Regular security audits

Performance Tuning

  • Configure WebSocket buffer sizes
  • Use CDN for static assets in production
  • Enable HTTP compression (already included)
  • Adjust resource limits in Kubernetes
  • Use CDN for static assets in production

Troubleshooting

Can't connect to RdpBroker

Check environment variables:

echo $RDP_BROKER_HOST
echo $RDP_BROKER_PORT

Test connectivity:

nc -zv rdpbroker 3389

WebSocket connection fails

Ensure WebSocket upgrade is allowed through proxies/load balancers.

For Traefik: Already handled automatically!

For nginx:

location /ws/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

For Traefik middlewares: Ensure security-headers middleware includes:

customResponseHeaders:
  Connection: "upgrade"
  Upgrade: "$http_upgrade"

High memory usage

Adjust resource limits in Kubernetes values.yaml

Logging

All logs go to stdout/stderr for Kubernetes:

# View logs
kubectl logs -f deployment/rdp-web-gateway -n rdpbroker

# Follow logs for all pods
kubectl logs -f -l app=rdp-web-gateway -n rdpbroker

Reduce session timeout or implement session limits per user.

Development

Running Tests

npm test

Code Style

npm run lint

License

MIT License - see LICENSE file

Support

For issues and questions, check the logs:

# View logs
kubectl logs -f deployment/rdp-web-gateway -n rdpbroker

# Check health
curl http://localhost:8080/health