Compartir a través de


Optimización del tráfico de Microsoft 365 para trabajos remotos con el cliente VPN de Windows

En este artículo se describe cómo configurar las recomendaciones del artículo Túnel dividido de VPN para Microsoft 365 para el cliente VPN de Windows. Esta guía permite a los administradores de VPN optimizar el uso de Microsoft 365, a la vez que garantizan que el resto del tráfico pasa por la conexión VPN y a través de las herramientas o puertas de enlace de seguridad existentes.

Las recomendaciones se pueden implementar para el cliente VPN de Windows integrado mediante un enfoque de tunelización forzada con exclusiones , que define exclusiones basadas en IP incluso cuando se usa la tunelización forzada. Cierto tráfico se puede dividir para usar la interfaz física, a la vez que se fuerza todo el resto del tráfico a través de la interfaz VPN. El tráfico dirigido a destinos definidos (como los que aparecen en las categorías optimizadas para Microsoft 365) sigue una ruta de acceso mucho más directa y eficaz, sin necesidad de atravesar el túnel VPN ni de volver a salir de la red de la organización. En el caso de los servicios en la nube como Microsoft 365, esto supone una diferencia significativa en el rendimiento y la facilidad de uso de los usuarios remotos.

Nota

El término forzar tunelización con exclusiones a veces se denomina túneles divididos por otros proveedores y en alguna documentación en línea. Para VPN de Windows, el término túnel dividido se define de forma diferente, como se describe en el artículo Decisiones de enrutamiento de VPN.

Información general de la solución

La solución se basa en el uso de un perfil de referencia del proveedor de servicios de configuración de VPN (CSP VPNv2) y profileXML incrustado. Se usan para configurar el perfil de VPN en el dispositivo. Se pueden usar varios enfoques de aprovisionamiento para crear e implementar el perfil de VPN, como se describe en el artículo Paso 6. Configure Windows 10 cliente Always On conexiones VPN.

Normalmente, estos perfiles de VPN se distribuyen mediante una solución de mobile Administración de dispositivos como Intune, como se describe en Opciones de perfil de VPN y Configuración del cliente VPN mediante Intune.

Para habilitar el uso de la tunelización forzada en Windows 10 o Windows 11 VPN, la <RoutingPolicyType> configuración se configura normalmente con un valor de ForceTunnel en el XML de perfil (o script) existente mediante la siguiente entrada, en la <NativeProfile></NativeProfile> sección :

<RoutingPolicyType>ForceTunnel</RoutingPolicyType>

Para definir exclusiones específicas del túnel de fuerza, debe agregar las siguientes líneas a su XML de perfil (o script) existente para cada exclusión necesaria y colocarlas fuera de la sección de la <NativeProfile></NativeProfile> siguiente manera:

<Route>
 <Address>[IP addresses or subnet]</Address>
 <PrefixSize>[IP Prefix]</PrefixSize>
 <ExclusionRoute>true</ExclusionRoute>
</Route>

En consecuencia, las entradas definidas por [IP Addresses or Subnet] las referencias y [IP Prefix] se agregarán a la tabla de enrutamiento como entradas de ruta más específicas que usarán la interfaz conectada a Internet como puerta de enlace predeterminada, en lugar de usar la interfaz VPN. Debe definir una sección única e independiente <Route></Route> para cada exclusión necesaria.

A continuación se muestra un ejemplo de una configuración XML de perfil con el formato correcto para forzar el túnel con exclusiones:

<VPNProfile>
 <NativeProfile>
  <RoutingPolicyType>ForceTunnel</RoutingPolicyType>
 </NativeProfile>
 <Route>
  <Address>203.0.113.0</Address>
  <PrefixSize>24</PrefixSize>
  <ExclusionRoute>true</ExclusionRoute>
 </Route>
 <Route>
  <Address>198.51.100.0</Address>
  <PrefixSize>22</PrefixSize>
  <ExclusionRoute>true</ExclusionRoute>
 </Route>
</VPNProfile>

Nota

Las direcciones IP y los valores de tamaño de prefijo de este ejemplo se usan únicamente como ejemplos y no se deben usar.

Implementación de soluciones

