It is a good idea to be careful when deploying an unknown virtual machine created by someone else. We should not allow it access to the Internet or our local network. In this article I will describe the steps I take to achieve this.
My virtualisation platform of choice is VirtualBox - it is simple to set up, easy to use, and open source. VirtualBox supports importing machines using the Open Virtualization Format (OVF). VirtualBox offers an 'Internal Network' which is completely isolated from the host network environment. We shall connect any unknown virtual machines to this internal network.
Now the problem is how we can connect to virtual machines in this isolated network, without opening up access to our local network and/or the Internet. We can solve this by setting up a virtual machine to act as a gateway. This gateway will have 2 NICs; one connected to the internal network and the other connected to our LAN through VirtualBox Bridged Adapter mode.
To control access to the Internet we will use some clever routing tricks and set up a VPN.
First follow the instructions available here to setup OpenVPN:
The guide is quite long and detailed, covering setting up OpenVPN service, TLS authentication, and client configuration. I used iptables rather than ufw for firewall configuration:
# apt-get install iptables-persistent
Answer yes when prompted to save current IPv4 and IPv6 configurations. Edit the file /etc/iptables/rules.v4, adding in the content below starting from "*nat" until the first instance of "COMMIT":
*nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING -s 10.8.0.0/24 -o enp0s3 -j MASQUERADE COMMIT # Generated by xtables-save v1.8.2 on Fri Dec 25 18:36:19 2020 *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] COMMIT # Completed on Fri Dec 25 18:36:19 2020
The masquerade command tells the firewall to replace the source address of outgoing packets from the 10.8.0.0/24 subnet with the server's own IP address, so that return packets will have a path back.
Check IP forwarding is enabled in the kernal (see step 6 in the linked article):
# /usr/sbin/sysctl -p net.ipv4.ip_forward = 1
We should now have a working OpenVPN server, and connected clients will be able to access the Internet and LAN resources, while clients on the internal network will be completely isolated.
To connect a (linux) client:
# /usr/sbin/openvpn --config client1.ovpn &
To disconnect, end the openvpn process:
# pkill -SIGTERM openvpn
See the troubleshooting section in case the connected client cannot access the Internet.
Acessing the internal network from the VPN client
Now that VPN clients can and access one another, as well as the Internet, one thing remains. We want to be able to access clients connected to the Internal network, while at the same time prevent the same clients from accessing our network. We can do this in a similar way to how we allowed VPN clients on the 10.8.0.0/24 subnet external access - masquerading.
To achieve this goal, we need to think about address on the Internal network as if they are external addresses, and masquerade traffic leaving via the Internal network interface. Add a line in the nat section, under the similar from before to /etc/iptables/rules.v4
-A POSTROUTING -s 10.8.0.0/24 -o enp0s8 -j MASQUERADE
It is almost the same command, except the destination changes to the Internal network. The iptables should look something like this:
/usr/sbin/iptables -t nat -L -v -n Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 1432 packets, 447K bytes) pkts bytes target prot opt in out source destination 83 6113 MASQUERADE all -- * enp0s3 10.8.0.0/24 0.0.0.0/0 2 112 MASQUERADE all -- * enp0s8 10.8.0.0/24 0.0.0.0/0 Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
The client machine will need to add an entry into it's routing table to direct traffic intended for the Internal network correctly. For example, on a windows box (assuming the VPN interface was assigned the IP 10.8.0.10):
route add 192.168.240.0 mask 255.255.255.0 10.8.0.10
This provides a path the subnet which would otherwise be unreachable, and that should be all you need.
VirtualBox Internal Network does not offer IPv4 address
I found the new internal network I created did not have a working DHCP server to assign IP addresses to clients. I needed to configure the DHCP server by running VBoxManage on the host:
$ VBoxManage list dhcpservers
$ VBoxManage dhcpserver add --netname hackernet --ip 192.168.240.100 --netmask 255.255.255.0 --lowerip 192.168.240.101 --upperip 192.168.240.254 --enable
I found I needed to restart the VirtualBox Manager GUI for the settings to take effect.
Bridged mode adapter does not acquire IPv4 address on startup
I could't find the reason bridged mode adapters were not acquring an IP address, as a workaround I ran ifup/down after boot:
# /usr/sbin/ifdown enp0s3
# /usr/sbin/ifup enp0s3
If you know of a solution, please let me know in the comments section.
OpenVPN client cannot access Internet - unable to redirect default gateway
This error can happen if a client machine did not have a default gateway already configured prior to connecting to the vpn server. OpenVPN does not know how to reroute external packets if there is no default route configured. This a likely to happen on a machine connected to the VirtualBox internal network.
A possible solution would be to configure the default route manually after connecting to the openvpn server:
$ ip route 10.8.0.1 via 10.8.0.5 dev tun0 10.8.0.5 dev tun0 proto kernel scope link src 10.8.0.6 192.168.240.0/24 dev enp0s3 proto kernel scope link src 192.168.240.102
Manually add route (replicate the line "via X dev tun0", replacing 10.8.0.1 with default)
# ip route add default via 10.8.0.5 dev tun0
Updated routing table:
$ ip route default via 10.8.0.5 dev tun0 10.8.0.1 via 10.8.0.5 dev tun0 10.8.0.5 dev tun0 proto kernel scope link src 10.8.0.6 192.168.240.0/24 dev enp0s3 proto kernel scope link src 192.168.240.102
Another option could be to add a dummy default route (eg. to 127.0.0.1) prior to connecting the the vpn server. See https://unix.stackexchange.com/questions/308751/can-openvpn-create-the-default-route-if-it-doesnt-exist for more information.
Comprehensive guide to VirtualBox networking configurations:
Good guide to NAT with iptables:
Superuser.com question - how to forward packets from one network interface to another: