0) The situation
A Linux (VirtualBox) VM connects to a VPN and this connection should be usable by the host machine (that runs the VM) or other machines on the local network for that matter. For security reasons, the Linux VM should not be a full member on the local network, which means that it cannot reach anything and cannot be reached on the LAN. This type of topology is the default mode selected when configuring a VM with VirtualBox: the “NAT” (Network Address Translation) network mode.
1) Network Set-up
Once the VM is up and running, we setup the VPN in your Linux VM in order to connect to a remote network. The procedure is generally explained in the VPN setup documentation. As a result, the Linux VB will have two active network interfaces, it’s “dual homed”. The local network connection goes via VirtalBox to our physical network and the adapter is generally named eth0 when listed on Linux. The remote network is reached via the VPN connection. In most of the cases, the network device is named tap0 in Linux. A “tap” is a device, in this case a pure software device, that allows to access a data flow on a “line”.
To visualise our configuration and to obtain our two IP addresses, which we need later, we use the ifconfig command:
root@ATREIDES:~/Desktop# ifconfig eth0 Link encap:Ethernet HWaddr 08:00:27:8b:fe:b9 inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe8b:feb9/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:7586 errors:0 dropped:0 overruns:0 frame:0 TX packets:2842 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:2483822 (2.3 MiB) TX bytes:752406 (734.7 KiB) : tap0 Link encap:Ethernet HWaddr 26:7b:33:1e:de:e6 inet addr:10.11.0.99 Bcast:10.11.255.255 Mask:255.255.0.0 inet6 addr: fe80::247b:33ff:fe1e:dee6/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:4092 errors:0 dropped:243 overruns:0 frame:0 TX packets:339 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:326311 (318.6 KiB) TX bytes:42434 (41.4 KiB)
In the example above, our local network is located at 10.0.2.0/24. /24 indicates a network mask of 24 bit or “255.255.255.xxx”, which covers the range 10.0.2.0 to 10.0.2.255. The VPN is placed at 10.11.0.0/16 respectively.
Opening a SSH shell remotely against the Linux VM automatically gives access to all networks of the target box. We just need to allow our host host to reach our VM and we use the VirtualBox configuration to achieve this:
– In the VB VM Settings, “Network” -> “Adapter N (in NAT mode)” -> “Port Forwarding” -> Add “ssh, TCP, Host Port 10022, Guest Port 22”.
– In the Linux VM, the SSH daemon must be started:
$> service ssh start
– And on the host (OS X or Linux), we simply connect with:
$> ssh user@localhost -p 10022
Note: In case of Windows, 3rd party tools like Putty are required.
From a security point of view, we would like to limit the SSH access to our host and local network, and blocking SSH connections coming from the VPN. The easiest way to make this happen is to use the Linux TCP wrapper files. We start with the “hosts.allow” file and add our local subnet knowning that our “eth0” address is 10.0.2.xxx.
root@ATREIDES~$ nano /etc/hosts.allow # /etc/hosts.allow: list of hosts that are allowed to access the system. # See the manual pages hosts_access(5) and hosts_options(5). : sshd: 10.0.2.0/255.255.255.0
Next, we do “the contrary” by adding “the rest” of the IP space to the SSH blacklist. Please note that we specify the service name to limit this setting to SSH.
root@ATREIDES~$ nano /etc/hosts.deny # /etc/hosts.deny: list of hosts that are _not_ allowed to access the system. # See the manual pages hosts_access(5) and hosts_options(5). : sshd: ALL
So, login and enjoy :)
In order to access web servers on the remote network (and the Internet, if the box is online), our Linux VM hast to operate as HTTP proxy. Additionally, we need to add another Port Forwarding to expose our VM ports to the host.
– In the VB VM Settings, “Network” -> “Adapter N (in NAT mode)” -> “Port Forwarding” -> Add “webproxy, TCP, Host Port 3128, Guest Port 3128”. (Restart of the VM is not needed).
– Next, we install Squid in the Linux VM (http://www.squid-cache.org). We need to configure our proxy to allow usage from our local network only and not via the attached VPN. As the IP rages of our networks are known (see above), we modify the squid configuration accordingly.
root@ATREIDES~$ apt-get install squid root@ATREIDES~$ nano /etc/squid/squid.conf
In the configuration file, we locate the ACL section that should look like this:
: # TAG: acl # Defining an Access List : acl localnet src 10.0.0.0/8 # RFC1918 possible internal network acl localnet src 172.16.0.0/12 # RFC1918 possible internal network acl localnet src 192.168.0.0/16 # RFC1918 possible internal network :
Below these lines, we add the definition of your networks:
acl mylocalnet src 10.0.2.0/24 # my own local network acl notmylocalnet src 0.0.0.0/0.0.0.0
Now, we need to update the permission section to assign rights to the just defined network ranges. Let’s find the place first:
: # TAG: http_access # Allowing or Denying access based on defined access lists : # Example rule allowing access from your local networks. # Adapt localnet in the ACL section to list your (internal) IP networks # from where browsing should be allowed #http_access allow localnet http_access allow localhost # And finally deny all other access to this proxy http_access deny all :
So, here comes the important part: the following lines must be added AFTER “http_access allow localhost”, BUT BEFORE “http_access deny all”. The order is mandatory and failing this can mess up our proxy security settings.
http_access allow mylocalnet http_access deny notmylocalnet
Unto saving the configuration file, we (re)start the service:
root@ATREIDES~$ service squid restart # or root@ATREIDES~$ service squid start
The proxy up and running, we have to configure our browser to use the proxy VM to access web sites. This is simple in Firefox as the tool allows a manual configuration of the proxy. Chrome(ium) is a bit more tricky. The browser uses the system settings – which we obviously do not want to touch. A bit of command line magic can help us here. For OSX, this would look like this:
natasha@MACGYVER:$ cd /Applications/Google Chrome.app/Contents/MacOS natasha@MACGYVER:$ ./Google\ Chrome --proxy-server="127.0.0.1:3128"
Squid has access to all networks of the VM, so the local internet connection as well as the VPN can be reached.
4) Helpful Notes
Since the VM bridges to a (VPN) network located in another universe, it’s recommended to activate a firewall like “ufw”. We can also keep an eye on the open ports and connections:
# Lists all open ports: root@ATREIDES ~$ netstat -lntup root@ATREIDES ~$ lsof -i ---> We can also see the Squid ports: : squid 3405 proxy 6u IPv4 14762 0t0 UDP *:33663 # Management - restricted to locahost squid 3405 proxy 13u IPv4 14769 0t0 TCP *:3128 (LISTEN) # Proxy listening :
The Squid log files are of course useful as well:
root@ATREIDES~$ cd /var/log/squid root@ATREIDES~$ ls -l -rw-r----- 1 proxy proxy 96253 Sep 16 11:24 access.log -rw-r----- 1 proxy proxy 11174 Sep 16 10:57 cache.log -rw-r----- 1 proxy proxy 97581 Sep 16 11:24 store.log root@ATREIDES~$ tail -f access.log : 1474016471.426 240966 10.0.2.2 TCP_MISS/200 8688 CONNECT pagead2.googlesyndication.com:443 - DIRECT/220.127.116.11 - 1474016471.426 240129 10.0.2.2 TCP_MISS/200 6613 CONNECT clients1.google.com:443 - DIRECT/18.104.22.168 - 1474016471.426 237423 10.0.2.2 TCP_MISS/200 168095 CONNECT www.google.com:443 - DIRECT/22.214.171.124 - 1474016471.428 40591 10.0.2.2 TCP_MISS/200 5094 CONNECT apis.google.com:443 - DIRECT/126.96.36.199 - :
To conclude, a note on the VirtualBox network configuration.
Having the VM network mode set to “NAT” isolates the system from the local network, except when port forwarding is configured (which we did above). For the same reason, the VM can only be reached by the host operating system. While this is the safest bet and most of the time a good solution, we could choose other interesting options:
1) Setting the VM network mode to “Bridge” places the machine as full member of the local network (no NAT by VB anymore). The VM receives an IP in the same way the host does, on the same subnet. This has to be used with care, obviously.
2) It’s also possible to build an isolated “virtual network” for a specific subset of VMs. This is handy when wanting to share the proxy with other VMs, but without having these VMs exposed on the local network. First, we have to define a logical network by name. This is made in the VirtualBox preferences: “File” -> “Preferences” -> “Network” -> Button “Adds new NAT network”. We specify our favorite name and close the window. Next, we open the settings of all VMs that we wish to have participating in the party. Each time, we set the network adapter mode to “NAT Network” (instead of “NAT”), selecting your favorite name. Et zou…