Add header authentication

This commit is contained in:
Bolke de Bruin
2025-09-18 22:35:40 +02:00
parent fee421beba
commit 75a7ca62a9
11 changed files with 1392 additions and 127 deletions

View File

@@ -0,0 +1,111 @@
# Header Authentication
RDPGW supports header-based authentication for integration with reverse proxy services that handle authentication upstream.
## Configuration
```yaml
Server:
Authentication:
- header
Tls: disable # Proxy handles TLS termination
Header:
UserHeader: "X-Forwarded-User" # Required: Username header
UserIdHeader: "X-Forwarded-User-Id" # Optional: User ID header
EmailHeader: "X-Forwarded-Email" # Optional: Email header
DisplayNameHeader: "X-Forwarded-Name" # Optional: Display name header
Caps:
TokenAuth: true
Security:
VerifyClientIp: false # Requests come through proxy
```
## Proxy Service Examples
### Microsoft Azure Application Proxy
```yaml
Header:
UserHeader: "X-MS-CLIENT-PRINCIPAL-NAME"
UserIdHeader: "X-MS-CLIENT-PRINCIPAL-ID"
EmailHeader: "X-MS-CLIENT-PRINCIPAL-EMAIL"
```
**Setup**: Configure App Proxy to publish RDPGW with pre-authentication enabled. Users authenticate via Azure AD before reaching RDPGW.
### Google Cloud Identity-Aware Proxy (IAP)
```yaml
Header:
UserHeader: "X-Goog-Authenticated-User-Email"
UserIdHeader: "X-Goog-Authenticated-User-ID"
EmailHeader: "X-Goog-Authenticated-User-Email"
```
**Setup**: Enable IAP on your Cloud Load Balancer pointing to RDPGW. Configure OAuth consent screen and authorized users/groups.
### AWS Application Load Balancer (ALB) with Cognito
```yaml
Header:
UserHeader: "X-Amzn-Oidc-Subject"
EmailHeader: "X-Amzn-Oidc-Email"
DisplayNameHeader: "X-Amzn-Oidc-Name"
```
**Setup**: Configure ALB with Cognito User Pool authentication. Enable OIDC headers forwarding to RDPGW target group.
### Traefik with ForwardAuth
```yaml
Header:
UserHeader: "X-Forwarded-User"
EmailHeader: "X-Forwarded-Email"
DisplayNameHeader: "X-Forwarded-Name"
```
**Setup**: Use Traefik ForwardAuth middleware with external auth service (e.g., OAuth2 Proxy, Authelia) that sets headers.
### nginx with auth_request
```yaml
Header:
UserHeader: "X-Auth-User"
EmailHeader: "X-Auth-Email"
```
**nginx config**:
```nginx
location /auth {
internal;
proxy_pass http://auth-service;
proxy_set_header X-Original-URI $request_uri;
}
location / {
auth_request /auth;
auth_request_set $user $upstream_http_x_auth_user;
auth_request_set $email $upstream_http_x_auth_email;
proxy_set_header X-Auth-User $user;
proxy_set_header X-Auth-Email $email;
proxy_pass http://rdpgw;
}
```
## Security Considerations
- **Trust Boundary**: RDPGW trusts headers set by the proxy. Ensure the proxy cannot be bypassed.
- **Header Validation**: Configure proxy to strip/override user headers from client requests.
- **Network Security**: Deploy RDPGW in private network accessible only via the proxy.
- **TLS**: Enable TLS between proxy and RDPGW in production environments.
## Validation
Test header authentication:
```bash
curl -H "X-Forwarded-User: testuser@domain.com" \
https://your-proxy/connect
```

View File

