How to receive reverse shells and expose services to the Internet on QubesOS

Everyone is an atheist until they’re waiting for a reverse shell to connect back - Sun Tzu QubesOS is amazing for security, and equally amazing at making CTFs 10x harder than they need to be. It’s the firewall’s fault.

Exposing a service to the Internet

Don’t. Please.

Firstly, you don’t need to open it using your own IP address. You can use Cloudflare Tunnels or ngrok, which will work out of the box. This is the best way to expose something if you need to.

If you dare, you can expose your service to the Internet directly from your IP address, but you will need to configure your AppVM, sys-firewall, and sys-net, AND you’re almost certainly stuck behind CGNAT because NO ONE has their own IPv4 address nowadays unless they own a datacenter. (Do you own a datacenter? I want to know you). This means you will NOT be able to expose your service even if your system is technically configured to do so. That’s just how CGNAT works; it’s not a QubesOS issue.

If you want to do it anyway, go here.

Receiving reverse shells behind VPN in QubesOS (HTB, TryHackMe, etc.)

  1. Connect to the VPN using your .ovpn config file (usually provided by the platform)
sudo openvpn <file_here>.ovpn
  1. Use the following command in the AppVM you are using to receive the shell to allow incoming connections in your firewall:
sudo nft add rule ip qubes input iif "tun0" accept

Note: tun0 is the default VPN interface, but verify this with ip addr show

This opens the firewall to allow inbound traffic from your VPN tunnel (tun0). Without this, your netcat listener (or any other listener) won’t hear a thing.

  1. Try getting a reverse shell again:
 $ nc -lvnp 8080
listening on [any] 8080 ...
^C
 $ sudo nft add rule ip qubes input iif "tun0" accept
 $ nc -lvnp 8080
listening on [any] 8080 ...
connect to [10.10.17.10] from (UNKNOWN) [10.129.66.139] 51092