mirror of
https://github.com/bolkedebruin/rdpgw.git
synced 2026-03-27 14:36:36 +00:00
Extra docs
This commit is contained in:
269
docs/ms-app-proxy-deployment.md
Normal file
269
docs/ms-app-proxy-deployment.md
Normal file
@@ -0,0 +1,269 @@
|
||||
# Microsoft Azure Application Proxy Deployment Guide
|
||||
|
||||
This guide provides step-by-step instructions for deploying RDPGW behind Microsoft Azure Application Proxy with Conditional Access Policy enforcement.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
Internet → Azure AD (Auth + CAP) → App Proxy → RDPGW (Internal) → RDP Hosts
|
||||
```
|
||||
|
||||
**Authentication Flow:**
|
||||
- **Web requests** (`/connect`): Full Azure AD authentication with headers
|
||||
- **RDP protocol** (`/remoteDesktopGateway/`): Passthrough with token validation
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Azure AD Premium P1/P2 (for Conditional Access)
|
||||
- Azure AD Application Proxy connector installed
|
||||
- RDPGW deployed internally
|
||||
- Network connectivity from connector to RDPGW
|
||||
|
||||
## Step 1: Azure AD App Registration
|
||||
|
||||
```powershell
|
||||
# Create app registration
|
||||
$app = New-AzADApplication -DisplayName "RDPGW-AppProxy" `
|
||||
-HomePage "https://rdpgw.yourdomain.com" `
|
||||
-IdentifierUris "https://rdpgw.yourdomain.com"
|
||||
|
||||
# Note the Application ID
|
||||
Write-Host "Application ID: $($app.ApplicationId)"
|
||||
```
|
||||
|
||||
## Step 2: Configure Application Proxy
|
||||
|
||||
### Portal Configuration
|
||||
|
||||
1. **Navigate to**: Azure AD → Enterprise Applications → New Application
|
||||
2. **Select**: On-premises application
|
||||
3. **Configure**:
|
||||
- **Name**: RDPGW
|
||||
- **Internal URL**: `http://rdpgw-server:80`
|
||||
- **External URL**: `https://rdpgw.yourdomain.com`
|
||||
- **Pre-authentication**: Azure Active Directory
|
||||
- **Connector Group**: Select appropriate connector
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"application": {
|
||||
"name": "RDPGW",
|
||||
"internalUrl": "http://rdpgw-server",
|
||||
"externalUrl": "https://rdpgw.yourdomain.com",
|
||||
"preAuthentication": "aadPreAuthentication",
|
||||
"externalAuthenticationType": "aadPreAuthentication",
|
||||
"applicationProxyUrlSettings": {
|
||||
"externalUrl": "https://rdpgw.yourdomain.com",
|
||||
"internalUrl": "http://rdpgw-server",
|
||||
"isTranslateHostHeaderEnabled": true,
|
||||
"isTranslateLinksInBodyEnabled": false,
|
||||
"isOnPremPublishingEnabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Step 3: Configure Passthrough for RDP Endpoint
|
||||
|
||||
**Critical**: Configure App Proxy to bypass authentication for RDP connections:
|
||||
|
||||
### PowerShell Configuration
|
||||
|
||||
```powershell
|
||||
# Get the application
|
||||
$app = Get-AzADApplication -DisplayName "RDPGW-AppProxy"
|
||||
|
||||
# Configure passthrough paths (if available via API)
|
||||
# Note: This may need to be configured via Support ticket
|
||||
$passthroughPaths = @("/remoteDesktopGateway/*")
|
||||
```
|
||||
|
||||
### Support Request
|
||||
|
||||
If passthrough configuration isn't available in portal:
|
||||
|
||||
1. **Open Azure Support Ticket**
|
||||
2. **Request**: Passthrough configuration for `/remoteDesktopGateway/*` path
|
||||
3. **Provide**: Application ID and external URL
|
||||
4. **Reason**: RDP client compatibility requirements
|
||||
|
||||
## Step 4: RDPGW Configuration
|
||||
|
||||
### Complete Configuration File
|
||||
|
||||
```yaml
|
||||
# rdpgw.yaml
|
||||
Server:
|
||||
Authentication:
|
||||
- header
|
||||
Tls: disable
|
||||
GatewayAddress: https://rdpgw.yourdomain.com
|
||||
Port: 80
|
||||
Hosts:
|
||||
- server1.internal.domain:3389
|
||||
- server2.internal.domain:3389
|
||||
- "{{ preferred_username }}-desktop:3389" # Dynamic host mapping
|
||||
|
||||
Header:
|
||||
UserHeader: "X-MS-CLIENT-PRINCIPAL-NAME"
|
||||
UserIdHeader: "X-MS-CLIENT-PRINCIPAL-ID"
|
||||
EmailHeader: "X-MS-CLIENT-PRINCIPAL-EMAIL"
|
||||
|
||||
Security:
|
||||
VerifyClientIp: false
|
||||
PAATokenSigningKey: "your-32-character-signing-key-here"
|
||||
PAATokenEncryptionKey: "your-32-character-encryption-key"
|
||||
|
||||
Caps:
|
||||
TokenAuth: true
|
||||
IdleTimeout: 60
|
||||
|
||||
Client:
|
||||
UsernameTemplate: "{{ username }}\x1f{{ token }}"
|
||||
```
|
||||
|
||||
### Docker Deployment
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
rdpgw:
|
||||
image: bolkedebruin/rdpgw:latest
|
||||
ports:
|
||||
- "80:443"
|
||||
volumes:
|
||||
- ./rdpgw.yaml:/app/rdpgw.yaml:ro
|
||||
environment:
|
||||
- RDPGW_SERVER__TLS=disable
|
||||
- RDPGW_SERVER__PORT=443
|
||||
networks:
|
||||
- internal
|
||||
|
||||
networks:
|
||||
internal:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
## Step 5: Conditional Access Policy
|
||||
|
||||
### Create CAP for RDPGW
|
||||
|
||||
```powershell
|
||||
# PowerShell example (simplified)
|
||||
$conditions = @{
|
||||
"applications" = @{
|
||||
"includeApplications" = @($app.ApplicationId)
|
||||
}
|
||||
"users" = @{
|
||||
"includeGroups" = @("rdp-users-group-id")
|
||||
}
|
||||
"locations" = @{
|
||||
"includeLocations" = @("AllTrusted")
|
||||
}
|
||||
}
|
||||
|
||||
$grantControls = @{
|
||||
"operator" = "OR"
|
||||
"builtInControls" = @("mfa", "compliantDevice")
|
||||
}
|
||||
```
|
||||
|
||||
### Portal Configuration
|
||||
|
||||
1. **Navigate to**: Azure AD → Security → Conditional Access
|
||||
2. **Create Policy**:
|
||||
- **Name**: RDPGW Access Control
|
||||
- **Users**: Select appropriate groups
|
||||
- **Cloud apps**: Select RDPGW application
|
||||
- **Conditions**: Configure as needed (device, location, etc.)
|
||||
- **Grant**: Require MFA + Compliant Device
|
||||
- **Session**: Configure session lifetime
|
||||
|
||||
## Step 6: Testing
|
||||
|
||||
### Test Web Authentication
|
||||
|
||||
```bash
|
||||
# Test /connect endpoint
|
||||
curl -v https://rdpgw.yourdomain.com/connect
|
||||
# Should redirect to Azure AD login
|
||||
```
|
||||
|
||||
### Test RDP Connection
|
||||
|
||||
1. **Access web interface**: `https://rdpgw.yourdomain.com/connect`
|
||||
2. **Authenticate**: Complete Azure AD login + MFA
|
||||
3. **Download RDP file**: Should contain token-based credentials
|
||||
4. **Connect via RDP client**: Should work without additional authentication
|
||||
|
||||
### Verify Headers
|
||||
|
||||
Check that App Proxy forwards correct headers:
|
||||
|
||||
```bash
|
||||
# From internal network, test RDPGW directly
|
||||
curl -H "X-MS-CLIENT-PRINCIPAL-NAME: user@domain.com" \
|
||||
http://rdpgw-server/connect
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **RDP Client Won't Connect**:
|
||||
- Verify passthrough configuration for `/remoteDesktopGateway/*`
|
||||
- Check token generation in downloaded RDP file
|
||||
- Ensure `TokenAuth: true` in configuration
|
||||
|
||||
2. **Authentication Loop**:
|
||||
- Verify header configuration matches App Proxy headers
|
||||
- Check `VerifyClientIp: false` setting
|
||||
- Validate App Proxy connector connectivity
|
||||
|
||||
3. **CAP Not Enforced**:
|
||||
- Verify policy targets correct application
|
||||
- Check user/group assignments
|
||||
- Review conditional access logs
|
||||
|
||||
### Debug Commands
|
||||
|
||||
```bash
|
||||
# Check RDPGW logs
|
||||
docker logs rdpgw-container
|
||||
|
||||
# Test internal connectivity
|
||||
curl -H "X-MS-CLIENT-PRINCIPAL-NAME: test@domain.com" \
|
||||
http://rdpgw-internal/connect
|
||||
|
||||
# Verify token generation
|
||||
curl -v https://rdpgw.yourdomain.com/connect
|
||||
```
|
||||
|
||||
### Azure AD Logs
|
||||
|
||||
Monitor these logs for authentication issues:
|
||||
|
||||
- **Sign-ins**: User authentication events
|
||||
- **Conditional Access**: Policy evaluation results
|
||||
- **Application Proxy**: Connector and application events
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Network Isolation**: Deploy RDPGW in private network
|
||||
- **Connector Security**: Ensure App Proxy connector is secured
|
||||
- **Token Validation**: Monitor for token replay attacks
|
||||
- **Audit Logging**: Enable comprehensive logging for compliance
|
||||
- **Certificate Management**: Ensure proper TLS certificate chain
|
||||
|
||||
## Production Checklist
|
||||
|
||||
- [ ] App Proxy connector deployed and healthy
|
||||
- [ ] Application registration configured
|
||||
- [ ] Passthrough paths configured for RDP endpoints
|
||||
- [ ] Conditional Access policies tested
|
||||
- [ ] RDPGW header authentication working
|
||||
- [ ] RDP file download and connection successful
|
||||
- [ ] Monitoring and alerting configured
|
||||
- [ ] Backup and recovery procedures documented
|
||||
Reference in New Issue
Block a user