Por lo tanto, para Microsoft 365, es necesario agregar exclusiones para todas las direcciones IP documentadas en las categorías de optimización descritas en Office 365 direcciones URL e intervalos de direcciones IP para asegurarse de que se excluyen de la tunelización forzada de VPN.

Esto se puede lograr manualmente agregando las direcciones IP definidas dentro de las entradas de categoría de optimización a un archivo XML de perfil (o script) existente, o también se puede usar el siguiente script que agrega dinámicamente las entradas necesarias a un script de PowerShell existente, o a un archivo XML, basándose en consultar directamente el servicio web basado en REST para asegurarse de que siempre se usan los intervalos de direcciones IP correctos.

A continuación se proporciona un ejemplo de un script de PowerShell que se puede usar para actualizar una conexión VPN de túnel forzado con exclusiones de Microsoft 365.

# Copyright (c) Microsoft Corporation.  All rights reserved.
#
# THIS SAMPLE CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
# WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# IF THIS CODE AND INFORMATION IS MODIFIED, THE ENTIRE RISK OF USE OR RESULTS IN
# CONNECTION WITH THE USE OF THIS CODE AND INFORMATION REMAINS WITH THE USER.

<#
.SYNOPSIS
    Applies or updates recommended Microsoft 365 optimize IP address exclusions to an existing force tunnel Windows 10 and Windows 11 VPN profile
.DESCRIPTION
    Connects to the Microsoft 365 worldwide commercial service instance endpoints to obtain the latest published IP address ranges
    Compares the optimized IP addresses with those contained in the supplied VPN Profile (PowerShell or XML file)
    Adds or updates IP addresses as necessary and saves the resultant file with "-NEW" appended to the file name
.PARAMETERS
    Filename and path for a supplied Windows 10 or Windows 11 VPN profile file in either PowerShell or XML format
.NOTES
    Requires at least Windows 10 Version 1803 with KB4493437, 1809 with KB4490481, or later
.VERSION
    1.0
#>

param (
    [string]$VPNprofilefile
)

$usage=@"

This script uses the following parameters:

VPNprofilefile - The full path and name of the VPN profile PowerShell script or XML file

EXAMPLES

To check a VPN profile PowerShell script file:

Update-VPN-Profile-Office365-Exclusion-Routes.ps1 -VPNprofilefile [FULLPATH AND NAME OF POWERSHELL SCRIPT FILE]

To check a VPN profile XML file:

Update-VPN-Profile-Office365-Exclusion-Routes.ps1 -VPNprofilefile [FULLPATH AND NAME OF XML FILE]

"@

# Check if filename has been provided #
if ($VPNprofilefile -eq "")
{
   Write-Host "`nWARNING: You must specify either a PowerShell script or XML filename!" -ForegroundColor Red

    $usage
    exit
}

$FileExtension = [System.IO.Path]::GetExtension($VPNprofilefile)

# Check if XML file exists and is a valid XML file #
if ( $VPNprofilefile -ne "" -and $FileExtension -eq ".xml")
{
    if ( Test-Path $VPNprofilefile )
    {
        $xml = New-Object System.Xml.XmlDocument
        try
        {
            $xml.Load((Get-ChildItem -Path $VPNprofilefile).FullName)

        }
        catch [System.Xml.XmlException]
        {
            Write-Verbose "$VPNprofilefile : $($_.toString())"
            Write-Host "`nWARNING: The VPN profile XML file is not a valid xml file or incorrectly formatted!" -ForegroundColor Red
            $usage
            exit
        }
    }else
    {
        Write-Host "`nWARNING: VPN profile XML file does not exist or cannot be found!" -ForegroundColor Red
        $usage
        exit
    }
}

# Check if VPN profile PowerShell script file exists and contains a VPNPROFILE XML section #
if ( $VPNprofilefile -ne "" -and $FileExtension -eq ".ps1")
{
    if ( (Test-Path $VPNprofilefile) )
    {
        if (-Not $(Select-String -Path $VPNprofilefile -Pattern "<VPNPROFILE>") )
        {
            Write-Host "`nWARNING: PowerShell script file does not contain a valid VPN profile XML section or is incorrectly formatted!" -ForegroundColor Red
            $usage
            exit
        }
    }else
    {
        Write-Host "`nWARNING: PowerShell script file does not exist or cannot be found!"-ForegroundColor Red
        $usage
        exit
    }
}

