为什么 Windows Server 2019 和 Azure 之间的站点到站点 VPN 连接突然无法路由?
Why is my Site-to-Site VPN Connection Between Windows Server 2019 and Azure suddenly not routing?
今天我们遇到了一个 st运行ge 问题,原因是我们都在远程工作时办公室意外停电。在派人重启设备后,我们办公室的互联网连接恢复了,我们可以访问一些服务,但是我们办公室网络和云之间的站点到站点 (S2S) VPN 不再运行。奇怪的是,Azure 指示 VPN 是 "Connected",并且 - 经过一些创造性的隧道 - 我能够确认 Windows 办公室中的 Server 2019 也 表示连接为 "Connected",因此这看起来像是路由问题。通过重新启动和 Windows 更新,此 VPN 已忠实地工作了 10 个月,但今天却莫名其妙地宕机了。
现在,回顾一下历史:早在 2019 年 6 月,我们就在我们位于洛杉矶的办公室和 Azure 中的资源之间建立了一个 S2S VPN。目标是开始使用 Azure 上的 Windows 虚拟桌面为远程员工虚拟桌面,同时使他们能够访问与现场员工相同的资源。那时,我们 运行 在洛杉矶的域控制器上使用以下 PowerShell 脚本来配置 Windows Server 2019 和到 Azure 的 S2S VPN:
Install-WindowsFeature Routing, RemoteAccess, RSAT-RemoteAccess-PowerShell
# Only needed if "RestartNeeded" is "Yes"
# Restart-Computer
# After the machine reboots. Launch PowerShell again to resume the configuration
Install-RemoteAccess -VpnType VpnS2S
# Setting variables
$rrasInterfaceName = "Azure (vpn-subnet-to-la)"
$azureGatewayIpAddress = "12.74.131.73"
$virtualNetworkRange = "10.3.0.0/16"
$sharedKey = "redacted-psk"
Function Invoke-WindowsApi(
[string] $dllName,
[Type] $returnType,
[string] $methodName,
[Type[]] $parameterTypes,
[Object[]] $parameters
)
{
## Begin to build the dynamic assembly
$domain = [AppDomain]::CurrentDomain
$name = New-Object Reflection.AssemblyName 'PInvokeAssembly'
$assembly = $domain.DefineDynamicAssembly($name, 'Run')
$module = $assembly.DefineDynamicModule('PInvokeModule')
$type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit")
$inputParameters = @()
for($counter = 1; $counter -le $parameterTypes.Length; $counter++)
{
$inputParameters += $parameters[$counter - 1]
}
$method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl',$returnType, $parameterTypes)
## Apply the P/Invoke constructor
$ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
$attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName
$method.SetCustomAttribute($attr)
## Create the temporary type, and invoke the method.
$realType = $type.CreateType()
$ret = $realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null, $inputParameters)
return $ret
}
Function Set-PrivateProfileString(
$file,
$category,
$key,
$value)
{
## Prepare the parameter types and parameter values for the Invoke-WindowsApi script
$parameterTypes = [string], [string], [string], [string]
$parameters = [string] $category, [string] $key, [string] $value, [string] $file
## Invoke the API
[void] (Invoke-WindowsApi "kernel32.dll" ([UInt32]) "WritePrivateProfileString" $parameterTypes $parameters)
}
# Add and configure S2S VPN interface for VNet1
Add-VpnS2SInterface -Protocol IKEv2 -AuthenticationMethod PSKOnly -ResponderAuthenticationMethod PSKOnly `
-Name $rrasInterfaceName -Destination $azureGatewayIpAddress -IPv4Subnet @("$($virtualNetworkRange):256")`
-NumberOfTries 3 -SharedSecret $sharedKey
Set-VpnServerIPsecConfiguration -EncryptionType MaximumEncryption
# default value for Windows 2012 is 100MB, which is way too small. Increase it to 32GB.
Set-VpnServerIPsecConfiguration -SADataSizeForRenegotiationKilobytes 33553408
# TODO: Confirm why this setting is needed/what it does
# Seems related to this: https://tools.ietf.org/html/draft-dukes-ikev2-config-payload-00
New-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\RemoteAccess\Parameters\IKEV2 -Name SkipConfigPayload -PropertyType DWord -Value 1 -Force
# Set S2S VPN connections to be persistent by editing the router.pbk file (required admin priveleges)note that the IdelDisconnectSeconds and RedialOnLinkFailure are set for reach adaptors.
Set-PrivateProfileString $env:windir\System32\ras\router.pbk "$($rrasInterfaceName)" "IdleDisconnectSeconds" "0"
Set-PrivateProfileString $env:windir\System32\ras\router.pbk "$($rrasInterfaceName)" "RedialOnLinkFailure" "1"
# Restart the RRAS service
Restart-Service RemoteAccess
Connect-VpnS2SInterface -Name $rrasInterfaceName
route -p ADD 10.1.0.0 MASK 255.255.0.0 10.3.0.1 IF 30
末尾的静态路由规则确保发往 10.1.Windows 虚拟桌面计算机的数据包。0.x 运行ge 通过另一端的网关路由位于 10.3.0.1 的 S2S VPN。 S2S VPN VNet 与 WVD 连接到的 VNet 对等互连。
再次强调,自 6 月设置以来,我们没有对 Azure VPN 或服务器配置进行任何更改。
路由 table 看起来像这样:
===========================================================================
Interface List
15...6c 4b 90 21 ab 9b ......Intel(R) Ethernet Connection (2) I219-LM
27...........................Azure (vpn-subnet-to-la)
1...........................Software Loopback Interface 1
===========================================================================
IPv4 Route Table
===========================================================================
Active Routes:
Network Destination Netmask Gateway Interface Metric
0.0.0.0 0.0.0.0 192.168.100.254 192.168.100.1 281
10.3.0.0 255.255.0.0 On-link 169.254.0.27 281
10.3.255.255 255.255.255.255 On-link 169.254.0.27 281
127.0.0.0 255.0.0.0 On-link 127.0.0.1 331
127.0.0.1 255.255.255.255 On-link 127.0.0.1 331
127.255.255.255 255.255.255.255 On-link 127.0.0.1 331
169.254.0.0 255.255.0.0 On-link 169.254.0.27 281
169.254.0.27 255.255.255.255 On-link 169.254.0.27 281
169.254.255.255 255.255.255.255 On-link 169.254.0.27 281
192.168.100.0 255.255.255.0 On-link 192.168.100.1 281
192.168.100.1 255.255.255.255 On-link 192.168.100.1 281
192.168.100.255 255.255.255.255 On-link 192.168.100.1 281
224.0.0.0 240.0.0.0 On-link 127.0.0.1 331
224.0.0.0 240.0.0.0 On-link 192.168.100.1 281
224.0.0.0 240.0.0.0 On-link 169.254.0.27 281
255.255.255.255 255.255.255.255 On-link 127.0.0.1 331
255.255.255.255 255.255.255.255 On-link 192.168.100.1 281
255.255.255.255 255.255.255.255 On-link 169.254.0.27 281
===========================================================================
Persistent Routes:
Network Address Netmask Gateway Address Metric
10.1.0.0 255.255.0.0 10.3.0.1 1
0.0.0.0 0.0.0.0 192.168.100.254 Default
===========================================================================
IPv6 Route Table
===========================================================================
Active Routes:
If Metric Network Destination Gateway
1 331 ::1/128 On-link
15 281 fe80::/64 On-link
15 281 fe80::6430:2788:424f:47fb/128
On-link
1 331 ff00::/8 On-link
15 281 ff00::/8 On-link
===========================================================================
Persistent Routes:
None
亮点:
- 192.168.100.1 是提供到 Azure 的 VPN 连接的域控制器。
- 192.168.100.254 是互联网路由器。
- DC 的默认网关是 192.168.100.254(因此,默认情况下,DC 通过路由器将流量路由到 Internet)。
- 网络配置为从 DC 而不是路由器获取 DHCP 租约。
- DC 配置为发布使用 DC 作为默认网关的 DHCP 租约,这样来自办公室网络其余部分的发往云的数据包通过 VPN,而发往 Internet 的数据包则通过 VPN。转发到路由器。
使用此配置,互联网流量运行良好。办公室网络上的一切都能够很好地连接到互联网。但是云无法访问本地网络上的任何内容,反之亦然。
这是服务器指示 S2S 接口状态的内容:
Get-VpnS2SInterface -Name "Azure (vpn-subnet-to-la)"
RoutingDomain Name Destination AdminStatus ConnectionState IPv4Subnet
------------- ---- ----------- ----------- --------------- ----------
- Azure (vpn-subnet... {12.74.131.73} True Connected {10.3.0.0/16:256}
这是一条跟踪路由,显示发往云的流量被错误地路由到路由器:
tracert 10.1.2.7
Tracing route to 10.1.2.7 over a maximum of 30 hops
1 <1 ms <1 ms <1 ms dsldevice.attlocal.net [192.168.100.254]
2 * * *
3 * * *
为什么 Windows 没有通过正确的接口进行路由?
似乎意外断电导致Windows重新初始化S2S接口,使其具有不同的接口ID。请注意,在我 运行 六月份的原始脚本中,接口编号是 30
。
但是,当我删除静态路由并重新添加它时,我得到:
route delete 10.1.0.0
route -p ADD 10.1.0.0 MASK 255.255.0.0 10.3.0.1 IF 30
The route addition failed: The system cannot find the file specified.
这促使我查看 route print
输出顶部的接口列表:
===========================================================================
Interface List
15...6c 4b 90 21 ab 9b ......Intel(R) Ethernet Connection (2) I219-LM
27...........................Azure (vpn-subnet-to-la)
1...........................Software Loopback Interface 1
===========================================================================
注意接口号现在是27
。所以我 运行:
route -p ADD 10.1.0.0 MASK 255.255.0.0 10.3.0.1 IF 27
OK!
现在当我 运行 跟踪路线时:
tracert 10.1.2.7
Tracing route to 10.1.2.7 over a maximum of 30 hops
1 <1 ms <1 ms <1 ms server.subdomain.mydomain.com [192.168.100.1]
2 34 ms 33 ms 35 ms 10.1.2.7
Trace complete.
今天我们遇到了一个 st运行ge 问题,原因是我们都在远程工作时办公室意外停电。在派人重启设备后,我们办公室的互联网连接恢复了,我们可以访问一些服务,但是我们办公室网络和云之间的站点到站点 (S2S) VPN 不再运行。奇怪的是,Azure 指示 VPN 是 "Connected",并且 - 经过一些创造性的隧道 - 我能够确认 Windows 办公室中的 Server 2019 也 表示连接为 "Connected",因此这看起来像是路由问题。通过重新启动和 Windows 更新,此 VPN 已忠实地工作了 10 个月,但今天却莫名其妙地宕机了。
现在,回顾一下历史:早在 2019 年 6 月,我们就在我们位于洛杉矶的办公室和 Azure 中的资源之间建立了一个 S2S VPN。目标是开始使用 Azure 上的 Windows 虚拟桌面为远程员工虚拟桌面,同时使他们能够访问与现场员工相同的资源。那时,我们 运行 在洛杉矶的域控制器上使用以下 PowerShell 脚本来配置 Windows Server 2019 和到 Azure 的 S2S VPN:
Install-WindowsFeature Routing, RemoteAccess, RSAT-RemoteAccess-PowerShell
# Only needed if "RestartNeeded" is "Yes"
# Restart-Computer
# After the machine reboots. Launch PowerShell again to resume the configuration
Install-RemoteAccess -VpnType VpnS2S
# Setting variables
$rrasInterfaceName = "Azure (vpn-subnet-to-la)"
$azureGatewayIpAddress = "12.74.131.73"
$virtualNetworkRange = "10.3.0.0/16"
$sharedKey = "redacted-psk"
Function Invoke-WindowsApi(
[string] $dllName,
[Type] $returnType,
[string] $methodName,
[Type[]] $parameterTypes,
[Object[]] $parameters
)
{
## Begin to build the dynamic assembly
$domain = [AppDomain]::CurrentDomain
$name = New-Object Reflection.AssemblyName 'PInvokeAssembly'
$assembly = $domain.DefineDynamicAssembly($name, 'Run')
$module = $assembly.DefineDynamicModule('PInvokeModule')
$type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit")
$inputParameters = @()
for($counter = 1; $counter -le $parameterTypes.Length; $counter++)
{
$inputParameters += $parameters[$counter - 1]
}
$method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl',$returnType, $parameterTypes)
## Apply the P/Invoke constructor
$ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
$attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName
$method.SetCustomAttribute($attr)
## Create the temporary type, and invoke the method.
$realType = $type.CreateType()
$ret = $realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null, $inputParameters)
return $ret
}
Function Set-PrivateProfileString(
$file,
$category,
$key,
$value)
{
## Prepare the parameter types and parameter values for the Invoke-WindowsApi script
$parameterTypes = [string], [string], [string], [string]
$parameters = [string] $category, [string] $key, [string] $value, [string] $file
## Invoke the API
[void] (Invoke-WindowsApi "kernel32.dll" ([UInt32]) "WritePrivateProfileString" $parameterTypes $parameters)
}
# Add and configure S2S VPN interface for VNet1
Add-VpnS2SInterface -Protocol IKEv2 -AuthenticationMethod PSKOnly -ResponderAuthenticationMethod PSKOnly `
-Name $rrasInterfaceName -Destination $azureGatewayIpAddress -IPv4Subnet @("$($virtualNetworkRange):256")`
-NumberOfTries 3 -SharedSecret $sharedKey
Set-VpnServerIPsecConfiguration -EncryptionType MaximumEncryption
# default value for Windows 2012 is 100MB, which is way too small. Increase it to 32GB.
Set-VpnServerIPsecConfiguration -SADataSizeForRenegotiationKilobytes 33553408
# TODO: Confirm why this setting is needed/what it does
# Seems related to this: https://tools.ietf.org/html/draft-dukes-ikev2-config-payload-00
New-ItemProperty -Path HKLM:\System\CurrentControlSet\Services\RemoteAccess\Parameters\IKEV2 -Name SkipConfigPayload -PropertyType DWord -Value 1 -Force
# Set S2S VPN connections to be persistent by editing the router.pbk file (required admin priveleges)note that the IdelDisconnectSeconds and RedialOnLinkFailure are set for reach adaptors.
Set-PrivateProfileString $env:windir\System32\ras\router.pbk "$($rrasInterfaceName)" "IdleDisconnectSeconds" "0"
Set-PrivateProfileString $env:windir\System32\ras\router.pbk "$($rrasInterfaceName)" "RedialOnLinkFailure" "1"
# Restart the RRAS service
Restart-Service RemoteAccess
Connect-VpnS2SInterface -Name $rrasInterfaceName
route -p ADD 10.1.0.0 MASK 255.255.0.0 10.3.0.1 IF 30
末尾的静态路由规则确保发往 10.1.Windows 虚拟桌面计算机的数据包。0.x 运行ge 通过另一端的网关路由位于 10.3.0.1 的 S2S VPN。 S2S VPN VNet 与 WVD 连接到的 VNet 对等互连。
再次强调,自 6 月设置以来,我们没有对 Azure VPN 或服务器配置进行任何更改。
路由 table 看起来像这样:
===========================================================================
Interface List
15...6c 4b 90 21 ab 9b ......Intel(R) Ethernet Connection (2) I219-LM
27...........................Azure (vpn-subnet-to-la)
1...........................Software Loopback Interface 1
===========================================================================
IPv4 Route Table
===========================================================================
Active Routes:
Network Destination Netmask Gateway Interface Metric
0.0.0.0 0.0.0.0 192.168.100.254 192.168.100.1 281
10.3.0.0 255.255.0.0 On-link 169.254.0.27 281
10.3.255.255 255.255.255.255 On-link 169.254.0.27 281
127.0.0.0 255.0.0.0 On-link 127.0.0.1 331
127.0.0.1 255.255.255.255 On-link 127.0.0.1 331
127.255.255.255 255.255.255.255 On-link 127.0.0.1 331
169.254.0.0 255.255.0.0 On-link 169.254.0.27 281
169.254.0.27 255.255.255.255 On-link 169.254.0.27 281
169.254.255.255 255.255.255.255 On-link 169.254.0.27 281
192.168.100.0 255.255.255.0 On-link 192.168.100.1 281
192.168.100.1 255.255.255.255 On-link 192.168.100.1 281
192.168.100.255 255.255.255.255 On-link 192.168.100.1 281
224.0.0.0 240.0.0.0 On-link 127.0.0.1 331
224.0.0.0 240.0.0.0 On-link 192.168.100.1 281
224.0.0.0 240.0.0.0 On-link 169.254.0.27 281
255.255.255.255 255.255.255.255 On-link 127.0.0.1 331
255.255.255.255 255.255.255.255 On-link 192.168.100.1 281
255.255.255.255 255.255.255.255 On-link 169.254.0.27 281
===========================================================================
Persistent Routes:
Network Address Netmask Gateway Address Metric
10.1.0.0 255.255.0.0 10.3.0.1 1
0.0.0.0 0.0.0.0 192.168.100.254 Default
===========================================================================
IPv6 Route Table
===========================================================================
Active Routes:
If Metric Network Destination Gateway
1 331 ::1/128 On-link
15 281 fe80::/64 On-link
15 281 fe80::6430:2788:424f:47fb/128
On-link
1 331 ff00::/8 On-link
15 281 ff00::/8 On-link
===========================================================================
Persistent Routes:
None
亮点:
- 192.168.100.1 是提供到 Azure 的 VPN 连接的域控制器。
- 192.168.100.254 是互联网路由器。
- DC 的默认网关是 192.168.100.254(因此,默认情况下,DC 通过路由器将流量路由到 Internet)。
- 网络配置为从 DC 而不是路由器获取 DHCP 租约。
- DC 配置为发布使用 DC 作为默认网关的 DHCP 租约,这样来自办公室网络其余部分的发往云的数据包通过 VPN,而发往 Internet 的数据包则通过 VPN。转发到路由器。
使用此配置,互联网流量运行良好。办公室网络上的一切都能够很好地连接到互联网。但是云无法访问本地网络上的任何内容,反之亦然。
这是服务器指示 S2S 接口状态的内容:
Get-VpnS2SInterface -Name "Azure (vpn-subnet-to-la)"
RoutingDomain Name Destination AdminStatus ConnectionState IPv4Subnet
------------- ---- ----------- ----------- --------------- ----------
- Azure (vpn-subnet... {12.74.131.73} True Connected {10.3.0.0/16:256}
这是一条跟踪路由,显示发往云的流量被错误地路由到路由器:
tracert 10.1.2.7
Tracing route to 10.1.2.7 over a maximum of 30 hops
1 <1 ms <1 ms <1 ms dsldevice.attlocal.net [192.168.100.254]
2 * * *
3 * * *
为什么 Windows 没有通过正确的接口进行路由?
似乎意外断电导致Windows重新初始化S2S接口,使其具有不同的接口ID。请注意,在我 运行 六月份的原始脚本中,接口编号是 30
。
但是,当我删除静态路由并重新添加它时,我得到:
route delete 10.1.0.0
route -p ADD 10.1.0.0 MASK 255.255.0.0 10.3.0.1 IF 30
The route addition failed: The system cannot find the file specified.
这促使我查看 route print
输出顶部的接口列表:
===========================================================================
Interface List
15...6c 4b 90 21 ab 9b ......Intel(R) Ethernet Connection (2) I219-LM
27...........................Azure (vpn-subnet-to-la)
1...........................Software Loopback Interface 1
===========================================================================
注意接口号现在是27
。所以我 运行:
route -p ADD 10.1.0.0 MASK 255.255.0.0 10.3.0.1 IF 27
OK!
现在当我 运行 跟踪路线时:
tracert 10.1.2.7
Tracing route to 10.1.2.7 over a maximum of 30 hops
1 <1 ms <1 ms <1 ms server.subdomain.mydomain.com [192.168.100.1]
2 34 ms 33 ms 35 ms 10.1.2.7
Trace complete.