VPN Gateway Setup Guide - Point-to-Site Access (DEV ONLY)
⚠️ DEPRECATED (2025-10-24): This guide is for historical reference only. VPN Gateway has been replaced by Azure Bastion + Windows Jump Box VM (ADR-050).
→ See Bastion Dev Access for current recommended approach.
Why deprecated: - High cost (~$360/month for VPN Gateway) - Complex client setup and troubleshooting - Replaced by simpler, cheaper Bastion solution (~$210/month) - Bastion provides browser-based access with Windows environment for UI testing - Cost savings: ~$150/month
Migration: If you have existing VPN Gateway, consider migrating to Bastion (ADR-050).
Historical Documentation (VPN Gateway Approach)
⚠️ Production Note: VPN Gateway is NOT allowed in production. For production environments, use Azure Bastion with a jump box for secure access to private resources.
Overview
This guide walks you through setting up and using the Point-to-Site (P2S) VPN Gateway to access private Azure resources (AI Foundry Studio, Key Vault, etc.) from your local machine.
Environment Support: - ✅ Dev: Supported (default: enabled) - ✅ Staging: Supported (optional) - ❌ Prod: Not supported (use Azure Bastion)
Prerequisites
- VPN Gateway deployed (see deployment section below)
- Azure CLI or PowerShell installed
- Azure VPN Client app installed (download links below)
- Azure AD account with access to the subscription
Architecture
Your Laptop → VPN Tunnel (encrypted) → Azure VPN Gateway → VNet → Private Endpoints → AI Services, Key Vault, Storage
Once connected: - Access AI Foundry Studio: https://ai.azure.com - Access Azure Portal resources via private IPs - Use Azure CLI/SDKs as if you're on the Azure network
Step 1: Deploy VPN Gateway
Option A: Deploy with Infrastructure (Recommended)
VPN Gateway is automatically deployed when deployVpnGateway: true in dev environment.
# Deploy full infrastructure with VPN
./infrastructure/scripts/deploy.sh dev loan-defenders-dev-rg --stage all
# Or deploy VPN separately after infrastructure exists
./infrastructure/scripts/deploy.sh dev loan-defenders-dev-rg --stage vpn
Deployment Time: 30-45 minutes (VPN Gateway provisioning is slow)
Option B: Deploy Using Scripts
# Deploy Layer 1 with VPN Gateway enabled
# Edit infrastructure/bicep/environments/dev.parameters.json
# Set: "deployVpnGateway": { "value": true }
./infrastructure/scripts/deploy-layer1.sh dev
# Note: VPN Gateway deployment takes 30-45 minutes
Or use Azure CLI directly:
az deployment group create \
--name "layer1-vpn-$(date +%Y%m%d-%H%M%S)" \
--resource-group "loan-defenders-dev-rg" \
--template-file "infrastructure/bicep/layer1-foundation.bicep" \
--parameters "infrastructure/bicep/environments/dev.parameters.json" \
--verbose
Step 2: Install Azure VPN Client
Download and install the Azure VPN Client for your platform:
| Platform | Download Link |
|---|---|
| Windows | Microsoft Store - Azure VPN Client |
| macOS | App Store - Azure VPN Client |
| Linux | Manual Install |
⚠️ Native VPN Clients NOT Supported: Because this VPN Gateway uses Azure AD authentication with OpenVPN, you MUST use the Azure VPN Client app. Native OS VPN clients (Windows built-in VPN, macOS VPN) do NOT support Azure AD authentication.
Step 3: Download VPN Client Configuration
⚠️ CRITICAL: The VPN Gateway uses Azure AD authentication with OpenVPN protocol ONLY. The authentication method must be
EAPTLS, notEapMSChapv2.
PowerShell Method (Recommended)
# Authenticate to Azure
Connect-AzAccount
# Set subscription
Set-AzContext -SubscriptionId "<your-subscription-id>"
# Generate and download VPN client configuration (Azure AD auth)
$profile = New-AzVpnClientConfiguration `
-ResourceGroupName "loan-defenders-dev-rg" `
-VirtualNetworkGatewayName "vpn-gateway-dev" `
-AuthenticationMethod "EAPTLS"
# Get download URL
Write-Host "Download VPN Profile from:"
Write-Host $profile.VpnProfileSASUrl
# Open browser to download
Start-Process $profile.VpnProfileSASUrl
Azure CLI Method
# Authenticate to Azure
az login
# Generate VPN client configuration (Azure AD auth)
az network vnet-gateway vpn-client generate \
--resource-group loan-defenders-dev-rg \
--name vpn-gateway-dev \
--authentication-method EAPTLS \
--processor-architecture Amd64
# Output will show download URL - copy and download in browser
This generates a ZIP file containing:
- AzureVPN/azurevpnconfig.xml - Azure VPN Client profile (USE THIS)
- Generic/VpnSettings.xml - Generic VPN settings
- Generic/VpnServerRoot.cer_0 - Server root certificate
⚠️ Important: With Azure AD authentication, you MUST use the
AzureVPN/azurevpnconfig.xmlfile. Native clients (Windows VPN, macOS VPN) are NOT supported with Azure AD authentication.
Step 4: Import Configuration into Azure VPN Client
Windows / macOS
-
Open Azure VPN Client
-
Add VPN Connection:
- Click "+" (Add connection)
-
Click "Import"
-
Select Configuration File:
- Navigate to downloaded ZIP
-
Extract and select:
AzureVPN/azurevpnconfig.xml -
Configuration Imported:
- Connection name:
loan-defenders-dev-vpn - VPN Server: Azure VPN Gateway public IP
-
Authentication: Azure Active Directory
-
Save
Linux
Note: Linux support for Azure VPN Client requires the official Azure VPN Client for Linux. Follow Microsoft's documentation for Linux setup: https://aka.ms/azvpnclientdownload
Step 5: Grant Admin Consent (First Time Only)
⚠️ CRITICAL FIRST-TIME SETUP: Before connecting, you MUST grant admin consent for the Azure VPN Client application.
One-Time Setup (Azure AD Admin Required):
- Open the admin consent URL in your browser:
Replace {TENANT_ID} with your Azure AD tenant ID (find it in Azure Portal → Azure Active Directory → Overview)
-
Sign in with an Azure AD Global Administrator or Application Administrator account
-
Review permissions requested by Azure VPN Client:
- User.Read
-
User.ReadBasic.All
-
Click "Accept" to grant organization-wide consent
-
Confirmation - You'll see "Permissions granted" message
Why is this required? The Azure VPN Client needs permission to read your Azure AD profile to authenticate the VPN connection. Without admin consent, the VPN tunnel will fail to establish even after successful authentication.
Step 6: Connect to VPN
Azure VPN Client
-
Open Azure VPN Client
-
Select Connection:
-
Click on
loan-defenders-dev-vpn -
Click "Connect"
-
Authenticate:
- Browser window opens
- Sign in with your Azure AD account
-
Complete MFA if required
-
Connected!:
- Status shows "Connected"
- You're now on the Azure VNet
Verify Connection
# Check your VPN IP address (should be in 172.16.0.0/24 range)
ipconfig # Windows
ifconfig # macOS/Linux
# Test connectivity to private resources
nslookup loan-defenders-dev-ai.cognitiveservices.azure.com
Step 7: Access AI Foundry Studio
Once connected to VPN:
-
Open Browser: Navigate to https://ai.azure.com
-
Sign In: Use your Azure AD credentials
-
Select Hub: Choose
loan-defenders-dev-hub -
Access Studio: You now have full access to AI Foundry!
What you can access: - ✅ AI Foundry Studio (model deployments, playground, etc.) - ✅ Azure Portal (private resources) - ✅ Key Vault (via Azure SDK/CLI) - ✅ Storage Account (via Azure SDK/CLI) - ✅ All private endpoints on the VNet
Troubleshooting
Issue: VPN Connection Fails - Authentication Succeeds But Tunnel Doesn't Establish
Symptoms: - Azure AD authentication completes successfully - VPN client shows "Dialing" or "Connecting" - Connection never establishes - No clear error message
Root Cause: VPN Gateway Azure AD configuration uses incorrect issuer URL
Solution - Verify Gateway Configuration:
# Check VPN Gateway Azure AD configuration
az network vnet-gateway show \
--resource-group loan-defenders-dev-rg \
--name vpn-gateway-dev \
--query 'vpnClientConfiguration.{issuer:aadIssuer,tenant:aadTenant,audience:aadAudience,protocols:vpnClientProtocols}'
# Expected output:
# {
# "issuer": "https://sts.windows.net/{tenant-id}/", # MUST be sts.windows.net
# "tenant": "https://login.microsoftonline.com/{tenant-id}/",
# "audience": "41b23e61-6c1e-4545-b367-cd054e0ed4b4",
# "protocols": ["OpenVPN"] # MUST be OpenVPN only for AAD
# }
Critical Requirements:
1. ✅ aadIssuer MUST use https://sts.windows.net/{tenant-id}/ - NOT login.microsoftonline.com
2. ✅ vpnClientProtocols MUST be ["OpenVPN"] only - IKEv2 is incompatible with Azure AD auth
3. ✅ aadAudience must be 41b23e61-6c1e-4545-b367-cd054e0ed4b4 (Azure VPN Client app ID)
If configuration is wrong, redeploy VPN Gateway with corrected Bicep template.
Issue: VPN Gateway Provisioning Fails
Possible Causes: 1. Gateway still provisioning - Wait 30-45 minutes after deployment 2. Incorrect Bicep configuration - Check module parameters
Solution:
# Check VPN Gateway status
Get-AzVirtualNetworkGateway `
-ResourceGroupName "loan-defenders-dev-rg" `
-Name "vpn-gateway-dev"
# Look for: ProvisioningState should be "Succeeded"
Issue: Can't Access AI Foundry After Connecting
Verify VPN Connection:
# Check if you got a VPN IP
ipconfig | grep 172.16 # Should show IP in VPN range
# Test DNS resolution
nslookup loan-defenders-dev-ai.cognitiveservices.azure.com
# Test connectivity
ping 10.0.3.4 # Private endpoint subnet IP
Check Private Endpoint DNS:
# Verify private DNS zone records exist
Get-AzPrivateDnsZone -ResourceGroupName loan-defenders-dev-rg
Get-AzPrivateDnsRecordSet -ResourceGroupName loan-defenders-dev-rg -ZoneName "privatelink.cognitiveservices.azure.com"
Issue: "Authentication Failed"
Solution: 1. Ensure you're using correct Azure AD account 2. Check if your account has permissions on the subscription 3. Try re-downloading VPN client configuration 4. Clear browser cache and retry authentication
Issue: Slow VPN Connection
Possible Causes: - VPN Gateway SKU too small (VpnGw1 is basic) - Network congestion - Geographic distance from gateway
Solution:
# Upgrade to VpnGw2 for better performance
$gateway = Get-AzVirtualNetworkGateway `
-ResourceGroupName "loan-defenders-dev-rg" `
-Name "vpn-gateway-dev"
$gateway.Sku.Name = "VpnGw2"
$gateway.Sku.Tier = "VpnGw2"
Set-AzVirtualNetworkGateway -VirtualNetworkGateway $gateway
Note: Upgrade costs ~$360/month vs $140/month for VpnGw1
Disconnecting from VPN
Azure VPN Client
- Open Azure VPN Client
- Click "Disconnect"
Note: VPN Gateway still runs (and costs ~$144/month) even when not connected.
Cost Management
Monthly Costs (VPN Gateway VpnGw1)
- VPN Gateway: ~$140/month
- Public IP: ~$3.60/month
- Total: ~$144/month
Runs 24/7 regardless of connection status.
Alternative: Teardown When Not Needed
If you only need VPN access occasionally:
# Teardown dev environment (removes VPN Gateway)
./infrastructure/scripts/teardown.sh dev loan-defenders-dev-rg --confirm
# Rebuild when needed (30-45 min deployment)
./infrastructure/scripts/deploy.sh dev loan-defenders-dev-rg --stage all
Savings: ~$140/month when torn down
Production Alternative: Azure Bastion
For production environments, use Azure Bastion instead of VPN Gateway:
Advantages: - No client software needed (browser-based) - No open public ports - No client-side configuration - Better audit logging - Lower cost for single-user access
See: Azure Bastion Documentation
Security Best Practices
For Development (VPN Gateway)
- ✅ Use Azure AD authentication (no certificate management)
- ✅ Enable MFA for all VPN users
- ✅ Limit VPN client address pool size
- ✅ Monitor VPN connections in Azure Monitor
- ✅ Disconnect when not actively working
For Production (Azure Bastion)
- ✅ Deploy Bastion in production environments
- ✅ Use Just-In-Time (JIT) VM access
- ✅ Limit Bastion access via RBAC
- ✅ Enable Bastion audit logging
- ✅ Use jump boxes instead of direct access
Additional Resources
- Azure VPN Gateway Documentation
- Point-to-Site VPN Connections
- Azure AD Authentication for P2S
- Troubleshooting P2S Connections
Summary
- ✅ Deploy VPN Gateway (
deployVpnGateway: truein dev) - ✅ Install Azure VPN Client
- ✅ Download VPN configuration
- ✅ Import into Azure VPN Client
- ✅ Connect and authenticate
- ✅ Access AI Foundry Studio at https://ai.azure.com
Questions? Check the troubleshooting section or refer to Azure documentation.