# Define Microsoft 365 endpoints and service URLs #
$ws = "https://endpoints.office.com"
$baseServiceUrl = "https://endpoints.office.com"

# Path where client ID and latest version number will be stored #
$datapath = $Env:TEMP + "\endpoints_clientid_latestversion.txt"

# Fetch client ID and version if data file exists; otherwise create new file #
if (Test-Path $datapath)
{
    $content = Get-Content $datapath
    $clientRequestId = $content[0]
    $lastVersion = $content[1]

}else
{
    $clientRequestId = [GUID]::NewGuid().Guid
    $lastVersion = "0000000000"
    @($clientRequestId, $lastVersion) | Out-File $datapath
}

# Call version method to check the latest version, and pull new data if version number is different #
$version = Invoke-RestMethod -Uri ($ws + "/version?clientRequestId=" + $clientRequestId)

if ($version[0].latest -gt $lastVersion)
{

    Write-Host
    Write-Host "A new version of Microsoft 365 worldwide commercial service instance endpoints has been detected!" -ForegroundColor Cyan

    # Write the new version number to the data file #
    @($clientRequestId, $version[0].latest) | Out-File $datapath
}

# Invoke endpoints method to get the new data #
$uri = "$baseServiceUrl" + "/endpoints/worldwide?clientRequestId=$clientRequestId"

# Invoke endpoints method to get the data for the VPN profile comparison #
$endpointSets = Invoke-RestMethod -Uri ($uri)
$Optimize = $endpointSets | Where-Object { $_.category -eq "Optimize" }
$optimizeIpsv4 = $Optimize.ips | Where-Object { ($_).contains(".") } | Sort-Object -Unique

# Temporarily include additional IP address until Teams client update is released
$optimizeIpsv4 += "13.107.60.1/32"

