部署帶有 mTLS 直通監聽器的 Azure 應用閘道

這個快速入門說明如何使用Azure Resource Manager範本(ARM 範本)和 API 版本 ,部署帶有 2025-03-01 的 Azure 應用程式閘道。 在通過模式下,閘道會請求客戶端憑證,但不會驗證。 憑證驗證與政策執行則在後端進行。

主要功能

  • 將 SSL 設定檔與監聽器關聯,以實現 mTLS 直通。
  • 閘道器不需要客戶端 CA 憑證。
  • verifyClientAuthMode 屬性支援 Strict 與 Passthrough 值。
  • Portal 支援:你可以直接在 Microsoft Azure 入口網站設定 mTLS 代理。

備註

目前無法支援 PowerShell 與 CLI 的直通設定。 你可以使用 Azure 入口網站或 ARM 範本設定 mTLS 直通。

使用 Azure portal 設定 mTLS 透傳

你可以使用傳遞用戶端驗證方法,透過建立 SSL 設定檔直接在Azure入口網站設定 mTLS 傳遞:

  1. 在 Azure 入口網站中,導覽到你的應用程式閘道資源。

  2. 在 設定中選擇 SSL 設定檔。

  3. 選擇 + 新增 以建立新的 SSL 設定檔。

  4. 輸入你的 SSL 設定檔名稱。

  5. 在 客戶端認證 標籤中,選擇 「通過」。

    在直通模式下,用戶端憑證是可選的,後端伺服器負責用戶端認證。

螢幕擷取畫面顯示 Azure 入口網站中建立 SSL 設定檔對話方塊,且用戶端驗證方法選取「傳遞」。

  1. 根據需要設定 SSL 政策設定。
  2. 選擇 新增 以建立 SSL 設定檔。
  3. 將 SSL 設定檔與你的 HTTPS 監聽器關聯起來。

先決條件

  • 需要 Azure 訂用帳戶與資源群組。
  • Azure CLI 安裝於本地。
  • SSL憑證(Base64編碼的PFX)和密碼。
  • Linux VM 管理用的 SSH 金鑰(如果適用)。
  • API 版本 2025-03-01 或更新版本的直通特性。

部署帶有 mTLS 直通監聽器的應用閘道

此範本會建立下列資源:

  • 一個包含兩個子網(其中一個委派給應用閘道器)的虛擬網路。
  • 閘道前端的公共 IP 位址。
  • 應用程式閘道(Standard_v2)包括:
    • SSL 憑證與 SSL 模型用於客戶端憑證透傳。
    • HTTPS 監聽器與路由規則。
    • 後端集區指向一個 App Service。

更新範本,加入你的設定細節,並附上有效的 SSL 憑證。

參數檔案:deploymentParameters.json

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "addressPrefix": {
            "value": "10.0.0.0/16"
        },
        "subnetPrefix": {
            "value": "10.0.0.0/24"
        },
        "skuName": {
            "value": "Standard_v2"
        },
        "capacity": {
            "value": 2
        },
        "adminUsername": {
            "value": "ubuntu"
        },
        "adminSSHKey": {
            "value": "<your-ssh-public-key>"
        },
        "certData": {
            "value": "<Base64-encoded-PFX-data>"
        },
        "certPassword": {
            "value": "<certificate-password>"
        }
    }
}

