Return to

Running a VM as a router for the host. Is this possible? I feel it should be possible

Hi. I was hoping for some help - just confirmation it’s possible and pointing in the right direction would be a good start.

I have VPN connection (OpenVPN) on a GNU/Linux VM running on a Windows host. The VM is in Hyper-V. I usually connect to it via RDP. I want to be able to share its VPN connection with the host. Specifically some SSH connections but also web-browsing for certain domains. I’d rather not put the host on the VPN for a few reasons (not least of which I’ve had bad experiences of OpenVPN on Windows).

My theory would be that I create two virtual network ports on this VM and then share one of them. And then somehow tell the Windows host to route certain traffic through that VM. The VM being on the VPN (this part already works), I should then be able to connect to the sites and machines via the VM from the host.

Is this possible? Is this sensible? I’ve searched but it’s hard to wade through all the blog posts talking about sharing a laptop’s WiFi connection. The VM currently connects to the outside world via the host’s ethernet port but directly to the router where it gets its own IP address; rather than using NAT on the host.

Any advice is much appreciated. I have a rare bit of free time today and am hoping to figure this out.

You can create a bridge interface on Windows host and add the physical interface as well as one router VM interface.

You can set the gateway on the router VM to your home router/gateway, and you can set your Windows host gateway to your router VM IP.

That way all Windows IP traffic for the internet will go through the router VM, that can then decide what to send to your modem/router internet, and what to send through the VPN connection

Thanks for the reply. It’s not possible to have traffic going out of the physical ethernet port from both the VM and the host with the host’s not going through the VM? If so, that would explain why I’m having so much trouble figuring out how to do that!

To make sure I understand, can you just confirm that the below is NOT possible?


If I understand what you’re saying I can’t have two connections to the router over a single physical ethernet port. I have to have my VM between ALL traffic to and from the router?

EDIT: I know this may be frustratingly basic for some here but it’s much appreciated. Most articles on sharing connections are the same copy-pasted How-To on sharing a WiFi connection over and over.

There are two ways to do this.

Way 1:

Create two vSwitches. The first switch will be an external switch. Don’t specify allowing the mgmt os to share the network adaptor. The second switch is an internal switch (a switch between VMs and the host). Configure the VM to have two nics, one assigned to each vswitch. Configure addresses for them, the nic in the external vSwitch might get a DHCP address. The nic in the internal vSwitch will need to have an address configured. In windows you’ll see a nic assigned to the internal vswitch, configure this address to be the same in the same network as the VM. Lastly, you’ll need to set a static route in your router pointing to the VM so it knows about the network the Windows box is on. Like if between Windows and the VM you created the network and the external address on the VM is Configure a route to the network on your router pointing to

This is what we’ve just built:
W10 <-Internal vSwitch-> OpenVPN VM <-External vSwitch+Phy adaptor-> Internet

This is a monolithic approach that forces all traffic to flow through the VM. You can then specify which traffic you want to be encrypted and which just flows through. It’s not a bad approach, there are some downfalls to it though.

The second way of doing this is to just create a single external vSwitch, but allow the mgmt os to share the adaptor (probably already done this). What you then do is configure specific routes in Windows to flow to the OpenVPN VM. Like if all traffic to needs to go over the OpenVPN tunnel, configure a route in Windows like this:

route ADD MASK

This is what way 2 builds:

VM <--->|
(External vSwitch)

Way 2 makes it a bit harder to choose what traffic goes over the tunnel since it’s based on networks and wouldn’t be able to be dynamic (like if you wanted all facebook traffic to go over the tunnel, you’d have to set routes for every single facebook network, pretty terrible since they have tons of networks).

I’d do way 1 if you can. I’m sure there are other ways to accomplish this, but I’ve done both of these ways before and they work well for what I needed them to do.

1 Like

Yes it is. It’s just packets and frames.

Local network traffic doesn’t go through the gateway. You could play with routing tables on windows to pick out what traffic should go where, but it’s much easier to do on Linux