# Process PowerShell script file start #
if ($VPNprofilefile -ne "" -and $FileExtension -eq ".ps1")
{
    Write-host "`nStarting PowerShell script exclusion route check...`n" -ForegroundColor Cyan

    # Clear Variables to allow re-run testing #

    $ARRVPN=$null              # Array to hold VPN addresses from VPN profile PowerShell file #
    $In_Opt_Only=$null         # Variable to hold IP addresses that only appear in the optimize list #
    $In_VPN_Only=$null         # Variable to hold IP addresses that only appear in the VPN profile PowerShell file #

    # Extract the Profile XML from the ps1 file #

    $regex = '(?sm).*^*.<VPNProfile>\r?\n(.*?)\r?\n</VPNProfile>.*'

    # Create xml format variable to compare with the optimize list #

    $xmlbody=(Get-Content -Raw $VPNprofilefile) -replace $regex, '$1'
    [xml]$VPNprofilexml="<VPNProfile>"+$xmlbody+"</VPNProfile>"

        # Loop through each address found in VPNPROFILE XML section #
        foreach ($Route in $VPNprofilexml.VPNProfile.Route)
        {
        $VPNIP=$Route.Address+"/"+$Route.PrefixSize
        [array]$ARRVPN=$ARRVPN+$VPNIP
        }

    # In optimize address list only #
    $In_Opt_Only= $optimizeIpsv4 | Where {$ARRVPN -NotContains $_}

    # In VPN list only #
    $In_VPN_only =$ARRVPN | Where {$optimizeIpsv4 -NotContains $_}
    [array]$Inpfile = get-content $VPNprofilefile

    if ($In_Opt_Only.Count -gt 0 )
    {
        Write-Host "Exclusion route IP addresses are unknown, missing, or need to be updated in the VPN profile`n" -ForegroundColor Red

         [int32]$insline=0

            for ($i=0; $i -lt $Inpfile.count; $i++)
            {
                if ($Inpfile[$i] -match "</NativeProfile>")
                {
                $insline += $i # Record the position of the line after the NativeProfile section ends #
                }
            }
            $OFS = "`r`n"
                foreach ($NewIP in $In_Opt_Only)
                {
                    # Add the missing IP address(es) #
                    $IPInfo=$NewIP.Split("/")
                    $InpFile[$insline] += $OFS+"    <Route>"
                    $InpFile[$insline] += $OFS+"      <Address>"+$IPInfo[0].Trim()+"</Address>"
                    $InpFile[$insline] += $OFS+"      <PrefixSize>"+$IPInfo[1].Trim()+"</PrefixSize>"
                    $InpFile[$insline] += $OFS+"      <ExclusionRoute>true</ExclusionRoute>"
                    $InpFile[$insline] += $OFS+"    </Route>"
                }
             # Update fileName and write new PowerShell file #
             $NewFileName=(Get-Item $VPNprofilefile).Basename + "-NEW.ps1"
             $OutFile=$(Split-Path $VPNprofilefile -Parent)+"\"+$NewFileName
             $InpFile | Set-Content $OutFile
             Write-Host "Exclusion routes have been added to VPN profile and output to a separate PowerShell script file; the original file has not been modified`n" -ForegroundColor Green
    }else
    {
        Write-Host "Exclusion route IP addresses are correct and up to date in the VPN profile`n" -ForegroundColor Green
        $OutFile=$VPNprofilefile
    }

if ( $In_VPN_Only.Count -gt 0 )
{
    Write-Host "Unknown exclusion route IP addresses have been found in the VPN profile`n" -ForegroundColor Yellow

        foreach ($OldIP in $In_VPN_Only)
        {
            [array]$Inpfile = get-content $Outfile
            $IPInfo=$OldIP.Split("/")
            Write-Host "Unknown exclusion route IP address"$IPInfo[0]"has been found in the VPN profile - Do you wish to remove it? (Y/N)`n" -ForegroundColor Yellow
            $matchstr="<Address>"+$IPInfo[0].Trim()+"</Address>"
            $DelAns=Read-host
                if ($DelAns.ToUpper() -eq "Y")
                {
                    [int32]$insline=0
                        for ($i=0; $i -lt $Inpfile.count; $i++)
                        {
                            if ($Inpfile[$i] -match $matchstr)
                            {
                                $insline += $i # Record the position of the line for the string match #
                            }
                        }
                        # Remove entries from XML #
                        $InpFile[$insline-1]="REMOVETHISLINE"
                        $InpFile[$insline]="REMOVETHISLINE"
                        $InpFile[$insline+1]="REMOVETHISLINE"
                        $InpFile[$insline+2]="REMOVETHISLINE"
                        $InpFile[$insline+3]="REMOVETHISLINE"
                        $InpFile=$InpFile | Where-Object {$_ -ne "REMOVETHISLINE"}

                        # Update filename and write new PowerShell file #
                        $NewFileName=(Get-Item $VPNprofilefile).Basename + "-NEW.xml"
                        $OutFile=$(Split-Path $VPNprofilefile -Parent)+"\"+$NewFileName
                        $Inpfile | Set-content $OutFile
                        Write-Host "`nAddress"$IPInfo[0]"exclusion route has been removed from the VPN profile and output to a separate PowerShell script file; the original file has not been modified`n" -ForegroundColor Green

                }else
                {
                    Write-Host "`nExclusion route IP address has *NOT* been removed from the VPN profile`n" -ForegroundColor Green
                }
        }
 }
}

