Files
rdpgw/docs/ms-app-proxy-deployment.md
Bolke de Bruin 866ed46fdc Extra docs
2025-09-18 23:09:40 +02:00

7.0 KiB

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

# 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

{
  "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

# 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

# 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

# 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 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

# 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:

# 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

# 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