範本檔案:deploymentTemplate.json

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "addressPrefix": {
            "defaultValue": "10.0.0.0/16",
            "type": "String",
            "metadata": {
                "description": "Address prefix for the Virtual Network"
            }
        },
        "subnetPrefix": {
            "defaultValue": "10.0.0.0/24",
            "type": "String",
            "metadata": {
                "description": "Subnet prefix"
            }
        },
        "skuName": {
            "defaultValue": "Standard_Medium",
            "type": "String",
            "metadata": {
                "description": "Sku Name"
            }
        },
        "capacity": {
            "defaultValue": 2,
            "type": "Int",
            "metadata": {
                "description": "Number of instances"
            }
        },
        "adminUsername": {
            "type": "String"
        },
		"adminSSHKey": {
            "type": "securestring"
        },
        "certData": {
            "type": "String",
            "metadata": {
                "description": "ssl cert data"
            }
        },
        "certPassword": {
            "type": "SecureString",
            "metadata": {
                "description": "ssl cert password"
            }
        }
    },
    "variables": {
        "applicationGatewayName": "mtlsAppGw",
        "idName": "identity",
        "publicIPAddressName": "mtlsPip",
        "virtualNetworkName": "mtlsVnet",
        "subnetName": "appgwsubnet",
        "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]",
        "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
        "publicIPRef": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]",
        "applicationGatewayID": "[resourceId('Microsoft.Network/applicationGateways',variables('applicationGatewayName'))]",
        "apiVersion": "2025-03-01",
        "identityID": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities',variables('idName'))]",
        "backendSubnetId": "[concat(variables('vnetID'),'/subnets/backendsubnet')]"
    },
    "resources": [
        {
            "type": "Microsoft.Network/virtualNetworks",
            "name": "[variables('virtualNetworkName')]",
            "apiVersion": "2024-07-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "[parameters('addressPrefix')]"
                    ]
                },
                "subnets": [
                    {
                        "name": "[variables('subnetName')]",
                        "properties": {
                            "addressPrefix": "[parameters('subnetPrefix')]",
                             "delegations": [
                                {
                                    "name": "Microsoft.Network/applicationGateways",
                                    "properties": {
                                        "serviceName": "Microsoft.Network/applicationGateways"
                                    }
                                }
                            ]
                        }
                    },
                    {
                        "name": "backendSubnet",
                        "properties": {
                            "addressPrefix": "10.0.2.0/24"
                        }
                    }
                ]
            }
        },
        {
            "type": "Microsoft.Network/publicIPAddresses",
            "sku": {
                "name": "Standard"
            },
            "name": "[variables('publicIPAddressName')]",
            "apiVersion": "2024-07-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "publicIPAllocationMethod": "Static"
            }
        },
        {
            "type": "Microsoft.Network/applicationGateways",
            "name": "[variables('applicationGatewayName')]",
            "apiVersion": "[variables('apiVersion')]",
            "location": "[resourceGroup().location]",
            "properties": {
                "sku": {
                    "name": "Standard_v2",
                    "tier": "Standard_v2",
                    "capacity": 3
                },
                "sslCertificates": [
                    {
                        "name": "sslCert",
                        "properties": {
                            "data": "[parameters('certData')]",
                            "password": "[parameters('certPassword')]"
                        }
                    }
                ],
                "sslPolicy": {
                    "policyType": "Predefined",
                    "policyName": "AppGwSslPolicy20220101"
                },
                "sslProfiles": [
                    {
                        "name": "sslnotrustedcert",
                        "id": "[concat(resourceId('Microsoft.Network/applicationGateways',  variables('applicationGatewayName')), '/sslProfiles/sslnotrustedcert')]",
                        "properties": {
                            "clientAuthConfiguration": {
                                "VerifyClientCertIssuerDN": false,
                                "VerifyClientRevocation": "None",
                                "VerifyClientAuthMode": "Passthrough"
                            }
                        }
                    }                   
                ],
                "gatewayIPConfigurations": [
                    {
                        "name": "appGatewayIpConfig",
                        "properties": {
                            "subnet": {
                                "id": "[variables('subnetRef')]"
                            }
                        }
                    }
                ],
                "frontendIPConfigurations": [
                    {
                        "name": "appGatewayFrontendIP",
                        "properties": {
                            "PublicIPAddress": {
                                "id": "[variables('publicIPRef')]"
                            }
                        }
                    }
                ],
                "frontendPorts": [
                    {
                        "name": "port2",
                        "properties": {
                            "Port": 444
                        }
                    }
                ],
                "backendAddressPools": [
                    {
                        "name": "pool2",
                        "properties": {
                            "BackendAddresses": [
							  {
                                "fqdn": "headerappgw-hsa5gjh8fpfebcfd.westus-01.azurewebsites.net"
                              }
							]
                        }
                    }
                ],
                "backendHttpSettingsCollection": [
                    {
                        "name": "settings2",
                        "properties": {
                            "Port": 80,
                            "Protocol": "Http"
                        }
                    }
                ],
                "httpListeners": [
                    {
                        "name": "listener2",
                        "properties": {
                            "FrontendIPConfiguration": {
                                "Id": "[concat(variables('applicationGatewayID'), '/frontendIPConfigurations/appGatewayFrontendIP')]"
                            },
                            "FrontendPort": {
                                "Id": "[concat(variables('applicationGatewayID'), '/frontendPorts/port2')]"
                            },
                            "Protocol": "Https",
                            "SslCertificate": {
                                "Id": "[concat(variables('applicationGatewayID'), '/sslCertificates/sslCert')]"
                            },
                            "sslProfile": {
                                "id": "[concat(variables('applicationGatewayID'), '/sslProfiles/sslnotrustedcert')]"
                            }
                        }
                    }
                ],
                "requestRoutingRules": [
                    {
                        "Name": "rule2",
                        "properties": {
                            "RuleType": "Basic",
                            "priority": 2000,
                            "httpListener": {
                                "id": "[concat(variables('applicationGatewayID'), '/httpListeners/listener2')]"
                            },
                            "backendAddressPool": {
                                "id": "[concat(variables('applicationGatewayID'), '/backendAddressPools/pool2')]"
                            },
                            "backendHttpSettings": {
                                "id": "[concat(variables('applicationGatewayID'), '/backendHttpSettingsCollection/settings2')]"
                            }
                        }
                    }
                ]
            },
            "dependsOn": [
                "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
                "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]"
            ]
        }
    ]
}