# Process XML file start #
if ($VPNprofilefile -ne "" -and $FileExtension -eq ".xml")
{
    Write-host "`nStarting XML file exclusion route check...`n" -ForegroundColor Cyan

    # Clear variables to allow re-run testing #
    $ARRVPN=$null              # Array to hold VPN addresses from the XML file #
    $In_Opt_Only=$null         # Variable to hold IP Addresses that only appear in optimize list #
    $In_VPN_Only=$null         # Variable to hold IP Addresses that only appear in the VPN profile XML file #

    # Extract the Profile XML from the XML file #
    $regex = '(?sm).*^*.<VPNProfile>\r?\n(.*?)\r?\n</VPNProfile>.*'

    # Create xml format variable to compare with optimize list #
    $xmlbody=(Get-Content -Raw $VPNprofilefile) -replace $regex, '$1'
    [xml]$VPNRulesxml="$xmlbody"

        # Loop through each address found in VPNPROFILE file #
        foreach ($Route in $VPNRulesxml.VPNProfile.Route)
        {
            $VPNIP=$Route.Address+"/"+$Route.PrefixSize
            [array]$ARRVPN=$ARRVPN+$VPNIP
        }

    # In optimize address list only #
    $In_Opt_Only= $optimizeIpsv4 | Where {$ARRVPN -NotContains $_}

    # In VPN list only #
    $In_VPN_only =$ARRVPN | Where {$optimizeIpsv4 -NotContains $_}
    [System.Collections.ArrayList]$Inpfile = get-content $VPNprofilefile

        if ($In_Opt_Only.Count -gt 0 )
        {
            Write-Host "Exclusion route IP addresses are unknown, missing, or need to be updated in the VPN profile`n" -ForegroundColor Red

                foreach ($NewIP in $In_Opt_Only)
                {
                    # Add the missing IP address(es) #
                    $IPInfo=$NewIP.Split("/")
                    $routes += "<Route>`n"+"`t<Address>"+$IPInfo[0].Trim()+"</Address>`n"+"`t<PrefixSize>"+$IPInfo[1].Trim()+"</PrefixSize>`n"+"`t<ExclusionRoute>true</ExclusionRoute>`n"+"</Route>`n"
                }
            $inspoint = $Inpfile.IndexOf("</VPNProfile>")
            $Inpfile.Insert($inspoint,$routes)

            # Update filename and write new XML file #
            $NewFileName=(Get-Item $VPNprofilefile).Basename + "-NEW.xml"
            $OutFile=$(Split-Path $VPNprofilefile -Parent)+"\"+$NewFileName
            $InpFile | Set-Content $OutFile
            Write-Host "Exclusion routes have been added to VPN profile and output to a separate XML file; the original file has not been modified`n`n" -ForegroundColor Green

        }else
        {
            Write-Host "Exclusion route IP addresses are correct and up to date in the VPN profile`n" -ForegroundColor Green
            $OutFile=$VPNprofilefile
        }

        if ( $In_VPN_Only.Count -gt 0 )
        {
            Write-Host "Unknown exclusion route IP addresses found in the VPN profile`n" -ForegroundColor Yellow

            foreach ($OldIP in $In_VPN_Only)
            {
                [array]$Inpfile = get-content $OutFile
                $IPInfo=$OldIP.Split("/")
                Write-Host "Unknown exclusion route IP address"$IPInfo[0]"has been found in the VPN profile - Do you wish to remove it? (Y/N)`n" -ForegroundColor Yellow
                $matchstr="<Route>"+"<Address>"+$IPInfo[0].Trim()+"</Address>"+"<PrefixSize>"+$IPInfo[1].Trim()+"</PrefixSize>"+"<ExclusionRoute>true</ExclusionRoute>"+"</Route>"
                $DelAns=Read-host
                    if ($DelAns.ToUpper() -eq "Y")
                    {
                        # Remove unknown IP address(es) #
                        $inspoint = $Inpfile[0].IndexOf($matchstr)
                        $Inpfile[0] = $Inpfile[0].Replace($matchstr,"")

                        # Update filename and write new XML file #
                        $NewFileName=(Get-Item $VPNprofilefile).Basename + "-NEW.xml"
                        $OutFile=$(Split-Path $VPNprofilefile -Parent)+"\"+$NewFileName
                        $Inpfile | Set-content $OutFile
                        Write-Host "`nAddress"$IPInfo[0]"exclusion route has been removed from the VPN profile and output to a separate XML file; the original file has not been modified`n" -ForegroundColor Green

                    }else
                    {
                        Write-Host "`nExclusion route IP address has *NOT* been removed from the VPN profile`n" -ForegroundColor Green
                    }
            }
        }
}

Otras consideraciones

También debe poder adaptar este enfoque para incluir las exclusiones necesarias para otros servicios en la nube que se pueden definir mediante direcciones IP conocidas o estáticas; las exclusiones necesarias para Cisco WebEx o Zoom son buenos ejemplos.

Ejemplos

A continuación se proporciona un ejemplo de un script de PowerShell que se puede usar para crear una conexión VPN de túnel forzado con exclusiones de Microsoft 365 o consulte las instrucciones de Creación de los archivos de configuración ProfileXML para crear el script de PowerShell inicial:

# Copyright (c) Microsoft Corporation.  All rights reserved.
#
# THIS SAMPLE CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
# WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# IF THIS CODE AND INFORMATION IS MODIFIED, THE ENTIRE RISK OF USE OR RESULTS IN
# CONNECTION WITH THE USE OF THIS CODE AND INFORMATION REMAINS WITH THE USER.

<#
.SYNOPSIS
    Configures an AlwaysOn IKEv2 VPN Connection using a basic script
.DESCRIPTION
    Configures an AlwaysOn IKEv2 VPN Connection with proxy PAC information and force tunneling
.PARAMETERS
    Parameters are defined in a ProfileXML object within the script itself
.NOTES
    Requires at least Windows 10 Version 1803 with KB4493437, 1809 with KB4490481, or later
.VERSION
    1.0
#>

<#-- Define Key VPN Profile Parameters --#>
$ProfileName = 'Contoso VPN with Microsoft 365 Exclusions'
$ProfileNameEscaped = $ProfileName -replace ' ', '%20'

<#-- Define VPN ProfileXML --#>
$ProfileXML = '<VPNProfile>
      <RememberCredentials>true</RememberCredentials>
    <DnsSuffix>corp.contoso.com</DnsSuffix>
    <AlwaysOn>true</AlwaysOn>
    <TrustedNetworkDetection>corp.contoso.com</TrustedNetworkDetection>
<NativeProfile>
        <Servers>edge1.contoso.com</Servers>
        <RoutingPolicyType>ForceTunnel</RoutingPolicyType>
        <NativeProtocolType>IKEv2</NativeProtocolType>
        <Authentication>
            <MachineMethod>Certificate</MachineMethod>
        </Authentication>
    </NativeProfile>
    <Route>
      <Address>13.107.6.152</Address>
      <PrefixSize>31</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>13.107.18.10</Address>
      <PrefixSize>31</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>13.107.128.0</Address>
      <PrefixSize>22</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>23.103.160.0</Address>
      <PrefixSize>20</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>40.96.0.0</Address>
      <PrefixSize>13</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>40.104.0.0</Address>
      <PrefixSize>15</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>52.96.0.0</Address>
      <PrefixSize>14</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>131.253.33.215</Address>
      <PrefixSize>32</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>132.245.0.0</Address>
      <PrefixSize>16</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>150.171.32.0</Address>
      <PrefixSize>22</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>191.234.140.0</Address>
      <PrefixSize>22</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>204.79.197.215</Address>
      <PrefixSize>32</PrefixSize>
    <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>13.107.136.0</Address>
      <PrefixSize>22</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>40.108.128.0</Address>
      <PrefixSize>17</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>52.104.0.0</Address>
      <PrefixSize>14</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>104.146.128.0</Address>
      <PrefixSize>17</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>150.171.40.0</Address>
      <PrefixSize>22</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>13.107.60.1</Address>
      <PrefixSize>32</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>13.107.64.0</Address>
     <PrefixSize>18</PrefixSize>
    <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>52.112.0.0</Address>
      <PrefixSize>14</PrefixSize>
      <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Route>
      <Address>52.120.0.0</Address>
      <PrefixSize>14</PrefixSize>
    <ExclusionRoute>true</ExclusionRoute>
    </Route>
    <Proxy>
            <AutoConfigUrl>http://webproxy.corp.contoso.com/proxy.pac</AutoConfigUrl>
      </Proxy>
</VPNProfile>'

<#-- Convert ProfileXML to Escaped Format --#>
$ProfileXML = $ProfileXML -replace '<', '&lt;'
$ProfileXML = $ProfileXML -replace '>', '&gt;'
$ProfileXML = $ProfileXML -replace '"', '&quot;'

<#-- Define WMI-to-CSP Bridge Properties --#>
$nodeCSPURI = './Vendor/MSFT/VPNv2'
$namespaceName = "root\cimv2\mdm\dmmap"
$className = "MDM_VPNv2_01"

<#-- Define WMI Session --#>
$session = New-CimSession

