我想使用Windows VPN,但仅限于特定网络,因此它不会占用我的整个网络连接。
例如,不要将VPN变为默认路由,而是将其设置为192.168.123.0/24的路由
(我可以看到Ubuntu 在这个问题上有一个解决方案,但有时我也必须在Windows上这样做)
这可以自动化,这样每当我连接到VPN时它会这样做吗?
我想使用Windows VPN,但仅限于特定网络,因此它不会占用我的整个网络连接。
例如,不要将VPN变为默认路由,而是将其设置为192.168.123.0/24的路由
(我可以看到Ubuntu 在这个问题上有一个解决方案,但有时我也必须在Windows上这样做)
这可以自动化,这样每当我连接到VPN时它会这样做吗?
Answers:
您可以通过转到VPN,Networking
选项卡,Internet Protocol (TCP/IP)
属性Advanced
和取消选项的属性来关闭接管整个连接Use default gateway on remote network
。192.168.123.0/24
根据VPN服务器的设置,这可能会也可能不会留下路由。如果没有,您每次都必须手动添加路由,尽管您可以将其放在批处理文件中。
要手动添加路由,请运行(以管理员身份):
route -p add 192.168.0.12 mask 255.255.255.255 10.100.100.254
此示例将192.168.0.12
通过VPN网关建立持久性(无需在重新启动后运行命令)到IP的路由10.100.100.254
。
有关此内容的更多信息,请访问http://technet.microsoft.com/en-us/library/bb878117.aspx
虽然这个答案并不反映您的要求,但我专门为此目的使用了一个VM。这样,只有VM内的网络才受到路由的限制。
您可能会找到其他人更好的答案,但至少这可能会给您一些考虑因素,因为它是创建VM后的一个简单解决方案。
我发现它需要在route命令中直接指向接口。没有它,Windows将使用主网卡接口,而不是VPN。就我而言,它看起来像
route -p add 192.168.10.187 mask 255.255.255.255 0.0.0.0 IF 26
:: ^destination ^mask ^gateway ^interface
注意'IF 26'。
在Windows 8+中使用Add-VpnConnectionRoute cmdlet。
Add-VpnConnectionRoute -ConnectionName 'My VPN Connection' -DestinationPrefix 192.168.123.0/24
如果您使用CMAK并设置客户端可以下载的路由文件... Windows将下载路由文件并根据需要调整路由。有一些选项可以删除默认路由...并添加各种静态路由等。这被称为分裂隧道btw。
这里有一个很好的方法:http://blogs.technet.com/b/rrasblog/archive/2007/06/11/split-tunnelling-using-cmak.aspx
我想在混合中添加我的解决方案。它运行在Windows 7或更高版本上的Cygwin驱动的UNIX shell上,但也应该在构建14986或Windows的Busybox之后与MSYS2,Bash-on-Windows [WSL]一起使用。需要使用管理员权限运行。
它有一些设置,并试图检测一些你没有明确设置的东西。它还明确设置接口编号(IF)以解决某些用户(像我一样)在这里遇到的其他解决方案的一些问题。
#!/bin/sh
# these three settings are required
adapter_name='VPN Connection'
username=
password=
# This setting here might be important because it's about the target network
# and in some cases it can't be properly determined automatically so this might
# be then worth setting.
# Format is in CIDR notation with the network address and a forward slash and
# the amount of network bits
target_network=192.168.0.0/24
# the IP you will get on the target network, also the VPN gateway on your
# local machine, you normally don't need to set this as the script tries to
# detect it
ip=
# optional setting for metric which normally shouldn't be necessary,
# except in te very rare cases where it should be set to a value lower than all
# other routes that might match the target network
metric=
# experimental setting to delete routes to the target network prior and after
# should normally not be needed unless this script fails and you get error
# messages like 'The route addition failed: The object already exists.'
route_cleanup=F
prog_name=${0##*/}
msg() {
printf '%s: %s\n' "$prog_name" "$*"
}
die() {
msg "$*" >&2
exit 1
}
[ "$adapter_name" ] || die "Adapter name not set!"
[ "$username" ] || die "Username not set!"
[ "$password" ] || die "Password not set!"
if [ "$(uname -o)" != 'MS/Windows' ]; then
id -G | grep -qE '\<0|544\>' || die 'Not running with admin rights.'
fi
msg "Disconnecting any existing connection that might exist."
rasdial.exe "$adapter_name" /d
msg "Connecting"
rasdial.exe "$adapter_name" "$username" "$password"
if [ ! "$ip" ]; then
msg "Getting IP address on target network."
ip=$(netsh.exe interface ip show config name="$adapter_name" |
grep -a 'IP Address' | awk -F'[: ]+' '{print $4}')
[ "$ip" ] || die 'Could not get IP! Exiting.'
msg "Detected IP address as '$ip'."
fi
if [ ! "$target_network" ]; then
msg "Getting target network."
target_network=$(netsh.exe interface ip show config name="$adapter_name" |
grep -a 'Subnet Prefix' | awk -F'[: ]+' '{print $4}')
[ "$target_network" ] || die 'Could not get target network! Exiting.'
msg "Detected target network as '$target_network'."
fi
msg "Getting VPN interface number."
if=$(ROUTE.EXE print -4 | grep -a "$adapter_name" |
awk -F. '{gsub(" ", "");print $1}')
[ "$if" ] || die 'Could not get interface number! Exiting.'
msg "Detected VPN interface number as '$if'."
if [ "$route_cleanup" = T ]; then
msg "Deleting any potentially already existing routes for the target network."
ROUTE.EXE delete "$target_network"
fi
msg "Adding route for target network."
if [ "$metric" ]; then
ROUTE.EXE add "$target_network" "$ip" IF "$if" Metric "$metric"
else
ROUTE.EXE add "$target_network" "$ip" IF "$if"
fi
msg "VPN should be up now."
msg "Press enter to make it stop."
read -r _
if [ "$route_cleanup" = T ]; then
msg "Deleting route."
ROUTE.EXE delete "$target_network"
fi
msg "Disconnecting."
rasdial.exe "$adapter_name" /d
# msg "Press enter to exit."
# read -r _
exit 0
还值得注意的是,可能需要手动设置低度量标准,否则默认路由将在发往VPN的流量之前匹配。您可以通过转到适配器设置来执行此操作,在该设置中打开VPN适配器的“...属性”菜单项→ “网络”选项卡→ “Internet协议版本4(TCP / IP)”属性→ “高级” →然后取消选中在“自动度量”(除复选框“使用默认网关......”当然),并在其值设置“界面指标:”字段设置为大于默认路由(见低的值ROUTE.EXE -4 print
输出)。
你可以使用像netcatcher这样的东西 - 只需添加你需要的所有路线并忘掉它。当您连接或断开VPN会话时,它将自动添加和删除路由。如果您的VPN IP地址是动态获取的(DHCP),netcatcher将捕获它并以正确的方式更新路由。
来自俄罗斯论坛:http://forum.ixbt.com/topic.cgi?id = 14:43549
保存为文件(例如:vpn_route.vbs)和vpn连接执行命令之后
cscript vpn_route.vbs
vpn_route.vbs:
strComputer = "."
strMACAddress = "MAC of VPN interface here (example 00:45:55:00:00:00)"
strTarget = "route target here (example 192.168.123.0)"
strMask = "mask here (example 255.255.255.0)"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
("Select * From Win32_NetworkAdapterConfiguration Where MACAddress = '" & strMACAddress & "'")
For Each objItem in colItems
strIP = objItem.IPAddress(0)
Next
Set objShell = CreateObject("WScript.Shell")
objShell.Run "route add " & strTarget & " mask " & strMask & " " & strIP
如果不使用其他程序,批处理文件或命令行,则无法在Windows中执行此操作。另一种方法是获得可以运行VPN的虚拟(或物理)机器。
似乎很奇怪,像这样容易解释的东西很难实现。将流量从一个程序路由到VPN接口以及将所有其他程序路由到默认NIC接口有多难?为什么我们需要为此设置一个完整的虚拟机?使用Linux它是可能的,但它的解决方案也不是很优雅。
它也非常受欢迎:我在同一主题上遇到过几十个主题。所以我只希望有人意识到这种荒谬,并为此做点什么。(在Windows 8中!)
此解决方案来自未归因的批处理文件。它略有改编。
Windows 7的说明
该脚本将通过您的VPN连接和路由流量,直到重新启动-你可以替换route add
使用route -p add
的变化持续下去,但如果你没有持久的IP与你的VPN,它最终会停止工作时,你的VPN的IP变化。
Networking
选项卡Properties
Advanced
Use default gateway[...]
您需要在脚本中替换以下内容:
<VPN>
使用您创建的VPN连接的名称<USER>
使用VPN用户名<PASS>
使用VPN密码<TARGET>
使用您希望通过VPN路由的IP地址(如果要路由更多地址,只需复制使用目标的三条线路)注意:如果你不想在文件中保存密码,更换<PASS>
与%password%
和脚本的第一行后增加以下内容:set password= Input password:
。
脚本
@echo off
@echo make sure to be disconnected!
rasdial <VPN> /d
@echo start to connect to vpn
rasdial <VPN> <USER> <PASS>
netsh interface ip show config name="<VPN>" | findstr "IP" > ip.dat
set /p ip= < ip.dat
del ip.dat
set ip=%ip:~-12%
@echo VPN IP is %ip%
set target=<TARGET>
@echo Add route for %target%
route add %target% mask 255.255.255.255 %ip%
timeout /T 3 > nul
像我这样的新手的“简短”指南,他们对网络知之甚少。这里没什么新内容,但是前面的答案和其他相关主题中描述的所有好选项的摘要。整个过程包括3个基本步骤:
1)使所有流量不通过VPN。为此,您必须取消Use default gateway on remote network
选中VPN设置中的复选框。确保取消选中IPv4和IPv6的此复选框。通常我只是完全禁用VPN协议进行VPN连接。
(!)(有时)取消选中该复选框对于正常工作是足够的 - 根据我的经验,在建立VPN连接后,可以自动添加必要的路由(这将通过VPN引导必要的流量)。我不知道这些规则的确切位置和方式,但这种情况仍然存在 - 可能是VPN网络管理员所做的一些魔术。
2)只通过VPN进行必要的流量。为此,您需要定义路线。这里有3个选项:
2.1)通过VPN网关添加永久路由:
route -p add a.b.c.d/<CIDR> w.x.y.z
要么 route -p add a.b.c.d mask e.f.g.h w.x.y.z
其中'VPN网关'='您在VPN网络上的IP'= w.x.y.z
和目标地址/网络= a.b.c.d
。您可以w.x.y.z
通过执行ipconfig
和查找您的VPN连接名称来查找,或者,如果您使用PowerShell,您可以通过执行来获得紧凑的输出ipconfig | grep -A5 PPP
(在找到每个PPP连接后将输出5行)。
缺点:如果您的VPN IP将发生变化,您将不得不重新创建路由。
2.2)通过VPN网络接口添加永久路由:
route -p add a.b.c.d/<CIDR> 0.0.0.0 IF <interface number>
a.b.c.d
目标地址/网络在哪里,是interface number
VPN连接的标识符。可以通过执行来找到此ID netstat -rn
,或者,对于更紧凑的输出,可以找到该ID netstat -rn | grep -A10 'Interface List'
。
优点:如果您的VPN地址(w.x.y.z
)发生变化,则无需更改任何内容。
缺点:如果删除VPN连接,则需要使用新ID重新创建路由。
2.3)使用PowerShell cmdlet:
Add-VpnConnectionRoute -ConnectionName '<VPN connection name>' -DestinationPrefix a.b.c.d/<CIDR>
优点:每次建立VPN连接时都会添加必要的路由,并在每次断开连接时删除。
缺点:没有Get-VpnConnectionRoutes
cmdlet,因此很难管理这些规则。
3)检查并确保路由按预期工作!
如果添加了持久路由,则可以通过执行来检查它们netstat -rn | grep -A10 'Persistent Routes'
。
最后,tracert
对两个应该通过VPN访问的IP地址和那些应该在没有VPN的情况下工作的IP地址运行一些命令。