Programmatic Internet Connection Sharing



I have a Windows VM that can has an internet connection that acts as a tunnel into a VPN, and this VM is supposed to share this internet connection with the host. This works perfectly in principle: On that Windows VM, I have a network interface named Outbound which represents the VPN connection, and an interface named Gateway which represents the connection that is shared with the host. I use Windows Internet Connection Sharing (ICS) to provide routing to the Gateway interface via Outbound. For reasons unknown to me, however, this sometimes just breaks and the only way to get it running again is to simply disable ICS on the Outbound interface and re-enable it. Doing this through the UI every time became annoying, so I researched how to do it programmatically. There is [a great superuser answer](https://superuser.com/a/649183/222330) which provides _almost_ all the details you need, but not quite. Here's my current PowerShell code, which just does what I want:
 regsvr32 /s hnetcfg.dll

 $net = New-Object -ComObject HNetCfg.HNetShare

 $net.EnumEveryConnection |% {
    $net.INetSharingConfigurationForINetConnection($_).DisableSharing()
 }

 $out = $net.EnumEveryConnection |? {$net.NetConnectionProps($_).Name -eq "Outbound"}
 $outConfig = $net.INetSharingConfigurationForINetConnection($out)

 $net = $net.EnumEveryConnection |? {$net.NetConnectionProps($_).Name -eq "Gateway"}
 $netConfig = $net.INetSharingConfigurationForINetConnection($net)
 
 $outConfig.EnableSharing(0)
 $netConfig.EnableSharing(1)
Specifically, the use of the EnableSharing method had alluded me for a while: If you want to provide routing to one _specific_ interface (i.e. Gateway in my case) then you have to call EnableSharing(1) on that interface while calling EnableSharing(0) on the one that provides the connection to be shared. One could argue that this makes sense in isolation since you can then have a many-to-many relationship between interfaces providing connectivity and interfaces being routed, but it is very confusing when compared to the user interface for this feature, where you can always only select a single interface to be routed for any connection that is to be shared. I found tons and tons of already existing code that does this, or even more, but I only found them after knowing all the right keywords. So, I am writing this blog post to add another piece of content out there, hoping that some pour soul with a similar problem may find it sooner than the rest. Cheers!

Leave a Reply

Your email address will not be published. Required fields are marked *