How to access your virtual machine from the internet with OpenVPN

Rob
5 min readJun 21, 2021

During my pentest engagements, I sometimes get remote code execution (RCE) on a server. Depending on the type of engagement, sometimes this might be enough for the client, but other times they might ask for post exploitation too. For cases like this, I’ve relied on a droplet (VPS) hosted on Digital Ocean to transfer files across and get my shells going. This runs into a few problems, mostly related to costs. A VPS with kali and its toolset can become somewhat expensive. My previous solution was to have a debian distro with the kali repos and just use what I need, which worked fine for the most part, but I kept wanting to have access to my full kali box on my PC. Since I started working fully remote, I like working from various places, so the option of a fixed business IP is not really feasible. Thus this project.

To achieve this goal, I’m using my Digital Ocean droplet as a proxy with openvpn. Traffic sent to the public droplet IP will be forwarded to the kali box and the responses from the kali box will be sent across the droplet as well. Since the droplet just needs to act as a proxy/VPN server, you can run it on the cheapest cloud option available as performance is not an issue. The process is surprisingly short and simple if you’re familiar with IP tables, but it still took me about a week to figure it out. So, to save you this time, here’s how you can do it too.

The Virtual Machine:

Running it in bridged mode will make management easier. If you are using VMware, just change it from the VM settings:

The Router

This is fairly simple. Go to your router config, locate your kali VM, which should have its own IP since it’s a bridged network, and forward UDP port 1194:

The cloud server

I used digital ocean. You can use any VPS provider you like, I liked digital ocean’s options the most so if you decide on them as well, consider using my referral link: https://m.do.co/c/ec356af64a15 .

I’ll start by rebuilding my droplet so we can have a clean state. I’ll be using a Debain 10 image:

Once you get your shell on the VPS, we begin by using the amazing script made by the people at pivpn: https://www.pivpn.io/

curl -L https://install.pivpn.io | bash

For interface, select eth0:

You might have to create a new user for openvpn. I created a new user named “kali”.

Setup a password and continue on.

We’ll be using OpenVPN for our purpose:

Select no:

I personally like using the google DNS server:

Just keep pressing enter after this point until you get to the server reboot. Reboot when asked.

Reconnect to the box and generate an .ovpn file for your kali box:

pivpn add nopassEnter a Name for the Client: kaliHow many days should the certificate last? 1080

From your kali VM, copy over the .ovpn file:

scp -i id_rsa root@138.xxx.xxx.xxx:/home/kali/ovpns/kali.ovpn .

Let’s run a quick test before we move on:

sudo openvpn kali.ovpncurl ip.me

At this point you should be seeing your droplet IP. Congratulations, you have now rolled out your own VPN service!

But that’s not why we’re here. Return to the droplet/VPS, and flush the IP Tables options.

flush iptables:

iptables -F

Now for the crucial part, the iptables rules that make the NAT work. In this particular case, we want to make a webserver hosted on kali on port 8000 accessible from the web:

iptables -t nat -A PREROUTING -d 138.xxx.xxx.xxx -p tcp — dport 8000 -j DNAT — to-dest 10.8.0.2:8000iptables -t nat -A POSTROUTING -d 10.8.0.2 -p tcp — dport 8000 -j SNAT — to-source 138.xxx.xxx.1

138.xxx.xxx.xxx is the droplet IP. If you don’t have any other clients on the openvpn network, 10.8.0.2 should be your VM IP.

That’s it!

You can now return to the kali box, reconnect to the .ovpn file and run a python server on port 8000:

We can now visit the VPS IP and get access to our kali webserver:

You can redo the above IP tables rule for any other port you want.

If you’d like to forward all ports, you can use those rules:

iptables -t nat -A PREROUTING -d 138.xxx.xxx.xxx -p tcp -j DNAT — to-dest 10.8.0.2iptables -t nat -A POSTROUTING -d 10.8.0.2 -p tcp -j SNAT — to-source 138.xxx.xxx.1

WARNING: if you don’t have another way of managing your VPS, you will be unable to ssh into it from outside the openvpn network if you apply those rules. You can, however, SSH from inside it:

ssh -i id_rsa root@10.8.0.1

That is it. You should now have a VM accessible from the internet, with a fixed public IP. If you would like for those rules to persist across restarts, save them in /etc/iptables/rules.v4 .

--

--

Rob

Penetration tester, tinkerer, developer and AI enthusiast.