部署範本

執行以下 Azure CLI 指令來部署範本:

az deployment group create \
  --resource-group <your-resource-group> \
  --template-file deploymentTemplate.json \
  --parameters @deploymentParameters.json

驗證和測試

驗證部署

  1. 在 Azure 入口網站中,瀏覽至您的應用程式閘道資源。

  2. 選擇 JSON View ,並選擇 API 版本 2025-03-01。

  3. 請確認在 SSL 設定檔中,verifyClientAuthMode 已設定為 Passthrough。

    "sslProfiles": [
        {
            "name": "sslnotrustedcert",
            "id": "<sample-subscription-id>",
            "etag": "W/\"851e4e20-d2b1-4338-9135-e0beac11aa0e\"",
            "properties": {
                "provisioningState": "Succeeded",
                "clientAuthConfiguration": {
                    "verifyClientCertIssuerDN": false,
                    "verifyClientRevocation": "None",
                    "verifyClientAuthMode": "Passthrough"
                },
                "httpListeners": [
                    {
                        "id": "<sample-subscription-id>"
                    }
                ]
            }
        }
    ]
    

將客戶端憑證傳送到後端

如果你需要將客戶端憑證轉發到後端,請設定重寫規則。 欲了解更多資訊,請參閱 「用應用程式閘道重寫 HTTP 標頭與網址」。

當客戶端發送憑證時,此重寫確保該憑證包含在後端處理的請求標頭中。

測試連線能力

即使沒有提供客戶端憑證,也要確認連線是否已建立。

mTLS 透傳參數

下表說明了 mTLS 直通配置的參數:

名稱 類型 Description
verifyClientCertIssuerDN 布林值 規定是否要驗證閘道器上的用戶端憑證發行者名稱。
verifyClientRevocation 繩子 指定客戶端憑證撤銷驗證模式。
verifyClientAuthMode 繩子 指定用戶端憑證模式。 有效值為 Strict 和 Passthrough。

直通模式: 閘道器會要求客戶端憑證,但不會強制執行。 後端會驗證憑證並執行政策。

安全性考慮

部署和管理此解決方案時,請遵循貴組織的安全與資料處理最佳實務。