@@ -0,0 +1,156 @@
# Kerberos Authentication
![Kerberos](images/flow-kerberos.svg)
RDPGW supports Kerberos authentication via SPNEGO for seamless integration with Active Directory and other Kerberos environments.
## Important Notes
**⚠️ DNS Requirements**: Kerberos is heavily reliant on DNS (forward and reverse). Ensure your DNS is properly configured.
**⚠️ Error Messages**: Kerberos errors are not always descriptive. This documentation provides configuration guidance, but detailed Kerberos troubleshooting is beyond scope.
## Prerequisites
- Valid Kerberos environment (KDC/Active Directory)
- Proper DNS configuration (forward and reverse lookups)
- Service principal for the gateway
- Keytab file with appropriate permissions
## Configuration
### 1. Create Service Principal
Create a service principal for the gateway in your Kerberos realm:
```bash
# Active Directory
setspn -A HTTP/rdpgw.example.com@YOUR.REALM service-account
# MIT Kerberos
kadmin.local -q "addprinc -randkey HTTP/rdpgw.example.com@YOUR.REALM"
```
### 2. Generate Keytab
Use `ktutil` or similar tool to create a keytab file:
```bash
ktutil
addent -password -p HTTP/rdpgw.example.com@YOUR.REALM -k 1 -e aes256-cts-hmac-sha1-96
wkt rdpgw.keytab
quit
```
Place the keytab file in a secure location and ensure it's only readable by the gateway user:
```bash
sudo mv rdpgw.keytab /etc/keytabs/
sudo chown rdpgw:rdpgw /etc/keytabs/rdpgw.keytab
sudo chmod 600 /etc/keytabs/rdpgw.keytab
```
### 3. Configure krb5.conf
Ensure `/etc/krb5.conf` is properly configured:
```ini
[libdefaults]
default_realm = YOUR.REALM
dns_lookup_realm = true
dns_lookup_kdc = true
[realms]
YOUR.REALM = {
kdc = kdc.your.realm:88
admin_server = kdc.your.realm:749
}
[domain_realm]
.your.realm = YOUR.REALM
your.realm = YOUR.REALM
```
### 4. Gateway Configuration
```yaml
Server:
Authentication:
- kerberos
Kerberos:
Keytab: /etc/keytabs/rdpgw.keytab
Krb5conf: /etc/krb5.conf
Caps:
TokenAuth: false
```
## Authentication Flow
1. Client connects to gateway with Kerberos ticket
2. Gateway validates ticket using keytab
3. Client connects directly without RDP file download
4. Gateway proxies TGT requests to KDC as needed
## KDC Proxy Support
RDPGW includes KDC proxy functionality for environments where clients cannot directly reach the KDC:
- Endpoint: `https://your-gateway/KdcProxy`
- Supports MS-KKDCP protocol
- Automatically configured when Kerberos authentication is enabled
## Client Configuration
### Windows Clients
Configure Windows clients to use the gateway's FQDN and ensure:
- Client can resolve gateway hostname
- Client time is synchronized with KDC
- Client has valid TGT
### Linux Clients
Ensure `krb5.conf` is configured and client has valid ticket:
```bash
kinit username@YOUR.REALM
klist # Verify ticket
```
## Troubleshooting
### Common Issues
1. **Clock Skew**: Ensure all systems have synchronized time
2. **DNS Issues**: Verify forward/reverse DNS resolution
3. **Principal Names**: Ensure service principal matches gateway FQDN
4. **Keytab Permissions**: Verify keytab file permissions and ownership
### Debug Commands
```bash
# Test keytab
kinit -k -t /etc/keytabs/rdpgw.keytab HTTP/rdpgw.example.com@YOUR.REALM
# Verify DNS
nslookup rdpgw.example.com
nslookup <gateway-ip>
# Check time sync
ntpdate -q ntp.your.realm
```
### Log Analysis
Enable verbose logging in RDPGW and check for:
- Keytab loading errors
- Principal validation failures
- KDC communication issues
## Security Considerations
- Protect keytab files with appropriate permissions (600)
- Regularly rotate service account passwords
- Monitor for unusual authentication patterns
- Ensure encrypted communication (aes256-cts-hmac-sha1-96)
- Use specific service accounts, not user accounts

268
docs/ntlm-authentication.md Normal file
View File

