When running a small test sandbox using Hyper-V, the default switch is an ideal “quick and dirty” solution to provide hosted VM internet access (shared with the local workstation). Such configuration is extremely helpful for developers and testers, who can just run few VMs on their desktop or laptop. Of cause, a fully blown corporate environment shouldn’t use default switches, but have internal/external Hyper-V stitches and routers.
So, what does make the default switch so special? When it’s created, the default switch type is set to “Internal”. But there is a hidden trick. On the top of bare function of an internal switch, Hyper-V adds an invisible DHCP server and a NAT translation, which together allow hosted VM connect to the Internet. How that works? The local machine also has a virtual network interface, which connects to the same default switch. If take look at this NIC properties, it will be seen, that its IP v4 properties are set to use a static address. An assumption here: if this is static, it will not change. This is WRONG. Hyper-V may randomly change this IP at next boot or physical network connection change.
Is this a problem? If using DHCP for hosted virtual machines, then not. Actually this static IP changes because Hyper-V chose different IP range for the hidden DHCP, to match the new DHCP range. Why the range changes? To avoid conflicts with the current connection’s range. The range is being reconfigured each boot or physical connection change.
But is this a problem, when VMs are configured to use static IP addresses? Indeed, YES! This is not because only HDCP changes, but the hidden NAT changes as well. So, it stops natting the previous range, and hosted VMs lose their access to the Internet.
So how to fix this? This is pretty simple. First, the current range should be discovered. ‘Get-HnsNetwork‘ PowerShell command helps here. Just run it without parameters to get all host compute networks. NB! There are might be multiple of them if using dockers or containers. Hyper-V owned network will have its gateway IP address set to the same value, as configured on the host virtual NIC (the one, which connects host machine to the virtual switch). Or, simply look at the SwitchName property — where it is set to “Default Switch”.
ActivityId : <RANDOM-GUID>
AdditionalParams :
CurrentEndpointCount : 0
Extensions : {@{Id=E7C3B2F0-F3C5-48DF-AF2B-10FED6D72E7A; IsEnabled=False; Name=Microsoft Windows Filtering Platform}, @{Id=E9B59CFA-2BE1-4B21-828F-B6FBDBDDC017; IsEnabled=False;
Name=Microsoft Azure VFP Switch Extension}, @{Id=EA24CD6C-D17A-4348-9190-09F0D5BE83DD; IsEnabled=False; Name=Microsoft NDIS Capture}}
Flags : 11
GatewayMac : XX-XX-XX-XX-XX-XX
Health : @{AddressNotificationMissedCount=0; AddressNotificationSequenceNumber=7; DNSCacheNotificationMissedCount=0; DNSCacheNotificationSequenceNumber=0;
DNSNotificationMissedCount=0; DNSNotificationSequenceNumber=0; InterfaceNotificationMissedCount=0; InterfaceNotificationSequenceNumber=0; LastErrorCode=0;
LastUpdateTime=132414154124103875; RouteNotificationMissedCount=0; RouteNotificationSequenceNumber=0}
ID : <RANDOM-GUID>
IPv6 : False
LayeredOn : <RANDOM-GUID>
MacPools : {@{EndMacAddress=XX-XX-XX-XX-XX-XX; StartMacAddress=XX-XX-XX-XX-XX-XX}}
MaxConcurrentEndpoints : 0
Name : Default Switch
NatName : ICS<RANDOM-GUID>
Policies : {}
State : 1
Subnets : {@{AdditionalParams=; AddressPrefix=192.168.222.96/28; Flags=0; GatewayAddress=192.168.222.97; Health=; ID=<RANDOM-GUID>;
Policies=System.Object[]; State=0}}
SwitchGuid : <RANDOM-GUID>
SwitchName : Default Switch
TotalEndpoints : 0
Type : ICS
Version : 42949672963
Resources : @{AdditionalParams=; AllocationOrder=2; Allocators=System.Object[]; CompartmentOperationTime=0; Flags=0; Health=; ID=<RANDOM-GUID>;
PortOperationTime=0; State=1; SwitchOperationTime=0; VfpOperationTime=0; parentId=<RANDOM-GUID>}
Look at the “Subnet” property. It has the default GW address, which is assigned to the host machine, and the range, which can be used for hosted VMs. All is needed, is just to reconfigure all hosted VMs to be withing the new range and use the new default gateway.
FIXED!
But wait! Why re-configuring hosted VMs, isn’t it better to reconfigure the compute network? Yes, it would be much efficient to re-configure the network. Unfortunately, I didn’t manage to do this. Network re-configuration is certainly possible, but not en easy task at the moment: the HostNetworkingService PowerShell module provides “Get-” command, but not “Set-“. Using the API directly is not trivial task as well, so I preferred to reconfigure VMs.
Additional readings:
- Host Compute Network (HCN) service API: https://docs.microsoft.com/en-us/windows-server/networking/technologies/hcn/hcn-top
- Windows container networking: https://docs.microsoft.com/en-us/virtualization/windowscontainers/container-networking/architecture
- hcsshim, Microsoft library, written in Go to use in Windows Container oriented products: https://github.com/microsoft/hcsshim