Bridging VPN to Local Network with a Linux VirtualBox Proxy

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.

2) SSH

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 :)

3) HTTP/S

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/74.125.128.157 -
1474016471.426 240129 10.0.2.2 TCP_MISS/200 6613 CONNECT clients1.google.com:443 - DIRECT/173.194.65.113 -
1474016471.426 237423 10.0.2.2 TCP_MISS/200 168095 CONNECT www.google.com:443 - DIRECT/74.125.232.244 -
1474016471.428  40591 10.0.2.2 TCP_MISS/200 5094 CONNECT apis.google.com:443 - DIRECT/173.194.65.139 -
:

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…

Leave a Reply

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