@@ -0,0 +1,268 @@
# NTLM Authentication
RDPGW supports NTLM authentication for simple setup with Windows clients, particularly useful for small deployments with a limited number of users.
## Advantages
- **Easy Setup**: Simple configuration without external dependencies
- **Windows Client Support**: Works with default Windows client `mstsc`
- **No External Services**: Self-contained authentication mechanism
- **Quick Deployment**: Ideal for small teams or testing environments
## Security Warning
**⚠️ Plain Text Storage**: Passwords are currently stored in plain text to support the NTLM authentication protocol. Keep configuration files secure and avoid reusing passwords for other applications.
## Configuration
### 1. Gateway Configuration
Configure RDPGW to use NTLM authentication:
```yaml
Server:
Authentication:
- ntlm
Caps:
TokenAuth: false
```
### 2. Authentication Helper Configuration
Create configuration file for `rdpgw-auth` with user credentials:
```yaml
# /etc/rdpgw-auth.yaml
Users:
- Username: "alice"
Password: "secure_password_1"
- Username: "bob"
Password: "secure_password_2"
- Username: "admin"
Password: "admin_secure_password"
```
### 3. Start Authentication Helper
Run the `rdpgw-auth` helper with NTLM configuration:
```bash
./rdpgw-auth -c /etc/rdpgw-auth.yaml -s /tmp/rdpgw-auth.sock
```
## Authentication Flow
1. Client initiates NTLM handshake with gateway
2. Gateway forwards NTLM messages to `rdpgw-auth`
3. Helper validates credentials against configured user database
4. Client connects directly on successful authentication
## User Management
### Adding Users
Edit the configuration file and restart the helper:
```yaml
Users:
- Username: "newuser"
Password: "new_secure_password"
- Username: "existing_user"
Password: "existing_password"
```
### Password Rotation
1. Update passwords in configuration file
2. Restart `rdpgw-auth` helper
3. Notify users of password changes
### User Removal
Remove user entries from configuration and restart helper.
## Deployment Options
### Systemd Service
Create `/etc/systemd/system/rdpgw-auth.service`:
```ini
[Unit]
Description=RDPGW NTLM Authentication Helper
After=network.target
[Service]
Type=simple
User=rdpgw
ExecStart=/usr/local/bin/rdpgw-auth -c /etc/rdpgw-auth.yaml -s /tmp/rdpgw-auth.sock
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
### Docker Deployment
```yaml
# docker-compose.yml
services:
rdpgw-auth:
image: rdpgw-auth
volumes:
- ./rdpgw-auth.yaml:/etc/rdpgw-auth.yaml:ro
- auth-socket:/tmp
restart: always
rdpgw:
image: rdpgw
volumes:
- auth-socket:/tmp
depends_on:
- rdpgw-auth
volumes:
auth-socket:
```
### Kubernetes Deployment
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: rdpgw-auth-config
data:
rdpgw-auth.yaml: |
Users:
- Username: "user1"
Password: "password1"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rdpgw-auth
spec:
template:
spec:
containers:
- name: rdpgw-auth
image: rdpgw-auth
volumeMounts:
- name: config
mountPath: /etc/rdpgw-auth.yaml
subPath: rdpgw-auth.yaml
volumes:
- name: config
configMap:
name: rdpgw-auth-config
```
## Client Configuration
### Windows (mstsc)
NTLM authentication works seamlessly with the default Windows Remote Desktop client:
1. Configure gateway address in RDP settings
2. Save gateway credentials when prompted
3. Connect using domain credentials or local accounts
### Alternative Clients
NTLM is widely supported across RDP clients:
- **mRemoteNG** (Windows)
- **Royal TS/TSX** (Windows/macOS)
- **Remmina** (Linux)
- **FreeRDP** (Cross-platform)
## Security Best Practices
### File Permissions
Secure the configuration file:
```bash
sudo chown rdpgw:rdpgw /etc/rdpgw-auth.yaml
sudo chmod 600 /etc/rdpgw-auth.yaml
```
### Password Policy
- Use strong, unique passwords for each user
- Implement regular password rotation
- Avoid reusing passwords from other systems
- Consider minimum password length requirements
### Network Security
- Deploy gateway behind TLS termination
- Use private networks when possible
- Implement network-level access controls
- Monitor authentication logs for suspicious activity
### Access Control
- Limit user accounts to necessary personnel only
- Regularly audit user list and remove inactive accounts
- Use principle of least privilege
- Consider time-based access restrictions
## Migration Path
For production environments, consider migrating to more secure authentication methods:
### To OpenID Connect
- Better password security (hashed storage)
- MFA support
- Centralized user management
- SSO integration
### To Kerberos
- No password storage in gateway
- Enterprise authentication integration
- Stronger cryptographic security
- Seamless Windows domain integration
## Troubleshooting
### Common Issues
1. **Authentication Failed**: Verify username/password in configuration
2. **Helper Not Running**: Check if `rdpgw-auth` process is active
3. **Socket Errors**: Verify socket path and permissions
### Debug Commands
```bash
# Check helper process
ps aux | grep rdpgw-auth
# Verify configuration
cat /etc/rdpgw-auth.yaml
# Test socket connectivity
ls -la /tmp/rdpgw-auth.sock
# Monitor authentication logs
journalctl -u rdpgw-auth -f
```
### Log Analysis
Enable debug logging in `rdpgw-auth` for detailed NTLM protocol analysis:
```bash
./rdpgw-auth -c /etc/rdpgw-auth.yaml -s /tmp/rdpgw-auth.sock -v
```
## Future Enhancements
Planned improvements for NTLM authentication:
- **Database Backend**: Support for SQLite/PostgreSQL user storage
- **Password Hashing**: Secure password storage options
- **Group Support**: Role-based access control
- **Audit Logging**: Enhanced security monitoring