If you want local network access to be direct from the host, you can get away with one vswitch … Otherwise you need two - so that you have a local network between host and VM, and another one for VM, and physical interface with host not even having tcp configured there.

Usually folks only want internet traffic through the VM, so vswitch is enough

1 Like

Thanks to all for the responses. I’ll be honest, I can code great but networking I struggle with for some reason. Perhaps because I keep trying to do non-standard things, who knows? Every reply was part of the process of making this click for me but I marked xradeon’s as a solution because I think that’s what finally got it through my skull.

Despite the recommendation of Way 1 being better, I think that’s because you have an expectation I’ll need to keep editing those routes. But in fact once I’ve set up a few specific company sites I should be done. So Way 2 looks like it will be the most straightforward.

I have to ask though, as my motherboard has two ethernet ports would this all be simpler if I just bought another ethernet cable and used both? Because I’m plenty willing to spend £10 to make this headache go away! :wink:

Add long as you can make e.g. a list of IPs or IP ranges, then you could theoretically get by only with Windows. You could even encode that list in the OpenVPN config, and have OpenVPN setup your windows routes for those couple of IPs when it establishes the tunnel.

In Linux you can be a lot more flexible because you can, if you want to, have multiple routing tables and have the firewall determine/mark what packet goes to which table, that then has routing rules same as the archetypical big iron router would have. Some people call this policy based routing. The firewall can look at port numbers or source IPs, or sets of IPs populated by dnsmasq, or for when you don’t want to maintain the IPs manually for things that are served from a gazillion IPs… one can get really creative with these Anyway…

No it won’t make vswitch easier. $10 (or even £10) spent on an extra cable won’t make you a network admin overnight.

Now that you’ve clarified you want only a couple of IPs to go through the tunnel, and most traffic should work as normal, just set up 1 vswitch. Have your windows, the physical cable, and the VM on it. Let your VM get a local IP address and let your network think that your VM is just another computer you plugged in to the via a dumb switch (ie the vswitch). Then tell Windows too send all your internet traffic to the VM, and let the VM sort out what to send through the OpenVPN tunnel and what to send besides the tunnel unencapsulated to your local router and to regular Ethernet. You’ll need to tell the VM to nat outgoing connections, (and probably port forward almost everything from the VM to the windows host), otherwise some stuff might freak out due to this thing called “reverse path filtering” which is a primitive form of network spoofing protection).

Speaking of traffic policies, openwrt has an x86 build that’s possible to run on regular pc hardware or in a vm, and you can install OpenVPN and mwan3 on it to control what traffic goes where through the webui Uses very little ram because it still uses all lightweight versions of system libraries that let it fit on tiny 32 or 64MB of ram home routers. 128MB of ram VM is super overkill :slight_smile: needs waaay less resources than Debian/Ubuntu server editions, which use waaaay less resources than their desktop editions.

1 Like

Years of complaining upper management think they can just throw money at an engineering problem, and what’s the first thing I do when I face my own black box? :slight_smile: Well, anything that will help me get past this block so I can work… Can’t blame me for exploring options…

This sounds like a great solution. I don’t have hardware to hand for this right now (unless I installed it on my laptop and if you think 128MB is super overkill…). but I’ve been meaning to look into a custom home router system so this might be a good option…

FWIW, I’ve made big progress on this. I have my regular traffic going through it now but haven’t figured out how to get DNS served from the VM, yet. Which means DNS requests still go to the actual really real router. Which isn’t a problem necessarily but I still have to work out how to get requests for things on the VPN to go through the VM router. Names don’t resolve because they’re internal (they only resolve from within the VM) and I’m not sure that would help me anyway because whilst I have the IP addresses, they don’t want to go through the router. I’ve added routes on the host for the ip addresses to the VM router but they’re timing out at the moment. I think I need to add some forwarding in the VM so more research. Appreciate you guys getting me started on this - just knowing what was the right approach helped with researching the how to.