<#-- Detect and Delete Previous VPN Profile --#>
try
{
    $deleteInstances = $session.EnumerateInstances($namespaceName, $className, $options)
    foreach ($deleteInstance in $deleteInstances)
    {
        $InstanceId = $deleteInstance.InstanceID
        if ("$InstanceId" -eq "$ProfileNameEscaped")
        {
            $session.DeleteInstance($namespaceName, $deleteInstance, $options)
            $Message = "Removed $ProfileName profile $InstanceId"
            Write-Host "$Message"
        } else {
            $Message = "Ignoring existing VPN profile $InstanceId"
            Write-Host "$Message"
        }
    }
}
catch [Exception]
{
    $Message = "Unable to remove existing outdated instance(s) of $ProfileName profile: $_"
    Write-Host "$Message"
    exit
}

<#-- Create VPN Profile --#>
try
{
    $newInstance = New-Object Microsoft.Management.Infrastructure.CimInstance $className, $namespaceName
    $property = [Microsoft.Management.Infrastructure.CimProperty]::Create("ParentID", "$nodeCSPURI", 'String', 'Key')
    $newInstance.CimInstanceProperties.Add($property)
    $property = [Microsoft.Management.Infrastructure.CimProperty]::Create("InstanceID", "$ProfileNameEscaped", 'String', 'Key')
    $newInstance.CimInstanceProperties.Add($property)
    $property = [Microsoft.Management.Infrastructure.CimProperty]::Create("ProfileXML", "$ProfileXML", 'String', 'Property')
    $newInstance.CimInstanceProperties.Add($property)

    $session.CreateInstance($namespaceName, $newInstance, $options)
    $Message = "Created $ProfileName profile."
    Write-Host "$Message"
    Write-Host "$ProfileName profile summary:"
    $session.EnumerateInstances($namespaceName, $className, $options)
}
catch [Exception]
{
    $Message = "Unable to create $ProfileName profile: $_"
    Write-Host "$Message"
    exit
}

$Message = "Script Complete"
Write-Host "$Message"

A continuación se proporciona un ejemplo de un archivo XML listo para Intune que se puede usar para crear una conexión VPN de túnel forzado con exclusiones de Microsoft 365 o consulte las instrucciones de Creación de los archivos de configuración ProfileXML para crear el archivo XML inicial.

Nota

Este XML tiene formato para su uso con Intune y no puede contener ningún retorno de carro ni espacio en blanco.

<VPNProfile><RememberCredentials>true</RememberCredentials><DnsSuffix>corp.contoso.com</DnsSuffix><AlwaysOn>true</AlwaysOn><TrustedNetworkDetection>corp.contoso.com</TrustedNetworkDetection><NativeProfile><Servers>edge1.contoso.com</Servers><RoutingPolicyType>ForceTunnel</RoutingPolicyType><NativeProtocolType>IKEv2</NativeProtocolType><Authentication><MachineMethod>Certificate</MachineMethod></Authentication></NativeProfile><Route><Address>13.107.6.152</Address><PrefixSize>31</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>13.107.18.10</Address><PrefixSize>31</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>13.107.128.0</Address><PrefixSize>22</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>23.103.160.0</Address><PrefixSize>20</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>40.96.0.0</Address><PrefixSize>13</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>40.104.0.0</Address><PrefixSize>15</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>52.96.0.0</Address><PrefixSize>14</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>131.253.33.215</Address><PrefixSize>32</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>132.245.0.0</Address><PrefixSize>16</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>150.171.32.0</Address><PrefixSize>22</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>191.234.140.0</Address><PrefixSize>22</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>204.79.197.215</Address><PrefixSize>32</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>13.107.136.0</Address><PrefixSize>22</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>40.108.128.0</Address><PrefixSize>17</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>52.104.0.0</Address><PrefixSize>14</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>104.146.128.0</Address><PrefixSize>17</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>150.171.40.0</Address><PrefixSize>22</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>13.107.60.1</Address><PrefixSize>32</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>13.107.64.0</Address><PrefixSize>18</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>52.112.0.0</Address><PrefixSize>14</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Route><Address>52.120.0.0</Address><PrefixSize>14</PrefixSize><ExclusionRoute>true</ExclusionRoute></Route><Proxy><AutoConfigUrl>http://webproxy.corp.contoso.com/proxy.pac</AutoConfigUrl></Proxy></VPNProfile>