It took me a while to figure this out as I am totally new to Azure.
The solution proposed in the previous post uses Private Endpoint, the problem with private endpoint is that you incur in additional network costs: https://azure.microsoft.com/en-us/pricing/details/private-link/
Yes, MS decided that when consuming a PaaS service (Azure, AKS, whatever) that is by default exposed in a public IP you should pay to have it attached to a VNET with a private IP (both by the hour, and by the ammount of traffic).
In the case of Azure SQL, you can still secure you SQL without resorting to Private Link and without having to grant permissions to public IP's on the resource.
- Setup a VNet
- Setup a Subnet (GatewaySubnet - this naming is enforced by MS, I guess to prevent people to have more than one Gateway per VNET and so forcing them to use VNET peering to incur in then more costs) with permissions for service endpoint "Microsoft.Sql"
- Setup a Gateway VPN attached to GatewaySubnet
- Setup your managed SQL Instance, and in the Networking pane "attach" it to the GatewaySubnet
With this setup you might be thinking that a user connected to the VPN should be able to connect to the SQL Server on it's public IP. As traffic is leaving from an authorized subnet, you should not need to whitelist the client's pubilc IP. Indeed it is, the problem is with how are splitting traffic from within the VPN connected client considering that:
You can force all your client traffic through the VPN and the issue will vanish, but I would not recommend that.
Easy setup
- Change your SQL networking settings to "Proxy" instead of the default "Auto".
- Add a routing rule for your PaaS server Host to go through the VPN:
$Hostname = "mydatabasesql.database.windows.net";
$VpnConnectionName = "vnetname";
$ip = [System.Net.Dns]::GetHostAddresses($Hostname)[0].IPAddressToString;
Add-VpnConnectionRoute -ConnectionName $VpnConnectionName -DestinationPrefix "$ip/32" -PassThru;
The problem with this setup is that MS clearly states that having the SQL traffic fully go through the proxy is NOT performance wise. Making this change will negatively impact you production workload performance.
Redirecting the whole Azure PaaS ranges setup
What happens during a redirection is that after initial connection attempt to the PaaS endpoint (the one resolved by "mysql.database.windows.net") the client is provided with a new public IP address where the actual connection needs to be made. That connection comes from a pool of ip ranges that are made public by Azure and regularly updated:
https://download.microsoft.com/download/7/1/D/71D86715-5596-4529-9B13-DA13A5DE5B63/ServiceTags_Public_20240115.json
So we basically just need to redirect traffic targeting those IP ranges through the VPN.
I made a small PS script to do so: https://gist.github.com/david-garcia-garcia/180978df54744511adae5e06f9e3d2bd