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
- User Login - User enters credentials in web interface
- Health Check - Web-gateway verifies RdpBroker is available
- WebSocket Auth - Credentials sent via WebSocket to RdpBroker
- LDAP Authentication - RdpBroker authenticates against Samba AD
- Target Authorization - RdpBroker determines user's authorized targets based on groups/permissions
- Targets Display - User-specific target list sent back to web-gateway
- Target Selection - User chooses from their authorized servers
- 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
- Open your browser to
http://localhost:8080 - Enter your credentials (validated against Samba AD via RdpBroker)
- Select a target from the list
- 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:
- Authentication Phase: User authenticates and receives personalized target list
- 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
- Apply Traefik middlewares (one time):
kubectl apply -f chart/rdp-web-gateway/examples/traefik-middlewares.yaml -n rdpbroker
- 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
- 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 HTTPSsecurity-headers- Security headers including WebSocket supportrate-limit- Prevent abusecompression- 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