View File

@@ -0,0 +1,75 @@
# OpenID Connect Authentication
![OpenID Connect](images/flow-openid.svg)
RDPGW supports OpenID Connect authentication for integration with identity providers like Keycloak, Okta, Google, Azure, Apple, or Facebook.
## Configuration
To use OpenID Connect, ensure you have properly configured your OpenID Connect provider with a client ID and secret. The client ID and secret authenticate the gateway to the OpenID Connect provider. The provider authenticates the user and provides the gateway with a token, which generates a PAA token for RDP host connections.
```yaml
Server:
Authentication:
- openid
OpenId:
ProviderUrl: https://<provider_url>
ClientId: <your_client_id>
ClientSecret: <your_client_secret>
Caps:
TokenAuth: true
```
## Authentication Flow
1. User navigates to `https://your-gateway/connect`
2. Gateway redirects to OpenID Connect provider for authentication
3. User authenticates with the provider (supports MFA)
4. Provider redirects back to gateway with authentication token
5. Gateway validates token and generates RDP file with temporary credentials
6. User downloads RDP file and connects using remote desktop client
## Multi-Factor Authentication (MFA)
RDPGW provides multi-factor authentication out of the box with OpenID Connect integration. Configure MFA in your identity provider to enhance security.
## Provider Examples
### Keycloak
```yaml
OpenId:
ProviderUrl: https://keycloak.example.com/auth/realms/your-realm
ClientId: rdpgw
ClientSecret: your-keycloak-secret
```
### Azure AD
```yaml
OpenId:
ProviderUrl: https://login.microsoftonline.com/{tenant-id}/v2.0
ClientId: your-azure-app-id
ClientSecret: your-azure-secret
```
### Google
```yaml
OpenId:
ProviderUrl: https://accounts.google.com
ClientId: your-google-client-id.googleusercontent.com
ClientSecret: your-google-secret
```
## Security Considerations
- Always use HTTPS for production deployments
- Store client secrets securely and rotate them regularly
- Configure appropriate scopes and claims in your provider
- Enable MFA in your identity provider for enhanced security
- Set appropriate session timeouts in both gateway and provider
## Troubleshooting
- Ensure `ProviderUrl` is accessible from the gateway
- Verify redirect URI is configured in your provider (usually `https://your-gateway/callback`)
- Check that required scopes (openid, profile, email) are configured
- Validate that the provider's certificate is trusted by the gateway

242
docs/pam-authentication.md Normal file
View File

