引言
有一台L2TP协议的VPN服务器,这个服务器无法连接外网,只能连接特定的内网服务器,而且网段还与VPN服务器所在的网段不同,因此需要在连接VPN完成之后,自动追加相应的路由条目。这个需求在Linux下,操作起来还不算难,有各种各样的方案。但在Windows10上面,我还真花了一定的时间去研究并最终找到一个比较满意的解决方案,这里记录一下。
原理
Windows自带的VPN客户端,并没有设定连接之后设置路由的地方,远程VPN服务器也没有在完成连接之后推送路由信息,因此,只能在客户端这边编写自动化脚本。
要么,在脚本之中直接调用VPN连接指命,然后检测正常连接之后,再调用路由条目添加指令完成路由添加。
要么,监听Windows网络配置变更事件,事件发生之后,调用特定的Powershell脚本,检测目标VPN是否完成连接,连接完成之后,添加路由条目。
上面两种方案,都需要使用到Powershell编程,方案二,需要还使用计划调度程序。
不过经过一段时间的使用,方案一,门槛相对来说更高一些,需要掌握好几条API的使用,并且脚本也不方便管理。方案二,则近乎完美解决问题。
还有,windows10,其实没有完整的VPN方案,微软把VPN的能力基本都放在Server版本中,在Windows10中那个传入连接(使用RAS服务来实现),只能简单地实现连接进入本地,但无法实现SNAT,导致无法连接到本地网络,这个问题,我折腾了很久,最后没有找到解决方案,放弃了,使用softether vpn来解决。
自动化
第一步:设置正常连接的VPN信息
在设置->网络与Internet->VPN,这个菜单中设置好可以正常连接的VPN信息,如我的。
![](https://life.xiezhifeng.cn/wp-content/uploads/2024/07/image.png)
第二步:编译自动添加路由条目的脚本
在C:\Tools\AddRoute.ps1
,写入如下的代码,文件可以按每个人的喜欢保存好。
$vpnName = "dellsoft"
$vpnGateway = "192.168.60.1"
$routeDestination = "192.168.20.128"
$routeMask = "255.255.255.192"
# 检查 VPN 是否已连接
$vpnStatus = Get-VpnConnection -Name $vpnName | Select-Object -ExpandProperty ConnectionStatus
if ($vpnStatus -eq "Connected") {
# 添加路由
$routeAddCommand = "route add $routeDestination mask $routeMask $vpnGateway"
Invoke-Expression $routeAddCommand
}
$vpnName = "ten_vpn"
$vpnGateway = "192.168.42.10"
# 定义要添加的路由列表
$routesToAdd = @(
"route add 192.168.20.128 mask 255.255.255.192 $vpnGateway",
"route add 10.4.18.0 mask 255.255.255.0 $vpnGateway"
"route add 192.168.3.46 mask 255.255.255.255 $vpnGateway"
)
# 检查 VPN 是否已连接
$vpnStatus = Get-VpnConnection -Name $vpnName | Select-Object -ExpandProperty ConnectionStatus
if ($vpnStatus -eq "Connected") {
# 循环遍历路由数组并执行每条命令
foreach ($route in $routesToAdd) {
# Write-Host $route
Invoke-Expression $route
}
}
代码中,第一段,主要是设置一条路由用的,第二段,主要是设置多条路由用的,而且这个脚本可以集成多个vpn的个性化路由条目。
vpnName这个变量,说明了这两段代码,分别对应两个不同的VPN连接。
第三步:使用任务计划程序创建一个任务,当 VPN 连接成功时运行 PowerShell 脚本。
在计算机管理->系统工具->任务计划程序,创建任务。
- 在“常规”选项卡中,设置任务的名称,例如 Add Route for dellvpn。 勾选“使用最高权限运行”。 勾选“隐藏”。
![](https://life.xiezhifeng.cn/wp-content/uploads/2024/07/image-1.png)
- 在“触发器”选项卡中,点击“新建”,然后设置触发器为“在事件日志中创建事件”,配置如下:
日志:Microsoft-Windows-NetworkProfile/Operational
源:NetworkProfile
事件ID:10000(连接)和10001(断开)
![](https://life.xiezhifeng.cn/wp-content/uploads/2024/07/image-2.png)
![](https://life.xiezhifeng.cn/wp-content/uploads/2024/07/image-4.png)
- 在“操作”选项卡中,点击“新建”,然后配置操作为“启动程序”,并设置如下:
程序/脚本:powershell.exe
添加参数(可选):-NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Scripts\AddRoute.ps1"
参数说明:
-NoProfile:
这个参数用于启动PowerShell时不加载任何配置文件,包括用户的配置文件和系统配置文件。这样做可以确保脚本在执行时不会受到配置文件中设置的影响,特别是在需要执行特定任务而不想被现有配置干扰时。
-WindowStyle Hidden:
这个参数用于设置PowerShell窗口的样式为隐藏。当脚本不需要交互式输入,或者你不希望用户看到脚本执行时的窗口时,可以使用这个参数。脚本仍然会在后台运行,但不会有任何可见的窗口。
-ExecutionPolicy Bypass:
这个参数用于绕过执行策略。执行策略是PowerShell用来限制脚本执行的一种安全机制。默认情况下,PowerShell可能不允许执行未经签名的脚本。使用-ExecutionPolicy Bypass可以忽略这些限制,允许脚本执行,但这可能会带来安全风险,因为它允许执行任何脚本,无论它们是否被签名。
-NonInteractive
不产生交互界面
第四步:完成计划配置
关掉电源生效,还有其他选项则根据需要勾选,最后点确定。
![](https://life.xiezhifeng.cn/wp-content/uploads/2024/07/image-5.png)
测试
连接其中一个VPN,并在powershell或者cmd中输入以下命令,查看所设置的路由是否在路由表中。
route print -4
总结
任务计划程序,在windows真的是一个很好的工具。