My VMs were unable to access the VPN that the host was connected to. Seems rather simple... well here's the story.
- I have a number of guest VMs running Ubuntu on a Windows host
- These guest VMs used bridged network adapters with static IPs
- The Window host uses the OpenVPN Client to connect to a VPN
- The VPN endpoint is an OpenVPC server running in Amazon VPC
- The OpenVPC server is running Layer 3 NAT mode
- The Amazon VPC contains a bunch of other servers that I need to connect to
- The Amazon VPC is on a different subnet than my home subnet
The setup looks something like this:
With this setup I was unable to access the VPC servers from my VMs. Now I would imagine there are a variety of ways to solve this. I'm sure I could have configured a VPN connection through a hacked router. Or manually added routes to route tables on the VMs and host. But... seeing how I'm not much of a networking guy, I just messed about with network adapters and found a solution!
Bridged network adapters mean that the VM will use their own address on the host's network. This is great if you want to directly connect to the VM via a unique IP on the host's network.
Another network adapter setting is NAT. With NAT, the VM runs inside a VM specific subnet. The connections are then routed through the host and share the same IP as the host. Connecting to the VM from the host's network requires configuring port forwarding, not exactly ideal. The nice thing about NAT is that the host's routes are used. Interesting...
With this knowledge, I changed the VM to use NAT and attempted to hit the VPC, it worked! While running a NAT'd adapter, running
route shows the following in the routes table:
Destination Gateway Genmask Flags Metric Ref Use Iface default 192.168.111.2 0.0.0.0 UG 100 0 0 eth1 192.168.111.0 * 255.255.255.0 U 0 0 0 eth1
This is all good, however, the VM no longer had a static IP and I was limited to port forwarding. That's no good. So how about a hybrid solution?
The solution I came up with was to add a second network adapter to the VM. The first adapter would be Bridged to allow the static IP to work and would act as the primary gateway. The second adapter would be NAT to allow routing through the OpenVPN Client's network adapter for the VPN network. All you need is a static route after adding the second adatper.
After the adapters were configured, I changed /etc/network/interfaces in Ubuntu accordingly. With previous knowledge of the NAT'd gateway at 192.168.111.2 we can configure this route.
sudo vim /etc/network/interfaces
# Primary network interface (BRIDGED) auto eth0 iface eth0 inet static address 192.168.0.100 netmask 255.255.255.0 gateway 192.168.0.1 dns-nameservers 18.104.22.168 # Secondary network interface (NAT) auto eth1 iface eth1 inet dhcp up route add -net 10.0.10.0 gw 192.168.111.2 netmask 255.255.255.0 eth1
With this configuration, the VM is routing VPN traffic through the secondary NAT adapter. The static adapter will still be able to receive network traffic on its unique IP and route traffic as usual! Problem solved.
The route table ends up looking like this:
Destination Gateway Genmask Flags Metric Ref Use Iface default 192.168.0.1 0.0.0.0 UG 100 0 0 eth0 10.0.10.0 192.168.111.2 255.255.255.0 UG 0 0 0 eth1 192.168.0.0 * 255.255.255.0 U 0 0 0 eth0 192.168.111.0 * 255.255.255.0 U 0 0 0 eth1