@@ -0,0 +1,242 @@
# PAM/Local Authentication
![PAM](images/flow-pam.svg)
RDPGW supports PAM (Pluggable Authentication Modules) for authentication against local accounts, LDAP, Active Directory, and other PAM-supported systems.
## Important Notes
**⚠️ Client Limitation**: The default Windows client `mstsc` does not support basic authentication. Use alternative clients or switch to OpenID Connect, Kerberos, or NTLM authentication.
**⚠️ Container Considerations**: Using PAM for passwd authentication within containers is not recommended. Use OpenID Connect or Kerberos instead. For LDAP/AD authentication, PAM works well in containers.
## Architecture
PAM authentication uses a privilege separation model with the `rdpgw-auth` helper program:
- `rdpgw` - Main gateway (runs as unprivileged user)
- `rdpgw-auth` - Authentication helper (runs as root or setuid)
- Communication via Unix socket
## Configuration
### 1. PAM Service Configuration
Create `/etc/pam.d/rdpgw` for the authentication service:
**Local passwd authentication:**
```plaintext
auth required pam_unix.so
account required pam_unix.so
```
**LDAP authentication:**
```plaintext
auth required pam_ldap.so
account required pam_ldap.so
```
**Active Directory (via Winbind):**
```plaintext
auth sufficient pam_winbind.so
account sufficient pam_winbind.so
```
### 2. Gateway Configuration
```yaml
Server:
Authentication:
- local
AuthSocket: /tmp/rdpgw-auth.sock
BasicAuthTimeout: 5 # seconds
Caps:
TokenAuth: false
```
### 3. Start Authentication Helper
Run the `rdpgw-auth` helper program:
```bash
# Basic usage
./rdpgw-auth -n rdpgw -s /tmp/rdpgw-auth.sock
# With custom PAM service name
./rdpgw-auth -n custom-service -s /tmp/rdpgw-auth.sock
# Run as systemd service
systemctl start rdpgw-auth
```
## Authentication Flow
1. Client connects to gateway with username/password
2. Gateway forwards credentials to `rdpgw-auth` via socket
3. `rdpgw-auth` validates credentials using PAM
4. Gateway generates session tokens on successful authentication
5. Client connects directly using authenticated session
## PAM Module Examples
### LDAP Integration
Install and configure LDAP PAM module:
```bash
# Install LDAP PAM module
sudo apt-get install libpam-ldap
# Configure /etc/pam_ldap.conf
host ldap.example.com
base dc=example,dc=com
binddn cn=readonly,dc=example,dc=com
bindpw secret
```
### Active Directory Integration
Configure Winbind PAM module:
```bash
# Install Winbind
sudo apt-get install winbind libpam-winbind
# Configure /etc/samba/smb.conf
[global]
security = ads
realm = EXAMPLE.COM
workgroup = EXAMPLE
```
### Two-Factor Authentication
Integrate with TOTP/HOTP using pam_oath:
```plaintext
auth required pam_oath.so usersfile=/etc/users.oath
auth required pam_unix.so
account required pam_unix.so
```
## Container Deployment
### Option 1: External Helper
Run `rdpgw-auth` on the host and mount socket:
```yaml
# docker-compose.yml
services:
rdpgw:
image: rdpgw
volumes:
- /tmp/rdpgw-auth.sock:/tmp/rdpgw-auth.sock
```
### Option 2: Privileged Container
Mount PAM configuration and user databases:
```yaml
services:
rdpgw:
image: rdpgw
privileged: true
volumes:
- /etc/passwd:/etc/passwd:ro
- /etc/shadow:/etc/shadow:ro
- /etc/pam.d:/etc/pam.d:ro
```
## Systemd Service
Create `/etc/systemd/system/rdpgw-auth.service`:
```ini
[Unit]
Description=RDPGW Authentication Helper
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/rdpgw-auth -n rdpgw -s /tmp/rdpgw-auth.sock
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
Enable and start the service:
```bash
sudo systemctl enable rdpgw-auth
sudo systemctl start rdpgw-auth
```
## Compatible Clients
Since `mstsc` doesn't support basic authentication, use these alternatives:
### Windows
- **Remote Desktop Connection Manager** (RDCMan)
- **mRemoteNG**
- **Royal TS/TSX**
### Linux
- **Remmina**
- **FreeRDP** (with basic auth support)
- **KRDC**
### macOS
- **Microsoft Remote Desktop** (from App Store)
- **Royal TSX**
## Security Considerations
- Run `rdpgw-auth` with minimal privileges
- Secure the Unix socket with appropriate permissions
- Use strong PAM configurations (account lockout, password complexity)
- Enable logging for authentication events
- Consider rate limiting for brute force protection
- Use encrypted connections (TLS) for the gateway
## Troubleshooting
### Common Issues
1. **Socket Permission Denied**: Check socket permissions and ownership
2. **PAM Authentication Failed**: Verify PAM configuration and user credentials
3. **Helper Not Running**: Ensure `rdpgw-auth` is running and accessible
### Debug Commands
```bash
# Test PAM configuration
pamtester rdpgw username authenticate
# Check socket
ls -la /tmp/rdpgw-auth.sock
# Verify helper process
ps aux | grep rdpgw-auth
# Test authentication manually
echo "username:password" | nc -U /tmp/rdpgw-auth.sock
```
### Log Analysis
Enable PAM logging in `/etc/rsyslog.conf`:
```plaintext
auth,authpriv.* /var/log/auth.log
```
Monitor authentication attempts:
```bash
tail -f /var/log/auth.log | grep rdpgw
```