VirtualBox: file sharing on NAT with no shared folders

Updated: April 8, 2019

I have a rather interesting problem for you. It's also quite convoluted. Say you're using VirtualBox as your preferred virtualization tool. Say you're having trouble with 3D acceleration - black screen and all that. As you've seen in my tutorial, the fix is to use repo-provided guest additions. But this repo set, as provided by the distribution, unlike the additions provided by the official ISO, does not contain a shared folder driver. This means you don't have this functionality available.

To make things even more complicated, say you want to share stuff. We talked about this in another tutorial, aptly named network & sharing, but you're using NAT rather than bridged networking, so the guest machine is not accessible from your host by any normal means. And you don't want to use Samba or alike, so the whole situation is even more complex. Okay, so let me show you how you can transfer files from host to guest without having shared folders while using NAT. No Internet tomfoolery. We're doing it all local. After me.

Teaser

Problem statement

As you can see, we have an issue where seemingly we need to make our machine more visible by bridging the network adapter, which might not be what you want, especially if you have a 'noisy' virtual machine, plus you might need to setup file sharing servers and whatnot, all of which take more than trivial amount of work. The other option is to use the VirtualBox ISO, disable 3D acceleration in this particular case - until the black screen issue goes away, but consider it the proverbial problem of any kind - and then we can use the shared folders feature.

On that topic, if you use the repo packages, then you will have most of the stuff - graphics acceleration, mouse integration, screen resizing, clipboard sharing, and then some - but not the folders. If you try to manually mount the shared folder, you'll get something like:

mount -t vboxsf <share> <mount point>
mount: unknown filesystem type 'vboxsf'

Solution: port forwarding

VirtualBox lets you configure advanced network rules for your NAT-ed machines. In essence, this is not different from how your router works when translating local IP addresses to the public-facing one, and vice versa. Indeed, VirtualBox is your router here. We've also seen this with Docker, where you can map host ports to container ports, so you effectively access your local system but you're in fact connecting to a container, or in this case, a virtual machine.

Anyway, select your virtual machine > Settings. Under Networking, for the network type NAT, expand the Advanced section toward the bottom. Then click on Port Forwarding. This will open a table where you can input the necessary details. Host IP - the IP address of the interface you want to use; you may have more than one, but the easiest solution is to just use localhost (127.0.0.1), because this will work even if your other interfaces are down, or you don't have connectivity outside your host. Host Port - will be the 'virtual' address to which you will connect. For example, for SSH, hint hint, we can map port 2222 to be the Host Port. This means if you connect to this port, you will effectively be connecting to the Guest IP at the relevant Guest Port specified in the table. Indeed, the other two fields are for the virtual machine information, much like we did with our host.

Advanced rules

Port forwarding rule

Connect with SSH

So now we have the actual connection. You may say wait, SSH is for Linux! Yes, because we have a problem in Linux. There's no black screen issue with Windows, so the 3D acceleration thingie + guest additions from the ISO will work fine. Ergo, Linux.

We can now connect from our host to guest using SSH (on port 2222). But of course, the first step is to make sure openssh-server is installed and running in the guest operating system. We also need to make sure the guest is not using a firewall that's blocking incoming connections. Now we can test what gives.

ssh -p 2222 roger@127.0.0.1
The authenticity of host '[127.0.0.1]:2222 ([127.0.0.1]:2222)' can't be established. ECDSA key fingerprint is SHA256:Eq0ow03sffLb7G49e3KNMgMrpVV/8wFfN6uicdxPnEL.
Are you sure you want to continue connecting (yes/no)?

SSH works

But this is just to test connectivity. We actually need SCP to copy files from our host into the guest. Now, here we also need to specify a custom port. But please note: SSH uses lowercase -p to specify the port, whereas SCP uses uppercase -P flag for port numbers. Go figure. So the whole thingie will be something like:

scp -P 2222 "file" roger@127.0.0.1:/home/roger/"location"/
"file"                       100% 8244KB 135.0MB/s   00:00

Sharing works, zoomed

Conclusion

I like these kind of exercises, because they can be innovative and fun - like my KVM & bridged network trick. At first glance, you may think you'll need to use bridged networking, setup Samba or NFS, or email files, which can be tedious. Instead, we work around the issue with port-forwarding and SSH, both of which are simple, non-intrusive and very easy to setup or disable if not needed.

Well then, we learned quite a lot today - about the missing features in the repo guest additions, the use of advanced networking rules and port forwarding, SSH and SCP and the subtle differences in how they use port numbers, and a few other concepts. That would be all. Remember, there's always a neat way of fixing problems, if you're willing to be patient and methodical. Take care.

Cheers.