宿主机上运行完好的内部系统,虚拟机却始终访问不到;而且宿主机是通过一个掌握路由表的客户端联网的。把虚拟适配器桥接到隧道上看似直截了当,却会因为两个彼此独立的原因失败。真正可行的是在双方共有的网段上做地址转换。代价是真实的:每个客机都不再拥有自己在企业网中的独立身份。

网桥无法成立的两个原因

客户端的适配器通常只带一个地址,往往是 /32,而客户端会改写宿主机的路由,让普通出站流量优先走隧道。宿主机上的应用遵守这张表,因此能到达内部系统。桥接后的客机根本不读这张表,因为它的帧是通过 IP 层以下的交换机发出的。

把隧道适配器放进网桥,理论上能解决路径问题,但驱动不会接受。Windows 10 也只允许一个网桥设备,并且不提供让工作站可在两个子网之间转发所需的路由角色。剩下的办法是源地址转换。让客机的流量看起来来自宿主机,宿主机自身的路由决策就会把它送进隧道,客机也无须拥有一条它根本拿不到的路由。

创建由宿主机拥有的网段

在虚拟网络编辑器中,添加一个仅主机网络,例如在别处都不做路由的前缀上建立 VMnet3,比如 172.28.90.0/24。宿主机会在该适配器上取 172.28.90.1,客机接入同一台交换机。在该网段上关闭虚拟机管理程序的 DHCP,让地址服务只有一个来源。

在往上搭建任何东西之前,先确认 Windows 能看到该接口,因为整套设计都依赖这个适配器是普通适配器:

Get-NetAdapter | Format-Table Name, InterfaceDescription, Status
Get-NetIPAddress -AddressFamily IPv4 | Where-Object PrefixLength -eq 24

仅主机适配器在那里和任何物理适配器一样出现。与隧道适配器的区别恰恰在此:后者无法接上任何东西。

转换客机的前缀

打开提权的会话并转换前缀。先检查已经存在什么,因为容器运行时和虚拟机管理程序会安装各自的转换规则,删错会弄坏另一个产品。

Get-NetNat | Format-Table Name, InternalIPInterfaceAddressPrefix, Active
New-NetNat -Name "LabGuestEgress" -InternalIPInterfaceAddressPrefix 172.28.90.0/24

然后把客机配置成该前缀下的静态地址,网关填 172.28.90.1,DNS 填隧道交给宿主机的解析地址。地址转换只转发数据包,并不会告诉客机任何 DNS 信息,所以留在本地路由器上的客机会解析公网名字,却在每个内部名字上失败。

先查第一跳,再谈代价

先测试最近的边界然后再测具体应用。跟踪在宿主机网关处停住,说明转换没有发生;跟踪越过宿主机才停住,说明隧道已断,或对端拒绝了转换后的地址。

tracert -d 172.20.31.10
nslookup intranet.corp.example
Get-NetNatSession -NatName "LabGuestEgress"

在隧道正常时,与宿主机自身访问同一目标的结果作对比。若宿主机成功而客机失败,问题在地址转换或客机的网关设置上,而不在连接本身。

然后接受这笔交换。企业系统现在对所有客机只看到一个地址,因此设备证书和逐设备的合规检查无法区分它们,有些策略干脆禁止这种做法。还要决定隧道断开时的丢弃行为:若不把该前缀在宿主机防火墙上封死,转换后的流量可能落回普通上网路径。

相关文章